Merge "Extract the drawing logic from StartingSurfaceDrawer."
diff --git a/Android.bp b/Android.bp
index cd55dcf..c0a2abb 100644
--- a/Android.bp
+++ b/Android.bp
@@ -205,7 +205,7 @@
"android.hardware.contexthub-V1.0-java",
"android.hardware.contexthub-V1.1-java",
"android.hardware.contexthub-V1.2-java",
- "android.hardware.contexthub-V1-java",
+ "android.hardware.contexthub-V2-java",
"android.hardware.gnss-V1.0-java",
"android.hardware.gnss-V2.1-java",
"android.hardware.health-V1.0-java-constants",
diff --git a/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java b/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
index 652c49a..0c65b99 100644
--- a/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
+++ b/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
@@ -17,7 +17,9 @@
package android.app;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.app.job.IJobScheduler;
+import android.app.job.IUserVisibleJobObserver;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.app.job.JobSnapshot;
@@ -141,4 +143,28 @@
return null;
}
}
+
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
+ @Override
+ public void registerUserVisibleJobObserver(@NonNull IUserVisibleJobObserver observer) {
+ // TODO(255767350): implement
+ }
+
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
+ @Override
+ public void unregisterUserVisibleJobObserver(@NonNull IUserVisibleJobObserver observer) {
+ // TODO(255767350): implement
+ }
+
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
+ @Override
+ public void stopUserVisibleJobsForUser(@NonNull String packageName, int userId) {
+ // TODO(255767350): implement
+ }
}
diff --git a/apex/jobscheduler/framework/java/android/app/job/IUserVisibleJobObserver.aidl b/apex/jobscheduler/framework/java/android/app/job/IUserVisibleJobObserver.aidl
new file mode 100644
index 0000000..f65a47d
--- /dev/null
+++ b/apex/jobscheduler/framework/java/android/app/job/IUserVisibleJobObserver.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.app.job;
+
+import android.app.job.UserVisibleJobSummary;
+
+/**
+ * IPC protocol to know about user-visible job activity.
+ *
+ * @hide
+ */
+oneway interface IUserVisibleJobObserver {
+ /**
+ * Notify the client of all changes to a user-visible jobs' state.
+ * @param summary A token/summary that uniquely identifies and details a single running job
+ * @param isRunning whether the job is currently running or not
+ */
+ void onUserVisibleJobStateChanged(in UserVisibleJobSummary summary, boolean isRunning);
+}
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
index 76f71a2..13b6652 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
@@ -283,4 +283,32 @@
*/
@SuppressWarnings("HiddenAbstractMethod")
public abstract List<JobSnapshot> getAllJobSnapshots();
-}
\ No newline at end of file
+
+ /**
+ * @hide
+ */
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
+ @SuppressWarnings("HiddenAbstractMethod")
+ public abstract void registerUserVisibleJobObserver(@NonNull IUserVisibleJobObserver observer);
+
+ /**
+ * @hide
+ */
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
+ @SuppressWarnings("HiddenAbstractMethod")
+ public abstract void unregisterUserVisibleJobObserver(
+ @NonNull IUserVisibleJobObserver observer);
+
+ /**
+ * @hide
+ */
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
+ @SuppressWarnings("HiddenAbstractMethod")
+ public abstract void stopUserVisibleJobsForUser(@NonNull String packageName, int userId);
+}
diff --git a/apex/jobscheduler/framework/java/android/app/job/UserVisibleJobSummary.aidl b/apex/jobscheduler/framework/java/android/app/job/UserVisibleJobSummary.aidl
new file mode 100644
index 0000000..5160b42
--- /dev/null
+++ b/apex/jobscheduler/framework/java/android/app/job/UserVisibleJobSummary.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.app.job;
+
+parcelable UserVisibleJobSummary;
diff --git a/apex/jobscheduler/framework/java/android/app/job/UserVisibleJobSummary.java b/apex/jobscheduler/framework/java/android/app/job/UserVisibleJobSummary.java
new file mode 100644
index 0000000..afcbe7d
--- /dev/null
+++ b/apex/jobscheduler/framework/java/android/app/job/UserVisibleJobSummary.java
@@ -0,0 +1,122 @@
+/*
+ * 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.app.job;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Summary of a scheduled job that the user is meant to be aware of.
+ *
+ * @hide
+ */
+public class UserVisibleJobSummary implements Parcelable {
+ private final int mCallingUid;
+ private final int mSourceUserId;
+ @NonNull
+ private final String mSourcePackageName;
+ private final int mJobId;
+
+ public UserVisibleJobSummary(int callingUid, int sourceUserId,
+ @NonNull String sourcePackageName, int jobId) {
+ mCallingUid = callingUid;
+ mSourceUserId = sourceUserId;
+ mSourcePackageName = sourcePackageName;
+ mJobId = jobId;
+ }
+
+ protected UserVisibleJobSummary(Parcel in) {
+ mCallingUid = in.readInt();
+ mSourceUserId = in.readInt();
+ mSourcePackageName = in.readString();
+ mJobId = in.readInt();
+ }
+
+ public int getCallingUid() {
+ return mCallingUid;
+ }
+
+ public int getJobId() {
+ return mJobId;
+ }
+
+ public int getSourceUserId() {
+ return mSourceUserId;
+ }
+
+ public String getSourcePackageName() {
+ return mSourcePackageName;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof UserVisibleJobSummary)) return false;
+ UserVisibleJobSummary that = (UserVisibleJobSummary) o;
+ return mCallingUid == that.mCallingUid
+ && mSourceUserId == that.mSourceUserId
+ && mSourcePackageName.equals(that.mSourcePackageName)
+ && mJobId == that.mJobId;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 0;
+ result = 31 * result + mCallingUid;
+ result = 31 * result + mSourceUserId;
+ result = 31 * result + mSourcePackageName.hashCode();
+ result = 31 * result + mJobId;
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "UserVisibleJobSummary{"
+ + "callingUid=" + mCallingUid
+ + ", sourceUserId=" + mSourceUserId
+ + ", sourcePackageName='" + mSourcePackageName + "'"
+ + ", jobId=" + mJobId
+ + "}";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mCallingUid);
+ dest.writeInt(mSourceUserId);
+ dest.writeString(mSourcePackageName);
+ dest.writeInt(mJobId);
+ }
+
+ public static final Creator<UserVisibleJobSummary> CREATOR =
+ new Creator<UserVisibleJobSummary>() {
+ @Override
+ public UserVisibleJobSummary createFromParcel(Parcel in) {
+ return new UserVisibleJobSummary(in);
+ }
+
+ @Override
+ public UserVisibleJobSummary[] newArray(int size) {
+ return new UserVisibleJobSummary[size];
+ }
+ };
+}
diff --git a/core/api/current.txt b/core/api/current.txt
index f550952..614c4c3 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -1261,6 +1261,7 @@
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
+ field public static final int requiredDisplayCategory;
field public static final int requiredFeature = 16844116; // 0x1010554
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
field public static final int requiredNotFeature = 16844117; // 0x1010555
@@ -1508,7 +1509,6 @@
field public static final int targetCellWidth = 16844340; // 0x1010634
field public static final int targetClass = 16842799; // 0x101002f
field @Deprecated public static final int targetDescriptions = 16843680; // 0x10103a0
- field public static final int targetDisplayCategory;
field public static final int targetId = 16843740; // 0x10103dc
field public static final int targetName = 16843853; // 0x101044d
field public static final int targetPackage = 16842785; // 0x1010021
@@ -3116,6 +3116,7 @@
method public boolean onGesture(@NonNull android.accessibilityservice.AccessibilityGestureEvent);
method public abstract void onInterrupt();
method protected boolean onKeyEvent(android.view.KeyEvent);
+ method public void onMotionEvent(@NonNull android.view.MotionEvent);
method protected void onServiceConnected();
method public void onSystemActionsChanged();
method public final boolean performGlobalAction(int);
@@ -3273,6 +3274,7 @@
method @Deprecated public String getDescription();
method public String getId();
method public int getInteractiveUiTimeoutMillis();
+ method public int getMotionEventSources();
method public int getNonInteractiveUiTimeoutMillis();
method public android.content.pm.ResolveInfo getResolveInfo();
method public String getSettingsActivityName();
@@ -3282,6 +3284,7 @@
method @Nullable public CharSequence loadIntro(@NonNull android.content.pm.PackageManager);
method public CharSequence loadSummary(android.content.pm.PackageManager);
method public void setInteractiveUiTimeoutMillis(@IntRange(from=0) int);
+ method public void setMotionEventSources(int);
method public void setNonInteractiveUiTimeoutMillis(@IntRange(from=0) int);
method public void writeToParcel(android.os.Parcel, int);
field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10
@@ -11201,10 +11204,10 @@
field public String parentActivityName;
field public String permission;
field public int persistableMode;
+ field @Nullable public String requiredDisplayCategory;
field public int screenOrientation;
field public int softInputMode;
field public String targetActivity;
- field @Nullable public String targetDisplayCategory;
field public String taskAffinity;
field public int theme;
field public int uiOptions;
@@ -23953,11 +23956,17 @@
}
public static final class RouteListingPreference.Item implements android.os.Parcelable {
- ctor public RouteListingPreference.Item(@NonNull String);
+ ctor public RouteListingPreference.Item(@NonNull String, int, int);
method public int describeContents();
+ method public int getDisableReason();
+ method public int getFlags();
method @NonNull public String getRouteId();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.media.RouteListingPreference.Item> CREATOR;
+ field public static final int DISABLE_REASON_NONE = 0; // 0x0
+ field public static final int DISABLE_REASON_SUBSCRIPTION_REQUIRED = 1; // 0x1
+ field public static final int FLAG_ONGOING_SESSION = 1; // 0x1
+ field public static final int FLAG_SUGGESTED_ROUTE = 2; // 0x2
}
public final class RoutingSessionInfo implements android.os.Parcelable {
@@ -45670,6 +45679,19 @@
method public int previousStartBoundary(@IntRange(from=0) int);
}
+ public class Highlights {
+ method @NonNull public android.graphics.Paint getPaint(int);
+ method @NonNull public int[] getRanges(int);
+ method public int getSize();
+ }
+
+ public static final class Highlights.Builder {
+ ctor public Highlights.Builder();
+ method @NonNull public android.text.Highlights.Builder addRange(@NonNull android.graphics.Paint, int, int);
+ method @NonNull public android.text.Highlights.Builder addRanges(@NonNull android.graphics.Paint, @NonNull int...);
+ method @NonNull public android.text.Highlights build();
+ }
+
public class Html {
method public static String escapeHtml(CharSequence);
method @Deprecated public static android.text.Spanned fromHtml(String);
@@ -45761,6 +45783,9 @@
ctor protected Layout(CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float);
method public void draw(android.graphics.Canvas);
method public void draw(android.graphics.Canvas, android.graphics.Path, android.graphics.Paint, int);
+ method public void draw(@NonNull android.graphics.Canvas, @Nullable java.util.List<android.graphics.Path>, @Nullable java.util.List<android.graphics.Paint>, @Nullable android.graphics.Path, @Nullable android.graphics.Paint, int);
+ method public void drawBackground(@NonNull android.graphics.Canvas);
+ method public void drawText(@NonNull android.graphics.Canvas);
method public void fillCharacterBounds(@IntRange(from=0) int, @IntRange(from=0) int, @NonNull float[], @IntRange(from=0) int);
method public final android.text.Layout.Alignment getAlignment();
method public abstract int getBottomPadding();
@@ -58574,6 +58599,7 @@
method public boolean getFreezesText();
method public int getGravity();
method @ColorInt public int getHighlightColor();
+ method @Nullable public android.text.Highlights getHighlights();
method public CharSequence getHint();
method public final android.content.res.ColorStateList getHintTextColors();
method public int getHyphenationFrequency();
@@ -58703,6 +58729,7 @@
method public void setGravity(int);
method public void setHeight(int);
method public void setHighlightColor(@ColorInt int);
+ method public void setHighlights(@Nullable android.text.Highlights);
method public final void setHint(CharSequence);
method public final void setHint(@StringRes int);
method public final void setHintTextColor(@ColorInt int);
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 3228ce6..286a800 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -393,7 +393,6 @@
method public static void traceBegin(long, @NonNull String);
method public static void traceCounter(long, @NonNull String, int);
method public static void traceEnd(long);
- field public static final long TRACE_TAG_AIDL = 16777216L; // 0x1000000L
field public static final long TRACE_TAG_NETWORK = 2097152L; // 0x200000L
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index e976c48..3817202 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1474,6 +1474,7 @@
method @RequiresPermission(android.Manifest.permission.BACKUP) public void cancelBackups();
method @RequiresPermission(android.Manifest.permission.BACKUP) public void excludeKeysFromRestore(@NonNull String, @NonNull java.util.List<java.lang.String>);
method @RequiresPermission(android.Manifest.permission.BACKUP) public long getAvailableRestoreToken(String);
+ method @NonNull public android.app.backup.BackupRestoreEventLogger getBackupRestoreEventLogger(@NonNull android.app.backup.BackupAgent);
method @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.Intent getConfigurationIntent(String);
method @RequiresPermission(android.Manifest.permission.BACKUP) public String getCurrentTransport();
method @Nullable @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.ComponentName getCurrentTransportComponent();
@@ -1592,6 +1593,33 @@
field public final long bytesTransferred;
}
+ public class BackupRestoreEventLogger {
+ method public void logBackupMetaData(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, @NonNull String);
+ method public void logItemsBackedUp(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int);
+ method public void logItemsBackupFailed(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int, @android.app.backup.BackupRestoreEventLogger.BackupRestoreError @Nullable String);
+ method public void logItemsRestoreFailed(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int, @android.app.backup.BackupRestoreEventLogger.BackupRestoreError @Nullable String);
+ method public void logItemsRestored(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int);
+ method public void logRestoreMetadata(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, @NonNull String);
+ }
+
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface BackupRestoreEventLogger.BackupRestoreDataType {
+ }
+
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface BackupRestoreEventLogger.BackupRestoreError {
+ }
+
+ public static final class BackupRestoreEventLogger.DataTypeResult implements android.os.Parcelable {
+ ctor public BackupRestoreEventLogger.DataTypeResult(@NonNull String);
+ method public int describeContents();
+ method @android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull public String getDataType();
+ method @NonNull public java.util.Map<java.lang.String,java.lang.Integer> getErrors();
+ method public int getFailCount();
+ method @Nullable public byte[] getMetadataHash();
+ method public int getSuccessCount();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.backup.BackupRestoreEventLogger.DataTypeResult> CREATOR;
+ }
+
public class BackupTransport {
ctor public BackupTransport();
method public int abortFullRestore();
@@ -10021,6 +10049,10 @@
field public static final int STATUS_WAITING_REBOOT = 5; // 0x5
}
+ public final class Trace {
+ field public static final long TRACE_TAG_AIDL = 16777216L; // 0x1000000L
+ }
+
public class UpdateEngine {
ctor public UpdateEngine();
method @NonNull @WorkerThread public android.os.UpdateEngine.AllocateSpaceResult allocateSpace(@NonNull String, @NonNull String[]);
@@ -15912,6 +15944,7 @@
public class ImsSmsImplBase {
ctor public ImsSmsImplBase();
method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int);
+ method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int, @NonNull byte[]);
method public void acknowledgeSmsReport(int, @IntRange(from=0, to=65535) int, int);
method public String getSmsFormat();
method public void onReady();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 7d85faf..25c4652 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -440,6 +440,7 @@
method @NonNull public java.util.Set<java.lang.String> getAdoptedShellPermissions();
method @Deprecated public boolean grantRuntimePermission(String, String, android.os.UserHandle);
method public boolean injectInputEvent(@NonNull android.view.InputEvent, boolean, boolean);
+ method public void injectInputEventToInputFilter(@NonNull android.view.InputEvent);
method @Deprecated public boolean revokeRuntimePermission(String, String, android.os.UserHandle);
method public void syncInputTransactions();
method public void syncInputTransactions(boolean);
@@ -1316,6 +1317,14 @@
}
+package android.hardware.location {
+
+ public final class ContextHubManager {
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public long[] getPreloadedNanoAppIds(@NonNull android.hardware.location.ContextHubInfo);
+ }
+
+}
+
package android.hardware.soundtrigger {
public class KeyphraseEnrollmentInfo {
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 02a81ac..968ed87 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -54,6 +54,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
+import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceControl;
@@ -797,6 +798,8 @@
private FingerprintGestureController mFingerprintGestureController;
+ private int mMotionEventSources;
+
/**
* Callback for {@link android.view.accessibility.AccessibilityEvent}s.
*
@@ -820,7 +823,11 @@
for (int i = 0; i < mMagnificationControllers.size(); i++) {
mMagnificationControllers.valueAt(i).onServiceConnectedLocked();
}
- updateInputMethod(getServiceInfo());
+ final AccessibilityServiceInfo info = getServiceInfo();
+ if (info != null) {
+ updateInputMethod(info);
+ mMotionEventSources = info.getMotionEventSources();
+ }
}
if (mSoftKeyboardController != null) {
mSoftKeyboardController.onServiceConnected();
@@ -946,6 +953,25 @@
}
/**
+ * Callback that allows an accessibility service to observe generic {@link MotionEvent}s.
+ * <p>
+ * Prefer {@link TouchInteractionController} to observe and control touchscreen events,
+ * including touch gestures. If this or any enabled service is using
+ * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} then
+ * {@link #onMotionEvent} will not receive touchscreen events.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> The service must first request to listen to events using
+ * {@link AccessibilityServiceInfo#setMotionEventSources}.
+ * {@link MotionEvent}s from sources in {@link AccessibilityServiceInfo#getMotionEventSources()}
+ * are not sent to the rest of the system. To stop listening to events from a given source, call
+ * {@link AccessibilityServiceInfo#setMotionEventSources} with that source removed.
+ * </p>
+ * @param event The event to be processed.
+ */
+ public void onMotionEvent(@NonNull MotionEvent event) { }
+
+ /**
* Gets the windows on the screen of the default display. This method returns only the windows
* that a sighted user can interact with, as opposed to all windows.
* For example, if there is a modal dialog shown and the user cannot touch
@@ -2521,6 +2547,7 @@
public final void setServiceInfo(AccessibilityServiceInfo info) {
mInfo = info;
updateInputMethod(info);
+ mMotionEventSources = info.getMotionEventSources();
sendServiceInfo();
}
@@ -2724,7 +2751,7 @@
@Override
public void onMotionEvent(MotionEvent event) {
- AccessibilityService.this.onMotionEvent(event);
+ AccessibilityService.this.sendMotionEventToCallback(event);
}
@Override
@@ -3359,14 +3386,23 @@
}
}
- void onMotionEvent(MotionEvent event) {
- TouchInteractionController controller;
- synchronized (mLock) {
- int displayId = event.getDisplayId();
- controller = mTouchInteractionControllers.get(displayId);
+ void sendMotionEventToCallback(MotionEvent event) {
+ boolean sendingTouchEventToTouchInteractionController = false;
+ if (event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)) {
+ TouchInteractionController controller;
+ synchronized (mLock) {
+ int displayId = event.getDisplayId();
+ controller = mTouchInteractionControllers.get(displayId);
+ }
+ if (controller != null) {
+ sendingTouchEventToTouchInteractionController = true;
+ controller.onMotionEvent(event);
+ }
}
- if (controller != null) {
- controller.onMotionEvent(event);
+ final int eventSourceWithoutClass = event.getSource() & ~InputDevice.SOURCE_CLASS_MASK;
+ if ((mMotionEventSources & eventSourceWithoutClass) != 0
+ && !sendingTouchEventToTouchInteractionController) {
+ onMotionEvent(event);
}
}
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 295eaaf..ae57959 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -612,6 +612,12 @@
private boolean mIsAccessibilityTool = false;
/**
+ * The bit mask of {@link android.view.InputDevice} sources that the accessibility
+ * service wants to listen to for generic {@link android.view.MotionEvent}s.
+ */
+ private int mMotionEventSources = 0;
+
+ /**
* Creates a new instance.
*/
public AccessibilityServiceInfo() {
@@ -785,6 +791,7 @@
mNonInteractiveUiTimeout = other.mNonInteractiveUiTimeout;
mInteractiveUiTimeout = other.mInteractiveUiTimeout;
flags = other.flags;
+ mMotionEventSources = other.mMotionEventSources;
// NOTE: Ensure that only properties that are safe to be modified by the service itself
// are included here (regardless of hidden setters, etc.).
}
@@ -956,6 +963,44 @@
}
/**
+ * Returns the bit mask of {@link android.view.InputDevice} sources that the accessibility
+ * service wants to listen to for generic {@link android.view.MotionEvent}s.
+ */
+ public int getMotionEventSources() {
+ return mMotionEventSources;
+ }
+
+ /**
+ * Sets the bit mask of {@link android.view.InputDevice} sources that the accessibility
+ * service wants to listen to for generic {@link android.view.MotionEvent}s.
+ *
+ * <p>
+ * Note: including an {@link android.view.InputDevice} source that does not send
+ * {@link android.view.MotionEvent}s is effectively a no-op for that source, since you will
+ * not receive any events from that source.
+ * </p>
+ * <p>
+ * Allowed sources include:
+ * <li>{@link android.view.InputDevice#SOURCE_MOUSE}</li>
+ * <li>{@link android.view.InputDevice#SOURCE_STYLUS}</li>
+ * <li>{@link android.view.InputDevice#SOURCE_BLUETOOTH_STYLUS}</li>
+ * <li>{@link android.view.InputDevice#SOURCE_TRACKBALL}</li>
+ * <li>{@link android.view.InputDevice#SOURCE_MOUSE_RELATIVE}</li>
+ * <li>{@link android.view.InputDevice#SOURCE_TOUCHPAD}</li>
+ * <li>{@link android.view.InputDevice#SOURCE_TOUCH_NAVIGATION}</li>
+ * <li>{@link android.view.InputDevice#SOURCE_ROTARY_ENCODER}</li>
+ * <li>{@link android.view.InputDevice#SOURCE_JOYSTICK}</li>
+ * <li>{@link android.view.InputDevice#SOURCE_SENSOR}</li>
+ * </p>
+ *
+ * @param motionEventSources A bit mask of {@link android.view.InputDevice} sources.
+ * @see AccessibilityService#onMotionEvent
+ */
+ public void setMotionEventSources(int motionEventSources) {
+ mMotionEventSources = motionEventSources;
+ }
+
+ /**
* The localized summary of the accessibility service.
* <p>
* <strong>Statically set from
@@ -1179,6 +1224,7 @@
parcel.writeBoolean(mIsAccessibilityTool);
parcel.writeString(mTileServiceName);
parcel.writeInt(mIntroResId);
+ parcel.writeInt(mMotionEventSources);
}
private void initFromParcel(Parcel parcel) {
@@ -1203,6 +1249,7 @@
mIsAccessibilityTool = parcel.readBoolean();
mTileServiceName = parcel.readString();
mIntroResId = parcel.readInt();
+ mMotionEventSources = parcel.readInt();
}
@Override
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 96ced41..2dccd4d 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4763,14 +4763,16 @@
if (s != null) {
try {
if (localLOGV) Slog.v(TAG, "Timeout short service " + s);
- s.callOnTimeout(startId);
- // TODO(short-service): Do we need "service executing" for timeout?
- // (see handleStopService())
+ // Unlike other service callbacks, we don't do serviceDoneExecuting() here.
+ // "service executing" state is used to boost the procstate / oom-adj, but
+ // for short-FGS timeout, we have a specific control for them anyway, so
+ // we don't have to do that.
+ s.callOnTimeout(startId);
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
- "Unable to timeout service " + s
+ "Unable to call onTimeout on service " + s
+ ": " + e.toString(), e);
}
Slog.i(TAG, "handleTimeoutService: exception for " + token, e);
@@ -6683,34 +6685,6 @@
StrictMode.initThreadDefaults(data.appInfo);
StrictMode.initVmDefaults(data.appInfo);
- if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
- // XXX should have option to change the port.
- Debug.changeDebugPort(8100);
- if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
- Slog.w(TAG, "Application " + data.info.getPackageName()
- + " is waiting for the debugger on port 8100...");
-
- IActivityManager mgr = ActivityManager.getService();
- try {
- mgr.showWaitingForDebugger(mAppThread, true);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
-
- Debug.waitForDebugger();
-
- try {
- mgr.showWaitingForDebugger(mAppThread, false);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
-
- } else {
- Slog.w(TAG, "Application " + data.info.getPackageName()
- + " can be debugged on port 8100...");
- }
- }
-
// Allow binder tracing, and application-generated systrace messages if we're profileable.
boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
boolean isAppProfileable = isAppDebuggable || data.appInfo.isProfileable();
@@ -6818,6 +6792,34 @@
throw ex.rethrowFromSystemServer();
}
+ // Wait for debugger after we have notified the system to finish attach application
+ if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
+ // XXX should have option to change the port.
+ Debug.changeDebugPort(8100);
+ if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
+ Slog.w(TAG, "Application " + data.info.getPackageName()
+ + " is waiting for the debugger on port 8100...");
+
+ try {
+ mgr.showWaitingForDebugger(mAppThread, true);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+
+ Debug.waitForDebugger();
+
+ try {
+ mgr.showWaitingForDebugger(mAppThread, false);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+
+ } else {
+ Slog.w(TAG, "Application " + data.info.getPackageName()
+ + " can be debugged on port 8100...");
+ }
+ }
+
try {
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
diff --git a/core/java/android/app/ForegroundServiceTypePolicy.java b/core/java/android/app/ForegroundServiceTypePolicy.java
index 63fdc2e..332aadd 100644
--- a/core/java/android/app/ForegroundServiceTypePolicy.java
+++ b/core/java/android/app/ForegroundServiceTypePolicy.java
@@ -58,6 +58,7 @@
import android.healthconnect.HealthConnectManager;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.permission.PermissionCheckerManager;
import android.util.ArraySet;
import android.util.SparseArray;
@@ -880,11 +881,12 @@
int checkPermission(@NonNull Context context, @NonNull String name, int callerUid,
int callerPid, String packageName, boolean allowWhileInUse) {
// Simple case, check if it's already granted.
- if (PermissionChecker.checkPermissionForPreflight(context, name,
- callerPid, callerUid, packageName) == PERMISSION_GRANTED) {
+ @PackageManager.PermissionResult int result;
+ if ((result = PermissionChecker.checkPermissionForPreflight(context, name,
+ callerPid, callerUid, packageName)) == PERMISSION_GRANTED) {
return PERMISSION_GRANTED;
}
- if (allowWhileInUse) {
+ if (allowWhileInUse && result == PermissionCheckerManager.PERMISSION_SOFT_DENIED) {
// Check its appops
final int opCode = AppOpsManager.permissionToOpCode(name);
final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 3edaabd..040111c 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -799,4 +799,7 @@
* <p>Typically used only by automotive builds when the vehicle has multiple displays.
*/
@nullable int[] getSecondaryDisplayIdsForStartingBackgroundUsers();
+
+ /** Returns if the service is a short-service is still "alive" and past the timeout. */
+ boolean shouldServiceTimeOut(in ComponentName className, in IBinder token);
}
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index 623af5f..fbb0748 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -40,6 +40,7 @@
void connect(IAccessibilityServiceClient client, int flags);
void disconnect();
boolean injectInputEvent(in InputEvent event, boolean sync, boolean waitForAnimations);
+ void injectInputEventToInputFilter(in InputEvent event);
void syncInputTransactions(boolean waitForAnimations);
boolean setRotation(int rotation);
Bitmap takeScreenshot(in Rect crop);
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 3a7d483..0ab96a9 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -1119,10 +1119,21 @@
/** @hide */
public final void callOnTimeout(int startId) {
- // TODO(short-service): Do we need any check here, to avoid races?
- // e.g. if the service is already stopped, but ActivityThread.handleTimeoutService() is
- // already scheduled, then we'll call this method anyway. It should be doable to prevent
- // that if we keep track of startForeground, stopForeground, and onDestroy.
+ // Note, because all the service callbacks (and other similar callbacks, e.g. activity
+ // callbacks) are delivered using the main handler, it's possible the service is already
+ // stopped when before this method is called, so we do a double check here.
+ if (mToken == null) {
+ Log.w(TAG, "Service already destroyed, skipping onTimeout()");
+ return;
+ }
+ try {
+ if (!mActivityManager.shouldServiceTimeOut(
+ new ComponentName(this, mClassName), mToken)) {
+ Log.w(TAG, "Service no longer relevant, skipping onTimeout()");
+ return;
+ }
+ } catch (RemoteException ex) {
+ }
onTimeout(startId);
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 5d87012..762ac23 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1617,6 +1617,7 @@
case Context.INCREMENTAL_SERVICE:
case Context.ETHERNET_SERVICE:
case Context.CONTEXTHUB_SERVICE:
+ case Context.VIRTUALIZATION_SERVICE:
return null;
}
Slog.wtf(TAG, "Manager wrapper not available: " + name);
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 2718054..814f38b 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -793,6 +793,24 @@
}
/**
+ * Injects an arbitrary {@link InputEvent} to the accessibility input filter, for use in testing
+ * the accessibility input filter.
+ *
+ * Events injected to the input subsystem using the standard {@link #injectInputEvent} method
+ * skip the accessibility input filter to avoid feedback loops.
+ *
+ * @hide
+ */
+ @TestApi
+ public void injectInputEventToInputFilter(@NonNull InputEvent event) {
+ try {
+ mUiAutomationConnection.injectInputEventToInputFilter(event);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error while injecting input event to input filter", re);
+ }
+ }
+
+ /**
* Sets the system settings values that control the scaling factor for animations. The scale
* controls the animation playback speed for animations that respect these settings. Animations
* that do not respect the settings values will not be affected by this function. A lower scale
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 0201c12..3e4e7cb 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -178,6 +178,11 @@
}
@Override
+ public void injectInputEventToInputFilter(InputEvent event) throws RemoteException {
+ mAccessibilityManager.injectInputEventToInputFilter(event);
+ }
+
+ @Override
public void syncInputTransactions(boolean waitForAnimations) {
synchronized (mLock) {
throwIfCalledByNotTrustedUidLocked();
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 378020f..7255c3e 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -1018,6 +1018,29 @@
}
}
+ /**
+ * Get an instance of {@link BackupRestoreEventLogger} to report B&R related events during an
+ * ongoing backup or restore operation.
+ *
+ * @param backupAgent the agent currently running a B&R operation.
+ *
+ * @return an instance of {@code BackupRestoreEventLogger} or {@code null} if the agent has not
+ * finished initialisation, i.e. {@link BackupAgent#onCreate()} has not been called yet.
+ * @throws IllegalStateException if called before the agent has finished initialisation.
+ *
+ * @hide
+ */
+ @NonNull
+ @SystemApi
+ public BackupRestoreEventLogger getBackupRestoreEventLogger(@NonNull BackupAgent backupAgent) {
+ BackupRestoreEventLogger logger = backupAgent.getBackupRestoreEventLogger();
+ if (logger == null) {
+ throw new IllegalStateException("Attempting to get logger on an uninitialised "
+ + "BackupAgent");
+ }
+ return backupAgent.getBackupRestoreEventLogger();
+ }
+
/*
* We wrap incoming binder calls with a private class implementation that
* redirects them into main-thread actions. This serializes the backup
diff --git a/core/java/android/app/backup/BackupRestoreEventLogger.java b/core/java/android/app/backup/BackupRestoreEventLogger.java
index f892833..5805826 100644
--- a/core/java/android/app/backup/BackupRestoreEventLogger.java
+++ b/core/java/android/app/backup/BackupRestoreEventLogger.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -35,7 +36,6 @@
import java.util.List;
import java.util.Map;
-// TODO(b/244436184): Make this @SystemApi
/**
* Class to log B&R stats for each data type that is backed up and restored by the calling app.
*
@@ -46,12 +46,15 @@
*
* @hide
*/
+@SystemApi
public class BackupRestoreEventLogger {
private static final String TAG = "BackupRestoreEventLogger";
/**
* Max number of unique data types for which an instance of this logger can store info. Attempts
* to use more distinct data type values will be rejected.
+ *
+ * @hide
*/
public static final int DATA_TYPES_ALLOWED = 15;
@@ -301,7 +304,7 @@
/**
* Encapsulate logging results for a single data type.
*/
- public static class DataTypeResult implements Parcelable {
+ public static final class DataTypeResult implements Parcelable {
@BackupRestoreDataType
private final String mDataType;
private int mSuccessCount;
@@ -309,7 +312,7 @@
private final Map<String, Integer> mErrors = new HashMap<>();
private byte[] mMetadataHash;
- public DataTypeResult(String dataType) {
+ public DataTypeResult(@NonNull String dataType) {
mDataType = dataType;
}
@@ -358,7 +361,7 @@
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mDataType);
dest.writeInt(mSuccessCount);
@@ -374,6 +377,7 @@
dest.writeByteArray(mMetadataHash);
}
+ @NonNull
public static final Parcelable.Creator<DataTypeResult> CREATOR =
new Parcelable.Creator<>() {
public DataTypeResult createFromParcel(Parcel in) {
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index 01b42bf..568185a 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -416,7 +416,7 @@
* @param densityDpi The density of the virtual display in dpi, must be greater than 0.
* @param displayCategories The categories of the virtual display, indicating the type of
* activities allowed to run on the display. Activities can declare their type using
- * {@link android.content.pm.ActivityInfo#targetDisplayCategory}.
+ * {@link android.content.pm.ActivityInfo#requiredDisplayCategory}.
* @param surface The surface to which the content of the virtual display should
* be rendered, or null if there is none initially. The surface can also be set later using
* {@link VirtualDisplay#setSurface(Surface)}.
diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java
index e2b5c5d..1cbe910 100644
--- a/core/java/android/companion/virtual/VirtualDeviceParams.java
+++ b/core/java/android/companion/virtual/VirtualDeviceParams.java
@@ -617,7 +617,7 @@
/**
* Specifies a policy for this virtual device.
*
- * Policies define the system behavior that may be specific for this virtual device. A
+ * <p>Policies define the system behavior that may be specific for this virtual device. A
* policy can be defined for each {@code PolicyType}, but they are all optional.
*
* @param policyType the type of policy, i.e. which behavior to specify a policy for.
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 9d82274..65b3ca4 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3889,7 +3889,7 @@
"android.intent.action.USER_INITIALIZE";
/**
- * Sent when a user switch is happening, causing the process's user to be
+ * Sent after a user switch is complete, if the switch caused the process's user to be
* brought to the foreground. This is only sent to receivers registered
* through {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
* Context.registerReceiver}. It is sent to the user that is going to the
@@ -3901,7 +3901,7 @@
"android.intent.action.USER_FOREGROUND";
/**
- * Sent when a user switch is happening, causing the process's user to be
+ * Sent after a user switch is complete, if the switch caused the process's user to be
* sent to the background. This is only sent to receivers registered
* through {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
* Context.registerReceiver}. It is sent to the user that is going to the
@@ -4042,6 +4042,11 @@
* the current state of the user.
* @hide
*/
+ /*
+ * This broadcast is sent after the user switch is complete. In case a task needs to be done
+ * while the switch is happening (i.e. while the screen is frozen to hide UI jank), please use
+ * ActivityManagerService.registerUserSwitchObserver method.
+ */
@SystemApi
public static final String ACTION_USER_SWITCHED =
"android.intent.action.USER_SWITCHED";
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index fda4119..dab57fd 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -221,21 +221,20 @@
public String launchToken;
/**
- * Specifies the category of the target display the activity is expected to run on. Set from
- * the {@link android.R.attr#targetDisplayCategory} attribute. Upon creation, a virtual display
- * can specify which display categories it supports and one of the category must be present in
- * the activity's manifest to allow this activity to run. The default value is {@code null},
- * which indicates the activity does not belong to a restricted display category and thus can
- * only run on a display that didn't specify any display categories. Each activity can only
- * specify one category it targets to but a virtual display can support multiple restricted
- * categories.
- *
+ * Specifies the required display category of the activity. Set from the
+ * {@link android.R.attr#requiredDisplayCategory} attribute. Upon creation, a display can
+ * specify which display categories it supports and one of the category must be present
+ * in the {@code <activity>} element to allow this activity to run. The default value is
+ * {@code null}, which indicates the activity does not have a required display category and
+ * thus can only run on a display that didn't specify any display categories. Each activity
+ * can only specify one required category but a display can support multiple display categories.
+ * <p>
* This field should be formatted as a Java-language-style free form string(for example,
* com.google.automotive_entertainment), which may contain uppercase or lowercase letters ('A'
* through 'Z'), numbers, and underscores ('_') but may only start with letters.
*/
@Nullable
- public String targetDisplayCategory;
+ public String requiredDisplayCategory;
/**
* Activity can not be resized and always occupies the fullscreen area with all windows fully
@@ -1330,7 +1329,7 @@
mMaxAspectRatio = orig.mMaxAspectRatio;
mMinAspectRatio = orig.mMinAspectRatio;
supportsSizeChanges = orig.supportsSizeChanges;
- targetDisplayCategory = orig.targetDisplayCategory;
+ requiredDisplayCategory = orig.requiredDisplayCategory;
}
/**
@@ -1669,8 +1668,8 @@
if (mKnownActivityEmbeddingCerts != null) {
pw.println(prefix + "knownActivityEmbeddingCerts=" + mKnownActivityEmbeddingCerts);
}
- if (targetDisplayCategory != null) {
- pw.println(prefix + "targetDisplayCategory=" + targetDisplayCategory);
+ if (requiredDisplayCategory != null) {
+ pw.println(prefix + "requiredDisplayCategory=" + requiredDisplayCategory);
}
super.dumpBack(pw, prefix, dumpFlags);
}
@@ -1718,7 +1717,7 @@
dest.writeFloat(mMinAspectRatio);
dest.writeBoolean(supportsSizeChanges);
sForStringSet.parcel(mKnownActivityEmbeddingCerts, dest, flags);
- dest.writeString8(targetDisplayCategory);
+ dest.writeString8(requiredDisplayCategory);
}
/**
@@ -1844,7 +1843,7 @@
if (mKnownActivityEmbeddingCerts.isEmpty()) {
mKnownActivityEmbeddingCerts = null;
}
- targetDisplayCategory = source.readString8();
+ requiredDisplayCategory = source.readString8();
}
/**
diff --git a/core/java/android/content/res/FontScaleConverter.java b/core/java/android/content/res/FontScaleConverter.java
index c7fdb16..457225d 100644
--- a/core/java/android/content/res/FontScaleConverter.java
+++ b/core/java/android/content/res/FontScaleConverter.java
@@ -36,11 +36,6 @@
* @hide
*/
public class FontScaleConverter {
- /**
- * How close the given SP should be to a canonical SP in the array before they are considered
- * the same for lookup purposes.
- */
- private static final float THRESHOLD_FOR_MATCHING_SP = 0.02f;
@VisibleForTesting
final float[] mFromSpValues;
@@ -78,10 +73,11 @@
public float convertSpToDp(float sp) {
final float spPositive = Math.abs(sp);
// TODO(b/247861374): find a match at a higher index?
- final int spRounded = Math.round(spPositive);
final float sign = Math.signum(sp);
- final int index = Arrays.binarySearch(mFromSpValues, spRounded);
- if (index >= 0 && Math.abs(spRounded - spPositive) < THRESHOLD_FOR_MATCHING_SP) {
+ // We search for exact matches only, even if it's just a little off. The interpolation will
+ // handle any non-exact matches.
+ final int index = Arrays.binarySearch(mFromSpValues, spPositive);
+ if (index >= 0) {
// exact match, return the matching dp
return sign * mToDpValues[index];
} else {
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 441fd88..f7675e8 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -588,18 +588,20 @@
* @see #DISPLAY_CATEGORY_PRESENTATION
*/
public Display[] getDisplays(String category) {
- final int[] displayIds = mGlobal.getDisplayIds();
+ boolean includeDisabled = (category != null
+ && category.equals(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED));
+ final int[] displayIds = mGlobal.getDisplayIds(includeDisabled);
synchronized (mLock) {
try {
- if (category == null
- || DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED.equals(category)) {
- addAllDisplaysLocked(mTempDisplays, displayIds);
- } else if (category.equals(DISPLAY_CATEGORY_PRESENTATION)) {
+ if (DISPLAY_CATEGORY_PRESENTATION.equals(category)) {
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI);
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_EXTERNAL);
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY);
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_VIRTUAL);
addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_INTERNAL);
+ } else if (category == null
+ || DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED.equals(category)) {
+ addAllDisplaysLocked(mTempDisplays, displayIds);
}
return mTempDisplays.toArray(new Display[mTempDisplays.size()]);
} finally {
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index cc397d5..f038c66 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -212,6 +212,16 @@
*/
@UnsupportedAppUsage
public int[] getDisplayIds() {
+ return getDisplayIds(/* includeDisabled= */ false);
+ }
+
+ /**
+ * Gets all currently valid logical display ids.
+ *
+ * @param includeDisabled True if the returned list of displays includes disabled displays.
+ * @return An array containing all display ids.
+ */
+ public int[] getDisplayIds(boolean includeDisabled) {
try {
synchronized (mLock) {
if (USE_CACHE) {
@@ -220,7 +230,7 @@
}
}
- int[] displayIds = mDm.getDisplayIds();
+ int[] displayIds = mDm.getDisplayIds(includeDisabled);
if (USE_CACHE) {
mDisplayIdCache = displayIds;
}
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 1c2c895..829908f 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -423,8 +423,6 @@
public static final int POLICY_DIM = 2;
// Policy: Make the screen bright as usual.
public static final int POLICY_BRIGHT = 3;
- // Policy: Keep the screen and display optimized for VR mode.
- public static final int POLICY_VR = 4;
// The basic overall policy to apply: off, doze, dim or bright.
public int policy;
@@ -489,10 +487,6 @@
return policy == POLICY_BRIGHT || policy == POLICY_DIM;
}
- public boolean isVr() {
- return policy == POLICY_VR;
- }
-
public void copyFrom(DisplayPowerRequest other) {
policy = other.policy;
useProximitySensor = other.useProximitySensor;
@@ -566,8 +560,6 @@
return "DIM";
case POLICY_BRIGHT:
return "BRIGHT";
- case POLICY_VR:
- return "VR";
default:
return Integer.toString(policy);
}
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 6b5594b..28bb35f 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -37,7 +37,7 @@
interface IDisplayManager {
@UnsupportedAppUsage
DisplayInfo getDisplayInfo(int displayId);
- int[] getDisplayIds();
+ int[] getDisplayIds(boolean includeDisabled);
boolean isUidPresentOnDisplay(int uid, int displayId);
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index b54da6c..ac23af4 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -24,6 +24,7 @@
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.app.ActivityThread;
import android.app.PendingIntent;
import android.content.Context;
@@ -966,6 +967,34 @@
}
/**
+ * Queries for the list of preloaded nanoapp IDs on the system.
+ *
+ * @param hubInfo The Context Hub to query a list of nanoapp IDs from.
+ *
+ * @return The list of 64-bit IDs of the preloaded nanoapps.
+ *
+ * @throws NullPointerException if hubInfo is null
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
+ @NonNull public long[] getPreloadedNanoAppIds(@NonNull ContextHubInfo hubInfo) {
+ Objects.requireNonNull(hubInfo, "hubInfo cannot be null");
+
+ long[] nanoappIds = null;
+ try {
+ nanoappIds = mService.getPreloadedNanoAppIds(hubInfo);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+
+ if (nanoappIds == null) {
+ nanoappIds = new long[0];
+ }
+ return nanoappIds;
+ }
+
+ /**
* Unregister a callback for receive messages from the context hub.
*
* @see Callback
diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl
index ced75c4..490267f 100644
--- a/core/java/android/hardware/location/IContextHubService.aidl
+++ b/core/java/android/hardware/location/IContextHubService.aidl
@@ -109,4 +109,8 @@
// Queries for a list of nanoapps
@EnforcePermission("ACCESS_CONTEXT_HUB")
void queryNanoApps(int contextHubId, in IContextHubTransactionCallback transactionCallback);
+
+ // Queries for a list of preloaded nanoapps
+ @EnforcePermission("ACCESS_CONTEXT_HUB")
+ long[] getPreloadedNanoAppIds(in ContextHubInfo hubInfo);
}
diff --git a/core/java/android/nfc/AvailableNfcAntenna.java b/core/java/android/nfc/AvailableNfcAntenna.java
index 946ba67..6e6512a 100644
--- a/core/java/android/nfc/AvailableNfcAntenna.java
+++ b/core/java/android/nfc/AvailableNfcAntenna.java
@@ -27,13 +27,15 @@
*/
public final class AvailableNfcAntenna implements Parcelable {
/**
- * Location on the antenna on the Y axis in millimeters.
- * 0 is the bottom-left when the user is facing the screen.
+ * Location of the antenna on the Y axis in millimeters.
+ * 0 is the bottom-left when the user is facing the screen
+ * and the device orientation is Portrait.
*/
private final int mLocationX;
/**
- * Location on the antenna on the Y axis in millimeters.
- * 0 is the bottom-left when the user is facing the screen.
+ * Location of the antenna on the Y axis in millimeters.
+ * 0 is the bottom-left when the user is facing the screen
+ * and the device orientation is Portrait.
*/
private final int mLocationY;
@@ -43,16 +45,18 @@
}
/**
- * Location on the antenna on the X axis in millimeters.
- * 0 is the bottom-left when the user is facing the screen.
+ * Location of the antenna on the X axis in millimeters.
+ * 0 is the bottom-left when the user is facing the screen
+ * and the device orientation is Portrait.
*/
public int getLocationX() {
return mLocationX;
}
/**
- * Location on the antenna on the Y axis in millimeters.
- * 0 is the bottom-left when the user is facing the screen.
+ * Location of the antenna on the Y axis in millimeters.
+ * 0 is the bottom-left when the user is facing the screen
+ * and the device orientation is Portrait.
*/
public int getLocationY() {
return mLocationY;
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index b919393..cdde18a 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -100,7 +100,7 @@
/** @hide */
public static final long TRACE_TAG_VIBRATOR = 1L << 23;
/** @hide */
- @SystemApi(client = MODULE_LIBRARIES)
+ @SystemApi
public static final long TRACE_TAG_AIDL = 1L << 24;
/** @hide */
public static final long TRACE_TAG_NNAPI = 1L << 25;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2adbbcd..22d5a27 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -17935,6 +17935,12 @@
public static final String WET_MODE_ON = "wet_mode_on";
/*
+ * Whether the RSB wake feature is enabled.
+ * @hide
+ */
+ public static final String RSB_WAKE_ENABLED = "rsb_wake_enabled";
+
+ /*
* Whether the screen-unlock (keyguard) sound is enabled.
* @hide
*/
diff --git a/core/java/android/text/Highlights.java b/core/java/android/text/Highlights.java
new file mode 100644
index 0000000..356dfca
--- /dev/null
+++ b/core/java/android/text/Highlights.java
@@ -0,0 +1,148 @@
+/*
+ * 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.text;
+
+import android.graphics.Paint;
+import android.util.Pair;
+
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A class that represents of the highlight of the text.
+ */
+public class Highlights {
+ private final List<Pair<Paint, int[]>> mHighlights;
+
+ private Highlights(List<Pair<Paint, int[]>> highlights) {
+ mHighlights = highlights;
+ }
+
+ /**
+ * Returns a number of highlight.
+ *
+ * @return a number of highlight.
+ *
+ * @see Builder#addRange(Paint, int, int)
+ * @see Builder#addRanges(Paint, int...)
+ */
+ public @IntRange(from = 0) int getSize() {
+ return mHighlights.size();
+ }
+
+ /**
+ * Returns a paint used for the i-th highlight.
+ *
+ * @param index an index of the highlight. Must be between 0 and {@link #getSize()}
+ * @return a paint object
+ *
+ * @see Builder#addRange(Paint, int, int)
+ * @see Builder#addRanges(Paint, int...)
+ */
+ public @NonNull Paint getPaint(@IntRange(from = 0) int index) {
+ return mHighlights.get(index).first;
+ }
+
+ /**
+ * Returns ranges of the i-th highlight.
+ *
+ * Ranges are represented of flattened inclusive start and exclusive end integers array. The
+ * inclusive start offset of the {@code i}-th range is stored in {@code 2 * i}-th of the array.
+ * The exclusive end offset of the {@code i}-th range is stored in {@code 2* i + 1}-th of the
+ * array. For example, the two ranges: (1, 2) and (3, 4) are flattened into single int array
+ * [1, 2, 3, 4].
+ *
+ * @param index an index of the highlight. Must be between 0 and {@link #getSize()}
+ * @return a paint object
+ *
+ * @see Builder#addRange(Paint, int, int)
+ * @see Builder#addRanges(Paint, int...)
+ */
+ public @NonNull int[] getRanges(int index) {
+ return mHighlights.get(index).second;
+ }
+
+ /**
+ * A builder for the Highlights.
+ */
+ public static final class Builder {
+ private final List<Pair<Paint, int[]>> mHighlights = new ArrayList<>();
+
+ /**
+ * Add single range highlight.
+ *
+ * @param paint a paint object used for drawing highlight path.
+ * @param start an inclusive offset of the text.
+ * @param end an exclusive offset of the text.
+ * @return this builder instance.
+ */
+ public @NonNull Builder addRange(@NonNull Paint paint, @IntRange(from = 0) int start,
+ @IntRange(from = 0) int end) {
+ if (start > end) {
+ throw new IllegalArgumentException("start must not be larger than end: "
+ + start + ", " + end);
+ }
+ Objects.requireNonNull(paint);
+
+ int[] range = new int[] {start, end};
+ mHighlights.add(new Pair<>(paint, range));
+ return this;
+ }
+
+ /**
+ * Add multiple ranges highlight.
+ *
+ * @param paint a paint object used for drawing highlight path.
+ * @param ranges a flatten ranges. The {@code 2 * i}-th element is an inclusive start offset
+ * of the {@code i}-th character. The {@code 2 * i + 1}-th element is an
+ * exclusive end offset of the {@code i}-th character.
+ * @return this builder instance.
+ */
+ public @NonNull Builder addRanges(@NonNull Paint paint, @NonNull int... ranges) {
+ if (ranges.length % 2 == 1) {
+ throw new IllegalArgumentException(
+ "Flatten ranges must have even numbered elements");
+ }
+ for (int j = 0; j < ranges.length / 2; ++j) {
+ int start = ranges[j * 2];
+ int end = ranges[j * 2 + 1];
+ if (start > end) {
+ throw new IllegalArgumentException(
+ "Reverse range found in the flatten range: " + Arrays.toString(
+ ranges));
+ }
+ }
+ Objects.requireNonNull(paint);
+ mHighlights.add(new Pair<>(paint, ranges));
+ return this;
+ }
+
+ /**
+ * Build a new Highlights instance.
+ *
+ * @return a new Highlights instance.
+ */
+ public @NonNull Highlights build() {
+ return new Highlights(mHighlights);
+ }
+ }
+}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 54ec07e..64dc16d 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -44,6 +44,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
+import java.util.List;
/**
* A base class that manages text layout in visual elements on
@@ -347,9 +348,13 @@
/**
* Draw this Layout on the specified Canvas.
+ *
+ * This API draws background first, then draws text on top of it.
+ *
+ * @see #draw(Canvas, List, List, Path, Paint, int)
*/
public void draw(Canvas c) {
- draw(c, null, null, 0);
+ draw(c, (Path) null, (Paint) null, 0);
}
/**
@@ -357,23 +362,142 @@
* between the background and the text.
*
* @param canvas the canvas
- * @param highlight the path of the highlight or cursor; can be null
- * @param highlightPaint the paint for the highlight
+ * @param selectionHighlight the path of the selection highlight or cursor; can be null
+ * @param selectionHighlightPaint the paint for the selection highlight
* @param cursorOffsetVertical the amount to temporarily translate the
* canvas while rendering the highlight
+ *
+ * @see #draw(Canvas, List, List, Path, Paint, int)
*/
- public void draw(Canvas canvas, Path highlight, Paint highlightPaint,
+ public void draw(
+ Canvas canvas, Path selectionHighlight,
+ Paint selectionHighlightPaint, int cursorOffsetVertical) {
+ draw(canvas, null, null, selectionHighlight, selectionHighlightPaint, cursorOffsetVertical);
+ }
+
+ /**
+ * Draw this layout on the specified canvas.
+ *
+ * This API draws background first, then draws highlight paths on top of it, then draws
+ * selection or cursor, then finally draws text on top of it.
+ *
+ * @see #drawBackground(Canvas)
+ * @see #drawText(Canvas)
+ *
+ * @param canvas the canvas
+ * @param highlightPaths the path of the highlights. The highlightPaths and highlightPaints must
+ * have the same length and aligned in the same order. For example, the
+ * paint of the n-th of the highlightPaths should be stored at the n-th of
+ * highlightPaints.
+ * @param highlightPaints the paints for the highlights. The highlightPaths and highlightPaints
+ * must have the same length and aligned in the same order. For example,
+ * the paint of the n-th of the highlightPaths should be stored at the
+ * n-th of highlightPaints.
+ * @param selectionPath the selection or cursor path
+ * @param selectionPaint the paint for the selection or cursor.
+ * @param cursorOffsetVertical the amount to temporarily translate the canvas while rendering
+ * the highlight
+ */
+ public void draw(@NonNull Canvas canvas,
+ @Nullable List<Path> highlightPaths,
+ @Nullable List<Paint> highlightPaints,
+ @Nullable Path selectionPath,
+ @Nullable Paint selectionPaint,
int cursorOffsetVertical) {
final long lineRange = getLineRangeForDraw(canvas);
int firstLine = TextUtils.unpackRangeStartFromLong(lineRange);
int lastLine = TextUtils.unpackRangeEndFromLong(lineRange);
if (lastLine < 0) return;
- drawBackground(canvas, highlight, highlightPaint, cursorOffsetVertical,
- firstLine, lastLine);
+ drawWithoutText(canvas, highlightPaths, highlightPaints, selectionPath, selectionPaint,
+ cursorOffsetVertical, firstLine, lastLine);
drawText(canvas, firstLine, lastLine);
}
+ /**
+ * Draw text part of this layout.
+ *
+ * Different from {@link #draw(Canvas, List, List, Path, Paint, int)} API, this API only draws
+ * text part, not drawing highlights, selections, or backgrounds.
+ *
+ * @see #draw(Canvas, List, List, Path, Paint, int)
+ * @see #drawBackground(Canvas)
+ *
+ * @param canvas the canvas
+ */
+ public void drawText(@NonNull Canvas canvas) {
+ final long lineRange = getLineRangeForDraw(canvas);
+ int firstLine = TextUtils.unpackRangeStartFromLong(lineRange);
+ int lastLine = TextUtils.unpackRangeEndFromLong(lineRange);
+ if (lastLine < 0) return;
+ drawText(canvas, firstLine, lastLine);
+ }
+
+ /**
+ * Draw background of this layout.
+ *
+ * Different from {@link #draw(Canvas, List, List, Path, Paint, int)} API, this API only draws
+ * background, not drawing text, highlights or selections. The background here is drawn by
+ * {@link LineBackgroundSpan} attached to the text.
+ *
+ * @see #draw(Canvas, List, List, Path, Paint, int)
+ * @see #drawText(Canvas)
+ *
+ * @param canvas the canvas
+ */
+ public void drawBackground(@NonNull Canvas canvas) {
+ final long lineRange = getLineRangeForDraw(canvas);
+ int firstLine = TextUtils.unpackRangeStartFromLong(lineRange);
+ int lastLine = TextUtils.unpackRangeEndFromLong(lineRange);
+ if (lastLine < 0) return;
+ drawBackground(canvas, firstLine, lastLine);
+ }
+
+ /**
+ * @hide public for Editor.java
+ */
+ public void drawWithoutText(
+ @NonNull Canvas canvas,
+ @Nullable List<Path> highlightPaths,
+ @Nullable List<Paint> highlightPaints,
+ @Nullable Path selectionPath,
+ @Nullable Paint selectionPaint,
+ int cursorOffsetVertical,
+ int firstLine,
+ int lastLine) {
+ drawBackground(canvas, firstLine, lastLine);
+ if (highlightPaths == null && highlightPaints == null) {
+ return;
+ }
+ if (cursorOffsetVertical != 0) canvas.translate(0, cursorOffsetVertical);
+ try {
+ if (highlightPaths != null) {
+ if (highlightPaints == null) {
+ throw new IllegalArgumentException(
+ "if highlight is specified, highlightPaint must be specified.");
+ }
+ if (highlightPaints.size() != highlightPaths.size()) {
+ throw new IllegalArgumentException(
+ "The highlight path size is different from the size of highlight"
+ + " paints");
+ }
+ for (int i = 0; i < highlightPaths.size(); ++i) {
+ final Path highlight = highlightPaths.get(i);
+ final Paint highlightPaint = highlightPaints.get(i);
+ if (highlight != null) {
+ canvas.drawPath(highlight, highlightPaint);
+ }
+ }
+ }
+
+ if (selectionPath != null) {
+ canvas.drawPath(selectionPath, selectionPaint);
+ }
+ } finally {
+ if (cursorOffsetVertical != 0) canvas.translate(0, -cursorOffsetVertical);
+ }
+ }
+
private boolean isJustificationRequired(int lineNum) {
if (mJustificationMode == JUSTIFICATION_MODE_NONE) return false;
final int lineEnd = getLineEnd(lineNum);
@@ -635,8 +759,9 @@
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public void drawBackground(Canvas canvas, Path highlight, Paint highlightPaint,
- int cursorOffsetVertical, int firstLine, int lastLine) {
+ public void drawBackground(
+ @NonNull Canvas canvas,
+ int firstLine, int lastLine) {
// First, draw LineBackgroundSpans.
// LineBackgroundSpans know nothing about the alignment, margins, or
// direction of the layout or line. XXX: Should they?
@@ -700,14 +825,6 @@
}
mLineBackgroundSpans.recycle();
}
-
- // There can be a highlight even without spans if we are drawing
- // a non-spanned transformation of a spanned editing buffer.
- if (highlight != null) {
- if (cursorOffsetVertical != 0) canvas.translate(0, cursorOffsetVertical);
- canvas.drawPath(highlight, highlightPaint);
- if (cursorOffsetVertical != 0) canvas.translate(0, -cursorOffsetVertical);
- }
}
/**
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index 5e17551..8d8ddb9 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -35,6 +35,7 @@
import android.annotation.ColorInt;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.TaskInfo;
import android.app.WindowConfiguration;
@@ -175,10 +176,16 @@
public final Rect screenSpaceBounds;
/**
- * The starting bounds of the source container in screen space coordinates. This is {@code null}
- * if the animation target isn't MODE_CHANGING. Since this is the starting bounds, it's size
- * should be equivalent to the size of the starting thumbnail. Note that sourceContainerBounds
- * is the end bounds of a change transition.
+ * The starting bounds of the source container in screen space coordinates.
+ * For {@link #MODE_OPENING}, this will be equivalent to {@link #screenSpaceBounds}.
+ * For {@link #MODE_CLOSING}, this will be equivalent to {@link #screenSpaceBounds} unless the
+ * closing container is also resizing. For example, when ActivityEmbedding split pair becomes
+ * stacked, the container on the back will be resized to fullscreen, but will also be covered
+ * (closing) by the container in the front.
+ * For {@link #MODE_CHANGING}, since this is the starting bounds, its size should be equivalent
+ * to the bounds of the starting thumbnail.
+ *
+ * Note that {@link #screenSpaceBounds} is the end bounds of a transition.
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public final Rect startBounds;
@@ -247,7 +254,8 @@
Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position,
Rect localBounds, Rect screenSpaceBounds,
WindowConfiguration windowConfig, boolean isNotInRecents,
- SurfaceControl startLeash, Rect startBounds, ActivityManager.RunningTaskInfo taskInfo,
+ SurfaceControl startLeash, @Nullable Rect startBounds,
+ ActivityManager.RunningTaskInfo taskInfo,
boolean allowEnterPip) {
this(taskId, mode, leash, isTranslucent, clipRect, contentInsets, prefixOrderIndex,
position, localBounds, screenSpaceBounds, windowConfig, isNotInRecents, startLeash,
@@ -258,7 +266,7 @@
Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position,
Rect localBounds, Rect screenSpaceBounds,
WindowConfiguration windowConfig, boolean isNotInRecents,
- SurfaceControl startLeash, Rect startBounds,
+ SurfaceControl startLeash, @Nullable Rect startBounds,
ActivityManager.RunningTaskInfo taskInfo, boolean allowEnterPip,
@WindowManager.LayoutParams.WindowType int windowType) {
this.mode = mode;
@@ -275,10 +283,13 @@
this.windowConfiguration = windowConfig;
this.isNotInRecents = isNotInRecents;
this.startLeash = startLeash;
- this.startBounds = startBounds == null ? null : new Rect(startBounds);
this.taskInfo = taskInfo;
this.allowEnterPip = allowEnterPip;
this.windowType = windowType;
+ // Same as screenSpaceBounds if the window is not resizing.
+ this.startBounds = startBounds == null
+ ? new Rect(screenSpaceBounds)
+ : new Rect(startBounds);
}
public RemoteAnimationTarget(Parcel in) {
@@ -399,9 +410,7 @@
if (startLeash != null) {
startLeash.dumpDebug(proto, START_LEASH);
}
- if (startBounds != null) {
- startBounds.dumpDebug(proto, START_BOUNDS);
- }
+ startBounds.dumpDebug(proto, START_BOUNDS);
proto.end(token);
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0f970bf..09a9d46 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -853,7 +853,12 @@
private SurfaceSyncGroup mSyncGroup;
private SurfaceSyncGroup.TransactionReadyCallback mTransactionReadyCallback;
- private int mNumSyncsInProgress = 0;
+
+ private static final Object sSyncProgressLock = new Object();
+ // The count needs to be static since it's used to enable or disable RT animations which is
+ // done at a global level per process. If any VRI syncs are in progress, we can't enable RT
+ // animations until all are done.
+ private static int sNumSyncsInProgress = 0;
private HashSet<ScrollCaptureCallback> mRootScrollCaptureCallbacks;
@@ -11229,13 +11234,6 @@
});
}
- private final Executor mPostAtFrontExecutor = new Executor() {
- @Override
- public void execute(Runnable command) {
- mHandler.postAtFrontOfQueue(command);
- }
- };
-
public final SurfaceSyncGroup.SyncTarget mSyncTarget = new SurfaceSyncGroup.SyncTarget() {
@Override
public void onAddedToSyncGroup(SurfaceSyncGroup parentSyncGroup,
@@ -11245,9 +11243,6 @@
// Always sync the buffer if the sync request did not come from VRI.
mSyncBuffer = true;
}
- if (mAttachInfo.mThreadedRenderer != null) {
- HardwareRenderer.setRtAnimationsEnabled(false);
- }
if (mTransactionReadyCallback != null) {
Log.d(mTag, "Already set sync for the next draw.");
@@ -11261,16 +11256,29 @@
scheduleTraversals();
}
}
+ };
- private void updateSyncInProgressCount(SurfaceSyncGroup parentSyncGroup) {
- mNumSyncsInProgress++;
- parentSyncGroup.addSyncCompleteCallback(mPostAtFrontExecutor, () -> {
- if (--mNumSyncsInProgress == 0 && mAttachInfo.mThreadedRenderer != null) {
+ private final Executor mSimpleExecutor = Runnable::run;
+
+ private void updateSyncInProgressCount(SurfaceSyncGroup syncGroup) {
+ if (mAttachInfo.mThreadedRenderer == null) {
+ return;
+ }
+
+ synchronized (sSyncProgressLock) {
+ if (sNumSyncsInProgress++ == 0) {
+ HardwareRenderer.setRtAnimationsEnabled(false);
+ }
+ }
+
+ syncGroup.addSyncCompleteCallback(mSimpleExecutor, () -> {
+ synchronized (sSyncProgressLock) {
+ if (--sNumSyncsInProgress == 0) {
HardwareRenderer.setRtAnimationsEnabled(true);
}
- });
- }
- };
+ }
+ });
+ }
@Override
public SurfaceSyncGroup.SyncTarget getSyncTarget() {
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index a251948..364c7c8 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -27,6 +27,7 @@
import android.view.accessibility.IAccessibilityManagerClient;
import android.view.accessibility.AccessibilityWindowAttributes;
import android.view.accessibility.IWindowMagnificationConnection;
+import android.view.InputEvent;
import android.view.IWindow;
/**
@@ -114,4 +115,7 @@
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY)")
boolean unregisterProxyForDisplay(int displayId);
+
+ // Used by UiAutomation for tests on the InputFilter
+ void injectInputEventToInputFilter(in InputEvent event);
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 5740f86..0a3ea8a 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2054,7 +2054,10 @@
}
}
- void onDraw(Canvas canvas, Layout layout, Path highlight, Paint highlightPaint,
+ void onDraw(Canvas canvas, Layout layout,
+ List<Path> highlightPaths,
+ List<Paint> highlightPaints,
+ Path selectionHighlight, Paint selectionHighlightPaint,
int cursorOffsetVertical) {
final int selectionStart = mTextView.getSelectionStart();
final int selectionEnd = mTextView.getSelectionEnd();
@@ -2078,37 +2081,41 @@
mCorrectionHighlighter.draw(canvas, cursorOffsetVertical);
}
- if (highlight != null && selectionStart == selectionEnd && mDrawableForCursor != null) {
+ if (selectionHighlight != null && selectionStart == selectionEnd
+ && mDrawableForCursor != null
+ && !mTextView.hasGesturePreviewHighlight()) {
drawCursor(canvas, cursorOffsetVertical);
// Rely on the drawable entirely, do not draw the cursor line.
// Has to be done after the IMM related code above which relies on the highlight.
- highlight = null;
+ selectionHighlight = null;
}
if (mSelectionActionModeHelper != null) {
mSelectionActionModeHelper.onDraw(canvas);
if (mSelectionActionModeHelper.isDrawingHighlight()) {
- highlight = null;
+ selectionHighlight = null;
}
}
if (mTextView.canHaveDisplayList() && canvas.isHardwareAccelerated()) {
- drawHardwareAccelerated(canvas, layout, highlight, highlightPaint,
- cursorOffsetVertical);
+ drawHardwareAccelerated(canvas, layout, highlightPaths, highlightPaints,
+ selectionHighlight, selectionHighlightPaint, cursorOffsetVertical);
} else {
- layout.draw(canvas, highlight, highlightPaint, cursorOffsetVertical);
+ layout.draw(canvas, highlightPaths, highlightPaints, selectionHighlight,
+ selectionHighlightPaint, cursorOffsetVertical);
}
}
- private void drawHardwareAccelerated(Canvas canvas, Layout layout, Path highlight,
- Paint highlightPaint, int cursorOffsetVertical) {
+ private void drawHardwareAccelerated(Canvas canvas, Layout layout,
+ List<Path> highlightPaths, List<Paint> highlightPaints,
+ Path selectionHighlight, Paint selectionHighlightPaint, int cursorOffsetVertical) {
final long lineRange = layout.getLineRangeForDraw(canvas);
int firstLine = TextUtils.unpackRangeStartFromLong(lineRange);
int lastLine = TextUtils.unpackRangeEndFromLong(lineRange);
if (lastLine < 0) return;
- layout.drawBackground(canvas, highlight, highlightPaint, cursorOffsetVertical,
- firstLine, lastLine);
+ layout.drawWithoutText(canvas, highlightPaths, highlightPaints, selectionHighlight,
+ selectionHighlightPaint, cursorOffsetVertical, firstLine, lastLine);
if (layout instanceof DynamicLayout) {
if (mTextRenderNodes == null) {
@@ -2154,8 +2161,9 @@
continue;
}
startIndexToFindAvailableRenderNode = drawHardwareAcceleratedInner(canvas, layout,
- highlight, highlightPaint, cursorOffsetVertical, blockEndLines,
- blockIndices, i, numberOfBlocks, startIndexToFindAvailableRenderNode);
+ selectionHighlight, selectionHighlightPaint, cursorOffsetVertical,
+ blockEndLines, blockIndices, i, numberOfBlocks,
+ startIndexToFindAvailableRenderNode);
if (blockEndLines[i] >= lastLine) {
lastIndex = Math.max(indexFirstChangedBlock, i + 1);
break;
@@ -2169,9 +2177,9 @@
|| mTextRenderNodes[blockIndex] == null
|| mTextRenderNodes[blockIndex].needsToBeShifted) {
startIndexToFindAvailableRenderNode = drawHardwareAcceleratedInner(canvas,
- layout, highlight, highlightPaint, cursorOffsetVertical,
- blockEndLines, blockIndices, block, numberOfBlocks,
- startIndexToFindAvailableRenderNode);
+ layout, selectionHighlight, selectionHighlightPaint,
+ cursorOffsetVertical, blockEndLines, blockIndices, block,
+ numberOfBlocks, startIndexToFindAvailableRenderNode);
}
}
}
@@ -2707,7 +2715,7 @@
unregisterOnBackInvokedCallback();
}
- private void stopTextActionModeWithPreservingSelection() {
+ void stopTextActionModeWithPreservingSelection() {
if (mTextActionMode != null) {
mRestartActionModeOnNextRefresh = true;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index bf1a2bd..b9b928e 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -68,6 +68,7 @@
import android.graphics.BaseCanvas;
import android.graphics.BlendMode;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Paint;
@@ -87,6 +88,7 @@
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
+import android.os.CancellationSignal;
import android.os.Handler;
import android.os.LocaleList;
import android.os.Parcel;
@@ -102,6 +104,7 @@
import android.text.GetChars;
import android.text.GraphemeClusterSegmentFinder;
import android.text.GraphicsOperations;
+import android.text.Highlights;
import android.text.InputFilter;
import android.text.InputType;
import android.text.Layout;
@@ -147,6 +150,7 @@
import android.text.style.URLSpan;
import android.text.style.UpdateAppearance;
import android.text.util.Linkify;
+import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.FeatureFlagUtils;
@@ -198,6 +202,7 @@
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InsertGesture;
import android.view.inputmethod.JoinOrSplitGesture;
+import android.view.inputmethod.PreviewableHandwritingGesture;
import android.view.inputmethod.RemoveSpaceGesture;
import android.view.inputmethod.SelectGesture;
import android.view.inputmethod.SelectRangeGesture;
@@ -221,6 +226,7 @@
import com.android.internal.accessibility.util.AccessibilityUtils;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.graphics.ColorUtils;
import com.android.internal.inputmethod.EditableInputConnection;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -238,8 +244,10 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.Locale;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@@ -926,6 +934,15 @@
@UnsupportedAppUsage
private boolean mHighlightPathBogus = true;
+ private List<Path> mHighlightPaths;
+ private List<Paint> mHighlightPaints;
+ private Highlights mHighlights;
+ private int mGesturePreviewHighlightStart = -1;
+ private int mGesturePreviewHighlightEnd = -1;
+ private Paint mGesturePreviewHighlightPaint;
+ private final List<Path> mPathRecyclePool = new ArrayList<>();
+ private boolean mHighlightPathsBogus = true;
+
// Although these fields are specific to editable text, they are not added to Editor because
// they are defined by the TextView's style and are theme-dependent.
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
@@ -6131,6 +6148,87 @@
}
/**
+ * Set Highlights
+ *
+ * @param highlights A highlight object. Call with null for reset.
+ *
+ * @see #getHighlights()
+ * @see Highlights
+ */
+ public void setHighlights(@Nullable Highlights highlights) {
+ mHighlights = highlights;
+ mHighlightPathsBogus = true;
+ invalidate();
+ }
+
+ /**
+ * Returns highlights
+ *
+ * @return a highlight to be drawn. null if no highlight was set.
+ *
+ * @see #setHighlights(Highlights)
+ * @see Highlights
+ *
+ */
+ @Nullable
+ public Highlights getHighlights() {
+ return mHighlights;
+ }
+
+ /**
+ * Highlights the text range (from inclusive start offset to exclusive end offset) to show what
+ * will be selected by the ongoing select handwriting gesture. While the gesture preview
+ * highlight is shown, the selection or cursor is hidden. If the text or selection is changed,
+ * the gesture preview highlight will be cleared.
+ */
+ private void setSelectGesturePreviewHighlight(int start, int end) {
+ // Selection preview highlight color is the same as selection highlight color.
+ setGesturePreviewHighlight(start, end, mHighlightColor);
+ }
+
+ /**
+ * Highlights the text range (from inclusive start offset to exclusive end offset) to show what
+ * will be deleted by the ongoing delete handwriting gesture. While the gesture preview
+ * highlight is shown, the selection or cursor is hidden. If the text or selection is changed,
+ * the gesture preview highlight will be cleared.
+ */
+ private void setDeleteGesturePreviewHighlight(int start, int end) {
+ // Deletion preview highlight color is 20% opacity of the default text color.
+ int color = mTextColor.getDefaultColor();
+ color = ColorUtils.setAlphaComponent(color, (int) (0.2f * Color.alpha(color)));
+ setGesturePreviewHighlight(start, end, color);
+ }
+
+ private void setGesturePreviewHighlight(int start, int end, int color) {
+ mGesturePreviewHighlightStart = start;
+ mGesturePreviewHighlightEnd = end;
+ if (mGesturePreviewHighlightPaint == null) {
+ mGesturePreviewHighlightPaint = new Paint();
+ mGesturePreviewHighlightPaint.setStyle(Paint.Style.FILL);
+ }
+ mGesturePreviewHighlightPaint.setColor(color);
+
+ if (mEditor != null) {
+ mEditor.hideCursorAndSpanControllers();
+ mEditor.stopTextActionModeWithPreservingSelection();
+ }
+
+ mHighlightPathsBogus = true;
+ invalidate();
+ }
+
+ private void clearGesturePreviewHighlight() {
+ mGesturePreviewHighlightStart = -1;
+ mGesturePreviewHighlightEnd = -1;
+ mHighlightPathsBogus = true;
+ invalidate();
+ }
+
+ boolean hasGesturePreviewHighlight() {
+ return mGesturePreviewHighlightStart > 0;
+ }
+
+ /**
* Convenience method to append the specified text to the TextView's
* display buffer, upgrading it to {@link android.widget.TextView.BufferType#EDITABLE}
* if it was not already editable.
@@ -8219,6 +8317,70 @@
return drawableState;
}
+ private void maybeUpdateHighlightPaths() {
+ if (!mHighlightPathsBogus) {
+ return;
+ }
+
+ if (mHighlightPaths != null) {
+ mPathRecyclePool.addAll(mHighlightPaths);
+ mHighlightPaths.clear();
+ mHighlightPaints.clear();
+ } else {
+ mHighlightPaths = new ArrayList<>();
+ mHighlightPaints = new ArrayList<>();
+ }
+
+ if (mHighlights != null) {
+ for (int i = 0; i < mHighlights.getSize(); ++i) {
+ final int[] ranges = mHighlights.getRanges(i);
+ final Paint paint = mHighlights.getPaint(i);
+
+ final Path path;
+ if (mPathRecyclePool.isEmpty()) {
+ path = new Path();
+ } else {
+ path = mPathRecyclePool.get(mPathRecyclePool.size() - 1);
+ mPathRecyclePool.remove(mPathRecyclePool.size() - 1);
+ path.reset();
+ }
+
+ boolean atLeastOnePathAdded = false;
+ for (int j = 0; j < ranges.length / 2; ++j) {
+ final int start = ranges[2 * j];
+ final int end = ranges[2 * j + 1];
+ if (start < end) {
+ mLayout.getSelection(start, end, (left, top, right, bottom, layout) ->
+ path.addRect(left, top, right, bottom, Path.Direction.CW)
+ );
+ atLeastOnePathAdded = true;
+ }
+ }
+ if (atLeastOnePathAdded) {
+ mHighlightPaths.add(path);
+ mHighlightPaints.add(paint);
+ }
+ }
+ }
+
+ if (hasGesturePreviewHighlight()) {
+ final Path path;
+ if (mPathRecyclePool.isEmpty()) {
+ path = new Path();
+ } else {
+ path = mPathRecyclePool.get(mPathRecyclePool.size() - 1);
+ mPathRecyclePool.remove(mPathRecyclePool.size() - 1);
+ path.reset();
+ }
+ mLayout.getSelectionPath(
+ mGesturePreviewHighlightStart, mGesturePreviewHighlightEnd, path);
+ mHighlightPaths.add(path);
+ mHighlightPaints.add(mGesturePreviewHighlightPaint);
+ }
+
+ mHighlightPathsBogus = false;
+ }
+
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private Path getUpdatedHighlightPath() {
Path highlight = null;
@@ -8418,17 +8580,22 @@
final int cursorOffsetVertical = voffsetCursor - voffsetText;
- Path highlight = getUpdatedHighlightPath();
+ maybeUpdateHighlightPaths();
+ // If there is a gesture preview highlight, then the selection or cursor is not drawn.
+ Path highlight = hasGesturePreviewHighlight() ? null : getUpdatedHighlightPath();
if (mEditor != null) {
- mEditor.onDraw(canvas, layout, highlight, mHighlightPaint, cursorOffsetVertical);
+ mEditor.onDraw(canvas, layout, mHighlightPaths, mHighlightPaints, highlight,
+ mHighlightPaint, cursorOffsetVertical);
} else {
- layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
+ layout.draw(canvas, mHighlightPaths, mHighlightPaints, highlight, mHighlightPaint,
+ cursorOffsetVertical);
}
if (mMarquee != null && mMarquee.shouldDrawGhost()) {
final float dx = mMarquee.getGhostOffset();
canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
- layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
+ layout.draw(canvas, mHighlightPaths, mHighlightPaints, highlight, mHighlightPaint,
+ cursorOffsetVertical);
}
canvas.restore();
@@ -9112,6 +9279,14 @@
gestures.add(RemoveSpaceGesture.class);
gestures.add(JoinOrSplitGesture.class);
outAttrs.setSupportedHandwritingGestures(gestures);
+
+ Set<Class<? extends PreviewableHandwritingGesture>> previews = new ArraySet<>();
+ previews.add(SelectGesture.class);
+ previews.add(SelectRangeGesture.class);
+ previews.add(DeleteGesture.class);
+ previews.add(DeleteRangeGesture.class);
+ outAttrs.setSupportedHandwritingGesturePreviews(previews);
+
return ic;
}
}
@@ -9323,83 +9498,130 @@
}
/** @hide */
+ public boolean previewHandwritingGesture(
+ @NonNull PreviewableHandwritingGesture gesture,
+ @Nullable CancellationSignal cancellationSignal) {
+ if (gesture instanceof SelectGesture) {
+ performHandwritingSelectGesture((SelectGesture) gesture, /* isPreview= */ true);
+ } else if (gesture instanceof SelectRangeGesture) {
+ performHandwritingSelectRangeGesture(
+ (SelectRangeGesture) gesture, /* isPreview= */ true);
+ } else if (gesture instanceof DeleteGesture) {
+ performHandwritingDeleteGesture((DeleteGesture) gesture, /* isPreview= */ true);
+ } else if (gesture instanceof DeleteRangeGesture) {
+ performHandwritingDeleteRangeGesture(
+ (DeleteRangeGesture) gesture, /* isPreview= */ true);
+ } else {
+ return false;
+ }
+ if (cancellationSignal != null) {
+ cancellationSignal.setOnCancelListener(this::clearGesturePreviewHighlight);
+ }
+ return true;
+ }
+
+ /** @hide */
public int performHandwritingSelectGesture(@NonNull SelectGesture gesture) {
+ return performHandwritingSelectGesture(gesture, /* isPreview= */ false);
+ }
+
+ private int performHandwritingSelectGesture(@NonNull SelectGesture gesture, boolean isPreview) {
int[] range = getRangeForRect(
convertFromScreenToContentCoordinates(gesture.getSelectionArea()),
gesture.getGranularity());
if (range == null) {
- return handleGestureFailure(gesture);
+ return handleGestureFailure(gesture, isPreview);
}
- Selection.setSelection(getEditableText(), range[0], range[1]);
- mEditor.startSelectionActionModeAsync(/* adjustSelection= */ false);
+ return performHandwritingSelectGesture(range, isPreview);
+ }
+
+ private int performHandwritingSelectGesture(int[] range, boolean isPreview) {
+ if (isPreview) {
+ setSelectGesturePreviewHighlight(range[0], range[1]);
+ } else {
+ Selection.setSelection(getEditableText(), range[0], range[1]);
+ mEditor.startSelectionActionModeAsync(/* adjustSelection= */ false);
+ }
return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS;
}
/** @hide */
public int performHandwritingSelectRangeGesture(@NonNull SelectRangeGesture gesture) {
+ return performHandwritingSelectRangeGesture(gesture, /* isPreview= */ false);
+ }
+
+ private int performHandwritingSelectRangeGesture(
+ @NonNull SelectRangeGesture gesture, boolean isPreview) {
int[] startRange = getRangeForRect(
convertFromScreenToContentCoordinates(gesture.getSelectionStartArea()),
gesture.getGranularity());
if (startRange == null) {
- return handleGestureFailure(gesture);
+ return handleGestureFailure(gesture, isPreview);
}
int[] endRange = getRangeForRect(
convertFromScreenToContentCoordinates(gesture.getSelectionEndArea()),
gesture.getGranularity());
if (endRange == null) {
- return handleGestureFailure(gesture);
+ return handleGestureFailure(gesture, isPreview);
}
int[] range = new int[] {
Math.min(startRange[0], endRange[0]), Math.max(startRange[1], endRange[1])
};
- Selection.setSelection(getEditableText(), range[0], range[1]);
- mEditor.startSelectionActionModeAsync(/* adjustSelection= */ false);
- return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS;
+ return performHandwritingSelectGesture(range, isPreview);
}
/** @hide */
public int performHandwritingDeleteGesture(@NonNull DeleteGesture gesture) {
+ return performHandwritingDeleteGesture(gesture, /* isPreview= */ false);
+ }
+
+ private int performHandwritingDeleteGesture(@NonNull DeleteGesture gesture, boolean isPreview) {
int[] range = getRangeForRect(
convertFromScreenToContentCoordinates(gesture.getDeletionArea()),
gesture.getGranularity());
if (range == null) {
- return handleGestureFailure(gesture);
+ return handleGestureFailure(gesture, isPreview);
}
+ return performHandwritingDeleteGesture(range, gesture.getGranularity(), isPreview);
+ }
- if (gesture.getGranularity() == HandwritingGesture.GRANULARITY_WORD) {
- range = adjustHandwritingDeleteGestureRange(range);
+ private int performHandwritingDeleteGesture(int[] range, int granularity, boolean isPreview) {
+ if (isPreview) {
+ setDeleteGesturePreviewHighlight(range[0], range[1]);
+ } else {
+ if (granularity == HandwritingGesture.GRANULARITY_WORD) {
+ range = adjustHandwritingDeleteGestureRange(range);
+ }
+
+ getEditableText().delete(range[0], range[1]);
+ Selection.setSelection(getEditableText(), range[0]);
}
-
- getEditableText().delete(range[0], range[1]);
- Selection.setSelection(getEditableText(), range[0]);
return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS;
}
/** @hide */
public int performHandwritingDeleteRangeGesture(@NonNull DeleteRangeGesture gesture) {
+ return performHandwritingDeleteRangeGesture(gesture, /* isPreview= */ false);
+ }
+
+ private int performHandwritingDeleteRangeGesture(
+ @NonNull DeleteRangeGesture gesture, boolean isPreview) {
int[] startRange = getRangeForRect(
convertFromScreenToContentCoordinates(gesture.getDeletionStartArea()),
gesture.getGranularity());
if (startRange == null) {
- return handleGestureFailure(gesture);
+ return handleGestureFailure(gesture, isPreview);
}
int[] endRange = getRangeForRect(
convertFromScreenToContentCoordinates(gesture.getDeletionEndArea()),
gesture.getGranularity());
if (endRange == null) {
- return handleGestureFailure(gesture);
+ return handleGestureFailure(gesture, isPreview);
}
int[] range = new int[] {
Math.min(startRange[0], endRange[0]), Math.max(startRange[1], endRange[1])
};
-
- if (gesture.getGranularity() == HandwritingGesture.GRANULARITY_WORD) {
- range = adjustHandwritingDeleteGestureRange(range);
- }
-
- getEditableText().delete(range[0], range[1]);
- Selection.setSelection(getEditableText(), range[0]);
- return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS;
+ return performHandwritingDeleteGesture(range, gesture.getGranularity(), isPreview);
}
private int[] adjustHandwritingDeleteGestureRange(int[] range) {
@@ -9577,7 +9799,12 @@
}
private int handleGestureFailure(HandwritingGesture gesture) {
- if (!TextUtils.isEmpty(gesture.getFallbackText())) {
+ return handleGestureFailure(gesture, /* isPreview= */ false);
+ }
+
+ private int handleGestureFailure(HandwritingGesture gesture, boolean isPreview) {
+ clearGesturePreviewHighlight();
+ if (!isPreview && !TextUtils.isEmpty(gesture.getFallbackText())) {
getEditableText()
.replace(getSelectionStart(), getSelectionEnd(), gesture.getFallbackText());
return InputConnection.HANDWRITING_GESTURE_RESULT_FALLBACK;
@@ -9750,6 +9977,7 @@
mOldMaxMode = mMaxMode;
mHighlightPathBogus = true;
+ mHighlightPathsBogus = true;
if (wantWidth < 0) {
wantWidth = 0;
@@ -11610,6 +11838,8 @@
resetErrorChangedFlag();
sendOnTextChanged(buffer, start, before, after);
onTextChanged(buffer, start, before, after);
+
+ clearGesturePreviewHighlight();
}
/**
@@ -11648,6 +11878,7 @@
}
if (selChanged) {
+ clearGesturePreviewHighlight();
mHighlightPathBogus = true;
if (mEditor != null && !isFocused()) mEditor.mSelectionMoved = true;
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 292a50b..4f7f8ba 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -556,6 +556,12 @@
"show_stop_button_for_user_allowlisted_apps";
/**
+ * (boolean) Whether the task manager should show apps running user-visible jobs.
+ */
+ public static final String TASK_MANAGER_SHOW_USER_VISIBLE_JOBS =
+ "task_manager_show_user_visible_jobs";
+
+ /**
* (boolean) Whether to show notification volume control slider separate from ring.
*/
public static final String VOLUME_SEPARATE_NOTIFICATION = "volume_separate_notification";
diff --git a/core/java/com/android/internal/content/om/OverlayConfig.java b/core/java/com/android/internal/content/om/OverlayConfig.java
index 828e5cf..2d04bdb 100644
--- a/core/java/com/android/internal/content/om/OverlayConfig.java
+++ b/core/java/com/android/internal/content/om/OverlayConfig.java
@@ -140,7 +140,6 @@
ArrayMap<Integer, List<String>> activeApexesPerPartition = getActiveApexes(partitions);
- boolean foundConfigFile = false;
final Map<String, ParsedOverlayInfo> packageManagerOverlayInfos =
packageProvider == null ? null : getOverlayPackageInfos(packageProvider);
@@ -154,7 +153,6 @@
activeApexesPerPartition.getOrDefault(partition.type,
Collections.emptyList()));
if (partitionOverlays != null) {
- foundConfigFile = true;
overlays.addAll(partitionOverlays);
continue;
}
@@ -191,12 +189,6 @@
overlays.addAll(partitionConfigs);
}
- if (!foundConfigFile) {
- // If no overlay configuration files exist, disregard partition precedence and allow
- // android:priority to reorder overlays across partition boundaries.
- overlays.sort(sStaticOverlayComparator);
- }
-
for (int i = 0, n = overlays.size(); i < n; i++) {
// Add the configurations to a map so definitions of an overlay in an earlier
// partition can be replaced by an overlay with the same package name in a later
diff --git a/core/java/com/android/internal/inputmethod/EditableInputConnection.java b/core/java/com/android/internal/inputmethod/EditableInputConnection.java
index 330ff8e..52e7471 100644
--- a/core/java/com/android/internal/inputmethod/EditableInputConnection.java
+++ b/core/java/com/android/internal/inputmethod/EditableInputConnection.java
@@ -27,6 +27,7 @@
import android.annotation.Nullable;
import android.graphics.RectF;
import android.os.Bundle;
+import android.os.CancellationSignal;
import android.text.Editable;
import android.text.Selection;
import android.text.method.KeyListener;
@@ -44,6 +45,7 @@
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InsertGesture;
import android.view.inputmethod.JoinOrSplitGesture;
+import android.view.inputmethod.PreviewableHandwritingGesture;
import android.view.inputmethod.RemoveSpaceGesture;
import android.view.inputmethod.SelectGesture;
import android.view.inputmethod.SelectRangeGesture;
@@ -321,6 +323,13 @@
}
@Override
+ public boolean previewHandwritingGesture(
+ @NonNull PreviewableHandwritingGesture gesture,
+ @Nullable CancellationSignal cancellationSignal) {
+ return mTextView.previewHandwritingGesture(gesture, cancellationSignal);
+ }
+
+ @Override
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
CharSequence editableText = mTextView.getText();
diff --git a/core/jni/android_hardware_display_DisplayViewport.cpp b/core/jni/android_hardware_display_DisplayViewport.cpp
index 03432e9..7f630cb 100644
--- a/core/jni/android_hardware_display_DisplayViewport.cpp
+++ b/core/jni/android_hardware_display_DisplayViewport.cpp
@@ -61,7 +61,8 @@
viewport->displayId = env->GetIntField(viewportObj, gDisplayViewportClassInfo.displayId);
viewport->isActive = env->GetBooleanField(viewportObj, gDisplayViewportClassInfo.isActive);
- viewport->orientation = env->GetIntField(viewportObj, gDisplayViewportClassInfo.orientation);
+ jint orientation = env->GetIntField(viewportObj, gDisplayViewportClassInfo.orientation);
+ viewport->orientation = static_cast<ui::Rotation>(orientation);
viewport->deviceWidth = env->GetIntField(viewportObj, gDisplayViewportClassInfo.deviceWidth);
viewport->deviceHeight = env->GetIntField(viewportObj, gDisplayViewportClassInfo.deviceHeight);
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 80df0ea..403c583 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -763,7 +763,12 @@
static jint android_view_MotionEvent_nativeGetSurfaceRotation(jlong nativePtr) {
MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
- return jint(event->getSurfaceRotation());
+ auto rotation = event->getSurfaceRotation();
+ if (rotation) {
+ return static_cast<jint>(rotation.value());
+ } else {
+ return -1;
+ }
}
// ----------------------------------------------------------------------------
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 37220ed..f5e3009 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Stemboodskap"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Verbindingsprobleem of ongeldige MMI-kode."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Kenmerk word nie gesteun nie."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Bewerking is beperk tot belbeperking-nommers."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Kan oproep-aanstuurinstellings nie van jou foon af verander tewyl jy swerf nie."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Diens is geaktiveer."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 49a0b7a..305cefa 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -28,6 +28,8 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"የድምፅ መልዕክት"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"የተያያዥ ችግር ወይም ትክከል ያልሆነየMMI ኮድ ባህሪ።"</string>
+ <!-- no translation found for mmiErrorNotSupported (5001803469335286099) -->
+ <skip />
<string name="mmiFdnError" msgid="3975490266767565852">"ክዋኔ ለቋሚ መደወያ ቁጥሮች ብቻ ተገድቧል።"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Can not change call forwarding settings from your phone while you are roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"አገልግሎት ነቅቶ ነበር።"</string>
@@ -395,54 +397,30 @@
<string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"መተግበሪያው የራሱን ክፍሎች በማህደረ ትውስታ ውስጥ በቋሚነት የሚቀጥሉ እንዲያደርግ ይፈቅድለታል። ይህ ለሌላ መተግበሪያዎች ያለውን ማህደረ ትውስታ በመገደብ ስልኩን ያንቀራፍፈዋል።"</string>
<string name="permlab_foregroundService" msgid="1768855976818467491">"የፊት አገልግሎትን ማሄድ"</string>
<string name="permdesc_foregroundService" msgid="8720071450020922795">"መተግበሪያው ፊት ላይ ያሉ አገልግሎቶችን እንዲጠቀም ያስችለዋል።"</string>
- <!-- no translation found for permlab_foregroundServiceCamera (7814751737955715297) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceCamera (6973701931250595727) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceConnectedDevice (3019650546176872501) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceConnectedDevice (1067457315741352963) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceDataSync (5847463514326881076) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceDataSync (2267140263423973050) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceLocation (3745428302378535690) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceLocation (118894034365177183) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaPlayback (4002687983891935514) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaPlayback (3638032446063968043) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaProjection (2630868915733312527) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaProjection (4805677128082002298) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMicrophone (7390033424890545399) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMicrophone (1206041516173483201) -->
- <skip />
- <!-- no translation found for permlab_foregroundServicePhoneCall (627937743867697892) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServicePhoneCall (5941660252587015147) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceHealth (3675776442080928184) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceHealth (2024586220562667185) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceRemoteMessaging (105670277002780950) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceRemoteMessaging (8767598075877576277) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSystemExempted (1597663713590612685) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSystemExempted (947381760834649622) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSpecialUse (7973536745876645082) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSpecialUse (646713654541885919) -->
- <skip />
+ <string name="permlab_foregroundServiceCamera" msgid="7814751737955715297">"የፊት አገልግሎትን በ«ካሜራ» ዓይነት ማስሄድ"</string>
+ <string name="permdesc_foregroundServiceCamera" msgid="6973701931250595727">"መተግበሪያው የፊት አገልግሎትን በ«ካሜራ» ዓይነት እንዲጠቀም ይፈቅዳል"</string>
+ <string name="permlab_foregroundServiceConnectedDevice" msgid="3019650546176872501">"የፊት አገልግሎትን በ«connectedDevice» ዓይነት ማስሄድ"</string>
+ <string name="permdesc_foregroundServiceConnectedDevice" msgid="1067457315741352963">"መተግበሪያው የፊት አገልግሎትን በ«connectedDevice» ዓይነት እንዲጠቀም ይፈቅዳል"</string>
+ <string name="permlab_foregroundServiceDataSync" msgid="5847463514326881076">"የፊት አገልግሎትን በ«dataSync» ዓይነት ማስሄድ"</string>
+ <string name="permdesc_foregroundServiceDataSync" msgid="2267140263423973050">"መተግበሪያው የፊት አገልግሎትን በ«dataSync» ዓይነት እንዲጠቀም ይፈቅዳል"</string>
+ <string name="permlab_foregroundServiceLocation" msgid="3745428302378535690">"የፊት አገልግሎትን በ«አካባቢ» ዓይነት ማስሄድ"</string>
+ <string name="permdesc_foregroundServiceLocation" msgid="118894034365177183">"መተግበሪያው የፊት አገልግሎትን በ«አካባቢ» ዓይነት እንዲጠቀም ይፈቅዳል"</string>
+ <string name="permlab_foregroundServiceMediaPlayback" msgid="4002687983891935514">"የፊት አገልግሎትን በ«mediaPlayback» ዓይነት ማስሄድ"</string>
+ <string name="permdesc_foregroundServiceMediaPlayback" msgid="3638032446063968043">"መተግበሪያው የፊት አገልግሎትን በ«mediaPlayback» ዓይነት እንዲጠቀም ይፈቅዳል"</string>
+ <string name="permlab_foregroundServiceMediaProjection" msgid="2630868915733312527">"የፊት አገልግሎትን በ«mediaProjection» ዓይነት ማስሄድ"</string>
+ <string name="permdesc_foregroundServiceMediaProjection" msgid="4805677128082002298">"መተግበሪያው የፊት አገልግሎትን በ«mediaProjection» ዓይነት እንዲጠቀም ይፈቅዳል"</string>
+ <string name="permlab_foregroundServiceMicrophone" msgid="7390033424890545399">"የፊት አገልግሎትን በ«ማይክሮፎን» ዓይነት ማስሄድ"</string>
+ <string name="permdesc_foregroundServiceMicrophone" msgid="1206041516173483201">"መተግበሪያው የፊት አገልግሎትን በ«ማይክሮፎን» ዓይነት እንዲጠቀም ይፈቅዳል"</string>
+ <string name="permlab_foregroundServicePhoneCall" msgid="627937743867697892">"የፊት አገልግሎትን በ«phoneCall» ዓይነት ማስሄድ"</string>
+ <string name="permdesc_foregroundServicePhoneCall" msgid="5941660252587015147">"መተግበሪያው የፊት አገልግሎትን በ«phoneCall» ዓይነት እንዲጠቀም ይፈቅዳል"</string>
+ <string name="permlab_foregroundServiceHealth" msgid="3675776442080928184">"የፊት አገልግሎትን በ«ጤና» ዓይነት ማስሄድ"</string>
+ <string name="permdesc_foregroundServiceHealth" msgid="2024586220562667185">"መተግበሪያው የፊት አገልግሎትን በ«ጤና» ዓይነት እንዲጠቀም ይፈቅዳል"</string>
+ <string name="permlab_foregroundServiceRemoteMessaging" msgid="105670277002780950">"የፊት አገልግሎትን በ«remoteMessaging» ዓይነት ማስሄድ"</string>
+ <string name="permdesc_foregroundServiceRemoteMessaging" msgid="8767598075877576277">"መተግበሪያው የፊት አገልግሎትን በ«remoteMessaging» ዓይነት እንዲጠቀም ይፈቅዳል"</string>
+ <string name="permlab_foregroundServiceSystemExempted" msgid="1597663713590612685">"የፊት አገልግሎትን በ«systemExempted» ዓይነት ማስሄድ"</string>
+ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"መተግበሪያው የፊት አገልግሎትን በ«systemExempted» ዓይነት እንዲጠቀም ይፈቅዳል"</string>
+ <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"የፊት አገልግሎትን በ«specialUse» ዓይነት ማስሄድ"</string>
+ <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"መተግበሪያው የፊት አገልግሎትን በ«specialUse» ዓይነት እንዲጠቀም ይፈቅዳል"</string>
<string name="permlab_getPackageSize" msgid="375391550792886641">"የመተግበሪያ ማከማቻ ቦታ ለካ"</string>
<string name="permdesc_getPackageSize" msgid="742743530909966782">"የራሱን ኮድ ፣ውሂብ እና መሸጎጫ መጠኖች ሰርስሮ ለማውጣት ለመተግበሪያው ይፈቅዳሉ።"</string>
<string name="permlab_writeSettings" msgid="8057285063719277394">"የስርዓት ቅንብሮችን አስተካክል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 1db09f1..dc8ffda 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"البريد الصوتي"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"حدثت مشكلة في الاتصال أو أن رمز MMI غير صحيح."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"الميزة غير متاحة."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"تم تقييد التشغيل لأرقام الاتصال الثابت فقط."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"يتعذر تغيير إعدادات إعادة توجيه المكالمات من هاتفك أثناء التجوال."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"تم تفعيل الخدمة."</string>
@@ -2320,8 +2321,7 @@
<string name="vdm_camera_access_denied" product="default" msgid="6102378580971542473">"يتعذّر الوصول إلى كاميرا الهاتف من على جهاز <xliff:g id="DEVICE">%1$s</xliff:g>."</string>
<string name="vdm_camera_access_denied" product="tablet" msgid="6895968310395249076">"يتعذّر الوصول إلى كاميرا الجهاز اللوحي من على جهاز <xliff:g id="DEVICE">%1$s</xliff:g>."</string>
<string name="vdm_secure_window" msgid="161700398158812314">"لا يمكن الوصول إلى هذا المحتوى أثناء البث. بدلاً من ذلك، جرِّب استخدام هاتفك."</string>
- <!-- no translation found for vdm_pip_blocked (4036107522497281397) -->
- <skip />
+ <string name="vdm_pip_blocked" msgid="4036107522497281397">"لا يمكن عرض نافذة ضمن النافذة أثناء البث."</string>
<string name="system_locale_title" msgid="711882686834677268">"الإعداد التلقائي للنظام"</string>
<string name="default_card_name" msgid="9198284935962911468">"رقم البطاقة <xliff:g id="CARDNUMBER">%d</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 9a0dbfa..8f2e3f2 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"ভইচমেইল"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"সংযোগৰ সমস্যা বা MMI ক\'ড মান্য নহয়।"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"সুবিধাটো সমৰ্থিত নহয়।"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"কেৱল ফিক্সড ডায়েলিং নম্বৰৰ বাবে কার্য সীমাবদ্ধ কৰা হৈছে।"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"আপুনি ৰ\'মিঙত থকাৰ সময়ত কল ফৰৱাৰ্ডিঙৰ ছেটিং সলনি কৰিব নোৱাৰি।"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"সেৱা সক্ষম কৰা হ’ল।"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index bcee616..292f51b3 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Səsli poçt"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Bağlantı problemi və ya yalnış MM kodu."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funksiya dəstəklənmir."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Əməliyyat yalnız sabit nömrələrə yığımla məhdudlaşıb."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Roaminqdə olarkən zəng yönləndirmə ayarlarını telefonunuzdan dəyişə bilməz."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Servis işə salındı."</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 4267c7d..b1ccdf9 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Glasovna pošta"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problemi sa vezom ili nevažeći MMI kôd."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funkcija nije podržana."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Rad je ograničen samo na brojeve fiksnog biranja."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Ne možete da promenite podešavanja preusmeravanja poziva sa telefona dok ste u romingu."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Usluga je omogućena."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index e99c1cb..4cd558d 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Галасавая пошта"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Праблема падлучэння ці няправільны код MMI."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Функцыя не падтрымліваецца."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Выкарыстанне абмежаванае толькі дазволенымі нумарамі."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Немагчыма змяніць налады пераадрасацыі выклікаў з тэлефона, пакуль вы знаходзіцеся ў роўмінгу."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Служба была ўключана."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 5d1e8b5..d39425b 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Гласова поща"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Има проблем с връзката или MMI кодът е невалиден."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Функцията не се поддържа."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Операцията е ограничена само до фиксираните номера за набиране."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Докато сте в режим на роуминг, настройките за пренасочване на обажданията не могат да се променят от телефона ви."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Услугата бе активирана."</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 1ffe150..2836580 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"ভয়েসমেল"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"সংযোগ সমস্যা বা অবৈধ MMI কোড৷"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"ফিচার কাজ করে না।"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"নির্দিষ্ট নম্বরে ডায়ালযোগ্য হিসেবে প্রক্রিয়াটি সীমিত করা হয়েছে৷"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"আপনি রোমিংয়ে থাকাকালীন আপনার ফোন থেকে \'কল ফরওয়ার্ড করার সেটিংস\' পরিবর্তন করা যাবে না৷"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"পরিষেবা সক্ষম করা ছিল৷"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index f152392..0486932 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Govorna pošta"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problem sa povezivanjem ili nevažeći MMI kôd."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funkcija nije podržana."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operacija je ograničena samo na brojeve fiksnog biranja."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Nije moguće promijeniti postavke prosljeđivanja poziva s vašeg telefona dok ste u romingu."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Usluga je omogućena."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 1f267ac..8936e4f 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Bústia de veu"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problema de connexió o codi MMI no vàlid."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"La funció no s\'admet."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"L\'operació està restringida a números de marcatge fixos."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"No es pot canviar la configuració de desviació de trucades del telèfon quan estàs en itinerància."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"El servei s\'ha activat."</string>
@@ -395,54 +396,30 @@
<string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"Permet que l\'aplicació faci que parts de la seva memòria siguin persistents. Aquesta acció pot limitar la memòria disponible per a altres aplicacions i alentir el telèfon."</string>
<string name="permlab_foregroundService" msgid="1768855976818467491">"executar serveis en primer pla"</string>
<string name="permdesc_foregroundService" msgid="8720071450020922795">"Permet que l\'aplicació utilitzi serveis en primer pla."</string>
- <!-- no translation found for permlab_foregroundServiceCamera (7814751737955715297) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceCamera (6973701931250595727) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceConnectedDevice (3019650546176872501) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceConnectedDevice (1067457315741352963) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceDataSync (5847463514326881076) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceDataSync (2267140263423973050) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceLocation (3745428302378535690) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceLocation (118894034365177183) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaPlayback (4002687983891935514) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaPlayback (3638032446063968043) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaProjection (2630868915733312527) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaProjection (4805677128082002298) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMicrophone (7390033424890545399) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMicrophone (1206041516173483201) -->
- <skip />
- <!-- no translation found for permlab_foregroundServicePhoneCall (627937743867697892) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServicePhoneCall (5941660252587015147) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceHealth (3675776442080928184) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceHealth (2024586220562667185) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceRemoteMessaging (105670277002780950) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceRemoteMessaging (8767598075877576277) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSystemExempted (1597663713590612685) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSystemExempted (947381760834649622) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSpecialUse (7973536745876645082) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSpecialUse (646713654541885919) -->
- <skip />
+ <string name="permlab_foregroundServiceCamera" msgid="7814751737955715297">"executa serveis en primer pla amb el tipus \"camera\""</string>
+ <string name="permdesc_foregroundServiceCamera" msgid="6973701931250595727">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"camera\""</string>
+ <string name="permlab_foregroundServiceConnectedDevice" msgid="3019650546176872501">"executa serveis en primer pla amb el tipus \"connectedDevice\""</string>
+ <string name="permdesc_foregroundServiceConnectedDevice" msgid="1067457315741352963">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"connectedDevice\""</string>
+ <string name="permlab_foregroundServiceDataSync" msgid="5847463514326881076">"executa serveis en primer pla amb el tipus \"dataSync\""</string>
+ <string name="permdesc_foregroundServiceDataSync" msgid="2267140263423973050">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"dataSync\""</string>
+ <string name="permlab_foregroundServiceLocation" msgid="3745428302378535690">"executa serveis en primer pla amb el tipus \"location\""</string>
+ <string name="permdesc_foregroundServiceLocation" msgid="118894034365177183">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"location\""</string>
+ <string name="permlab_foregroundServiceMediaPlayback" msgid="4002687983891935514">"executa serveis en primer pla amb el tipus \"mediaPlayback\""</string>
+ <string name="permdesc_foregroundServiceMediaPlayback" msgid="3638032446063968043">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"mediaPlayback\""</string>
+ <string name="permlab_foregroundServiceMediaProjection" msgid="2630868915733312527">"executa serveis en primer pla amb el tipus \"mediaProjection\""</string>
+ <string name="permdesc_foregroundServiceMediaProjection" msgid="4805677128082002298">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"mediaProjection\""</string>
+ <string name="permlab_foregroundServiceMicrophone" msgid="7390033424890545399">"executa serveis en primer pla amb el tipus \"microphone\""</string>
+ <string name="permdesc_foregroundServiceMicrophone" msgid="1206041516173483201">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"microphone\""</string>
+ <string name="permlab_foregroundServicePhoneCall" msgid="627937743867697892">"executa serveis en primer pla amb el tipus \"phoneCall\""</string>
+ <string name="permdesc_foregroundServicePhoneCall" msgid="5941660252587015147">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"phoneCall\""</string>
+ <string name="permlab_foregroundServiceHealth" msgid="3675776442080928184">"executa serveis en primer pla amb el tipus \"health\""</string>
+ <string name="permdesc_foregroundServiceHealth" msgid="2024586220562667185">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"health\""</string>
+ <string name="permlab_foregroundServiceRemoteMessaging" msgid="105670277002780950">"executa serveis en primer pla amb el tipus \"remoteMessaging\""</string>
+ <string name="permdesc_foregroundServiceRemoteMessaging" msgid="8767598075877576277">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"remoteMessaging\""</string>
+ <string name="permlab_foregroundServiceSystemExempted" msgid="1597663713590612685">"executa serveis en primer pla amb el tipus \"systemExempted\""</string>
+ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"systemExempted\""</string>
+ <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"executa serveis en primer pla amb el tipus \"specialUse\""</string>
+ <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"specialUse\""</string>
<string name="permlab_getPackageSize" msgid="375391550792886641">"mesura l\'espai d\'emmagatzematge d\'aplicacions"</string>
<string name="permdesc_getPackageSize" msgid="742743530909966782">"Permet que l\'aplicació recuperi les mides del codi, de les dades i de la memòria cau"</string>
<string name="permlab_writeSettings" msgid="8057285063719277394">"modificar la configuració del sistema"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index ff49c69..91daf78 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Hlasová schránka"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problém s připojením nebo neplatný kód MMI."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funkce není podporována."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operace je omezena pouze na povolená telefonní čísla."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Když je aktivní roaming, nastavení přesměrování hovorů z telefonu nelze změnit."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Služba byla zapnuta."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 9c069e7..b1f5e2a 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Telefonsvarer"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Forbindelsesproblemer eller ugyldigt MMI-nummer."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funktionen understøttes ikke."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Du kan kun foretage handlinger med dine numre til begrænset opkald."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Det er ikke muligt at ændre indstillingerne for viderestilling af opkald fra din telefon, mens du bruger roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Tjenesten blev aktiveret."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index efc7e96..9e89501 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Mailbox"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Verbindungsproblem oder ungültiger MMI-Code."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funktion nicht unterstützt."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Der Vorgang ist nur für deine zugelassenen Rufnummern möglich."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Die Einstellungen für die Anrufweiterleitung von deinem Smartphone können während des Roamings nicht geändert werden."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Dienst wurde aktiviert."</string>
@@ -395,54 +396,30 @@
<string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"Ermöglicht der App, Teile der eigenen App dauerhaft im Speicher abzulegen. Dies kann dazu führen, dass anderen Apps weniger Arbeitsspeicher zur Verfügung steht und das Telefon langsamer wird."</string>
<string name="permlab_foregroundService" msgid="1768855976818467491">"Vordergrunddienst ausführen"</string>
<string name="permdesc_foregroundService" msgid="8720071450020922795">"Ermöglicht der App, die Vordergrunddienste zu verwenden."</string>
- <!-- no translation found for permlab_foregroundServiceCamera (7814751737955715297) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceCamera (6973701931250595727) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceConnectedDevice (3019650546176872501) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceConnectedDevice (1067457315741352963) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceDataSync (5847463514326881076) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceDataSync (2267140263423973050) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceLocation (3745428302378535690) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceLocation (118894034365177183) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaPlayback (4002687983891935514) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaPlayback (3638032446063968043) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaProjection (2630868915733312527) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaProjection (4805677128082002298) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMicrophone (7390033424890545399) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMicrophone (1206041516173483201) -->
- <skip />
- <!-- no translation found for permlab_foregroundServicePhoneCall (627937743867697892) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServicePhoneCall (5941660252587015147) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceHealth (3675776442080928184) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceHealth (2024586220562667185) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceRemoteMessaging (105670277002780950) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceRemoteMessaging (8767598075877576277) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSystemExempted (1597663713590612685) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSystemExempted (947381760834649622) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSpecialUse (7973536745876645082) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSpecialUse (646713654541885919) -->
- <skip />
+ <string name="permlab_foregroundServiceCamera" msgid="7814751737955715297">"Vordergrunddienste mit dem Typ „camera“ ausführen"</string>
+ <string name="permdesc_foregroundServiceCamera" msgid="6973701931250595727">"Ermöglicht der App, Vordergrunddienste mit dem Typ „camera“ zu verwenden"</string>
+ <string name="permlab_foregroundServiceConnectedDevice" msgid="3019650546176872501">"Vordergrunddienste mit dem Typ „connectedDevice“ ausführen"</string>
+ <string name="permdesc_foregroundServiceConnectedDevice" msgid="1067457315741352963">"Ermöglicht der App, Vordergrunddienste mit dem Typ „connectedDevice“ zu verwenden"</string>
+ <string name="permlab_foregroundServiceDataSync" msgid="5847463514326881076">"Vordergrunddienste mit dem Typ „dataSync“ ausführen"</string>
+ <string name="permdesc_foregroundServiceDataSync" msgid="2267140263423973050">"Ermöglicht der App, Vordergrunddienste mit dem Typ „dataSync“ zu verwenden"</string>
+ <string name="permlab_foregroundServiceLocation" msgid="3745428302378535690">"Vordergrunddienste mit dem Typ „location“ ausführen"</string>
+ <string name="permdesc_foregroundServiceLocation" msgid="118894034365177183">"Ermöglicht der App, Vordergrunddienste mit dem Typ „location“ zu verwenden"</string>
+ <string name="permlab_foregroundServiceMediaPlayback" msgid="4002687983891935514">"Vordergrunddienste mit dem Typ „mediaPlayback“ ausführen"</string>
+ <string name="permdesc_foregroundServiceMediaPlayback" msgid="3638032446063968043">"Ermöglicht der App, Vordergrunddienste mit dem Typ „mediaPlayback“ zu verwenden"</string>
+ <string name="permlab_foregroundServiceMediaProjection" msgid="2630868915733312527">"Vordergrunddienste mit dem Typ „mediaProjection“ ausführen"</string>
+ <string name="permdesc_foregroundServiceMediaProjection" msgid="4805677128082002298">"Ermöglicht der App, Vordergrunddienste mit dem Typ „mediaProjection“ zu verwenden"</string>
+ <string name="permlab_foregroundServiceMicrophone" msgid="7390033424890545399">"Vordergrunddienste mit dem Typ „microphone“ ausführen"</string>
+ <string name="permdesc_foregroundServiceMicrophone" msgid="1206041516173483201">"Ermöglicht der App, Vordergrunddienste mit dem Typ „microphone“ zu verwenden"</string>
+ <string name="permlab_foregroundServicePhoneCall" msgid="627937743867697892">"Vordergrunddienste mit dem Typ „phoneCall“ ausführen"</string>
+ <string name="permdesc_foregroundServicePhoneCall" msgid="5941660252587015147">"Ermöglicht der App, Vordergrunddienste mit dem Typ „phoneCall“ zu verwenden"</string>
+ <string name="permlab_foregroundServiceHealth" msgid="3675776442080928184">"Vordergrunddienste mit dem Typ „health“ ausführen"</string>
+ <string name="permdesc_foregroundServiceHealth" msgid="2024586220562667185">"Ermöglicht der App, Vordergrunddienste mit dem Typ „health“ zu verwenden"</string>
+ <string name="permlab_foregroundServiceRemoteMessaging" msgid="105670277002780950">"Vordergrunddienste mit dem Typ „remoteMessaging“ ausführen"</string>
+ <string name="permdesc_foregroundServiceRemoteMessaging" msgid="8767598075877576277">"Ermöglicht der App, Vordergrunddienste mit dem Typ „remoteMessaging“ zu verwenden"</string>
+ <string name="permlab_foregroundServiceSystemExempted" msgid="1597663713590612685">"Vordergrunddienste mit dem Typ „systemExempted“ ausführen"</string>
+ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Ermöglicht der App, Vordergrunddienste mit dem Typ „systemExempted“ zu verwenden"</string>
+ <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"Vordergrunddienste mit dem Typ „specialUse“ ausführen"</string>
+ <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Ermöglicht der App, Vordergrunddienste mit dem Typ „specialUse“ zu verwenden"</string>
<string name="permlab_getPackageSize" msgid="375391550792886641">"Speicherplatz der App ermitteln"</string>
<string name="permdesc_getPackageSize" msgid="742743530909966782">"Ermöglicht der App, ihre Code-, Daten- und Cache-Größe abzurufen"</string>
<string name="permlab_writeSettings" msgid="8057285063719277394">"Systemeinstellungen ändern"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index df8a6bb..8f55589 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Αυτ/τος τηλεφωνητής"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Πρόβλημα σύνδεσης ή μη έγκυρος κώδικας MMI."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Η λειτουργία δεν υποστηρίζεται."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Η λειτουργία περιορίζεται μόνο σε προκαθορισμένους αριθμούς κλήσης."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Δεν είναι δυνατή η αλλαγή των ρυθμίσεων προώθησης κλήσεων από το τηλέφωνό σας κατά τη διάρκεια της περιαγωγής."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Η υπηρεσία ενεργοποιήθηκε."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 114c375..003b3f0 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Voicemail"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Connection problem or invalid MMI code."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Feature not supported."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operation is restricted to fixed dialling numbers only."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Cannot change call forwarding settings from your phone while you are roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Service was enabled."</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 9c9f066..e1cfd83 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Voicemail"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Connection problem or invalid MMI code."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Feature not supported."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operation is restricted to fixed dialing numbers only."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Can not change call forwarding settings from your phone while you are roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Service was enabled."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index d11f733..4c0a7aa 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Voicemail"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Connection problem or invalid MMI code."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Feature not supported."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operation is restricted to fixed dialling numbers only."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Cannot change call forwarding settings from your phone while you are roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Service was enabled."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 8dd085a..7e3ce2d 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Voicemail"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Connection problem or invalid MMI code."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Feature not supported."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operation is restricted to fixed dialling numbers only."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Cannot change call forwarding settings from your phone while you are roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Service was enabled."</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 2197501..9cc06d1 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Voicemail"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Connection problem or invalid MMI code."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Feature not supported."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operation is restricted to fixed dialing numbers only."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Can not change call forwarding settings from your phone while you are roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Service was enabled."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 0d72ec5..69ce57e 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Buzón de voz"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problema de conexión o código incorrecto de MMI."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Función no compatible."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"La operación está limitada a números de marcación fija."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"No se puede cambiar la configuración de desvío de llamadas de tu teléfono mientras usas el servicio de roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Se ha activado el servicio."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 76495a8..91c12c9 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Buzón de voz"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Se ha producido un problema de conexión o el código MMI no es válido."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Función no disponible."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"La operación solo es válida para números de marcación fija."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"No se puede cambiar la configuración de desvío de llamadas desde tu teléfono mientras estás en roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"El servicio se ha habilitado."</string>
@@ -88,7 +89,7 @@
<string name="notification_channel_network_alert" msgid="4788053066033851841">"Alertas"</string>
<string name="notification_channel_call_forward" msgid="8230490317314272406">"Desvío de llamadas"</string>
<string name="notification_channel_emergency_callback" msgid="54074839059123159">"Modo de devolución de llamada de emergencia"</string>
- <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"Estado de los datos móviles"</string>
+ <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"Estado de datos móviles"</string>
<string name="notification_channel_sms" msgid="1243384981025535724">"Mensajes SMS"</string>
<string name="notification_channel_voice_mail" msgid="8457433203106654172">"Mensajes de voz"</string>
<string name="notification_channel_wfc" msgid="9048240466765169038">"Llamada por Wi-Fi"</string>
@@ -396,54 +397,30 @@
<string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"Permite que la aplicación haga que algunas de sus partes se mantengan en la memoria. Esto puede limitar la cantidad de memoria disponible para otras aplicaciones y ralentizar el teléfono."</string>
<string name="permlab_foregroundService" msgid="1768855976818467491">"ejecutar servicio en primer plano"</string>
<string name="permdesc_foregroundService" msgid="8720071450020922795">"Permite que la aplicación use servicios en primer plano."</string>
- <!-- no translation found for permlab_foregroundServiceCamera (7814751737955715297) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceCamera (6973701931250595727) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceConnectedDevice (3019650546176872501) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceConnectedDevice (1067457315741352963) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceDataSync (5847463514326881076) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceDataSync (2267140263423973050) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceLocation (3745428302378535690) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceLocation (118894034365177183) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaPlayback (4002687983891935514) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaPlayback (3638032446063968043) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaProjection (2630868915733312527) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaProjection (4805677128082002298) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMicrophone (7390033424890545399) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMicrophone (1206041516173483201) -->
- <skip />
- <!-- no translation found for permlab_foregroundServicePhoneCall (627937743867697892) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServicePhoneCall (5941660252587015147) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceHealth (3675776442080928184) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceHealth (2024586220562667185) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceRemoteMessaging (105670277002780950) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceRemoteMessaging (8767598075877576277) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSystemExempted (1597663713590612685) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSystemExempted (947381760834649622) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSpecialUse (7973536745876645082) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSpecialUse (646713654541885919) -->
- <skip />
+ <string name="permlab_foregroundServiceCamera" msgid="7814751737955715297">"ejecutar un servicio en primer plano con el tipo \"camera\""</string>
+ <string name="permdesc_foregroundServiceCamera" msgid="6973701931250595727">"Permite que la aplicación use servicios en primer plano con el tipo \"camera\""</string>
+ <string name="permlab_foregroundServiceConnectedDevice" msgid="3019650546176872501">"ejecutar un servicio en primer plano con el tipo \"connectedDevice\""</string>
+ <string name="permdesc_foregroundServiceConnectedDevice" msgid="1067457315741352963">"Permite que la aplicación use servicios en primer plano con el tipo \"connectedDevice\""</string>
+ <string name="permlab_foregroundServiceDataSync" msgid="5847463514326881076">"ejecutar un servicio en primer plano con el tipo \"dataSync\""</string>
+ <string name="permdesc_foregroundServiceDataSync" msgid="2267140263423973050">"Permite que la aplicación use servicios en primer plano con el tipo \"dataSync\""</string>
+ <string name="permlab_foregroundServiceLocation" msgid="3745428302378535690">"ejecutar un servicio en primer plano con el tipo \"location\""</string>
+ <string name="permdesc_foregroundServiceLocation" msgid="118894034365177183">"Permite que la aplicación use servicios en primer plano con el tipo \"location\""</string>
+ <string name="permlab_foregroundServiceMediaPlayback" msgid="4002687983891935514">"ejecutar un servicio en primer plano con el tipo \"mediaPlayback\""</string>
+ <string name="permdesc_foregroundServiceMediaPlayback" msgid="3638032446063968043">"Permite que la aplicación use servicios en primer plano con el tipo \"mediaPlayback\""</string>
+ <string name="permlab_foregroundServiceMediaProjection" msgid="2630868915733312527">"ejecutar un servicio en primer plano con el tipo \"mediaProjection\""</string>
+ <string name="permdesc_foregroundServiceMediaProjection" msgid="4805677128082002298">"Permite que la aplicación use servicios en primer plano con el tipo \"mediaProjection\""</string>
+ <string name="permlab_foregroundServiceMicrophone" msgid="7390033424890545399">"ejecutar un servicio en primer plano con el tipo \"microphone\""</string>
+ <string name="permdesc_foregroundServiceMicrophone" msgid="1206041516173483201">"Permite que la aplicación use servicios en primer plano con el tipo \"microphone\""</string>
+ <string name="permlab_foregroundServicePhoneCall" msgid="627937743867697892">"ejecutar un servicio en primer plano con el tipo \"phoneCall\""</string>
+ <string name="permdesc_foregroundServicePhoneCall" msgid="5941660252587015147">"Permite que la aplicación use servicios en primer plano con el tipo \"phoneCall\""</string>
+ <string name="permlab_foregroundServiceHealth" msgid="3675776442080928184">"ejecutar un servicio en primer plano con el tipo \"health\""</string>
+ <string name="permdesc_foregroundServiceHealth" msgid="2024586220562667185">"Permite que la aplicación use servicios en primer plano con el tipo \"health\""</string>
+ <string name="permlab_foregroundServiceRemoteMessaging" msgid="105670277002780950">"ejecutar un servicio en primer plano con el tipo \"remoteMessaging\""</string>
+ <string name="permdesc_foregroundServiceRemoteMessaging" msgid="8767598075877576277">"Permite que la aplicación use servicios en primer plano con el tipo \"remoteMessaging\""</string>
+ <string name="permlab_foregroundServiceSystemExempted" msgid="1597663713590612685">"ejecutar un servicio en primer plano con el tipo \"systemExempted\""</string>
+ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Permite que la aplicación use servicios en primer plano con el tipo \"systemExempted\""</string>
+ <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"ejecutar un servicio en primer plano con el tipo \"specialUse\""</string>
+ <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Permite que la aplicación use servicios en primer plano con el tipo \"specialUse\""</string>
<string name="permlab_getPackageSize" msgid="375391550792886641">"medir el espacio de almacenamiento de la aplicación"</string>
<string name="permdesc_getPackageSize" msgid="742743530909966782">"Permite que la aplicación recupere su código, sus datos y los tamaños de caché."</string>
<string name="permlab_writeSettings" msgid="8057285063719277394">"modificar los ajustes del sistema"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index c16f7fc..42a383c 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Kõnepost"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Ühendusprobleem või kehtetu MMI-kood."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funktsiooni ei toetata."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Toiming on ainult fikseeritud valimisnumbritele."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Kõne suunamise seadeid ei saa rändluse ajal teie telefonis muuta."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Teenus on lubatud."</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 2c29a80..878b57e 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Erantzungailua"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Konexio-arazoren bat gertatu da edo MMI kodea baliogabea da."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Ez da onartzen eginbidea."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Eragiketa markatze finkoko zenbakietara murriztua dago."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Ezin dira aldatu deiak desbideratzeko ezarpenak telefonoa ibiltaritzan dagoenean."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Zerbitzua gaitu da."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 4ee442c..a65910b 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"پست صوتی"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"مشکل در اتصال یا کد MMI نامعتبر."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"از این ویژگی پشتیبانی نمیشود."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"عملکرد فقط به شمارههای شمارهگیری ثابت محدود است."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"وقتی درحال فراگردی هستید، نمیتوانید تنظیمات هدایت تماس را از تلفنتان تغییر دهید."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"سرویس فعال شد."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 158290d..02ae893 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Vastaaja"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Yhteysongelma tai virheellinen MMI-koodi."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Ominaisuutta ei tueta."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Voit suorittaa toiminnon vain sallitut puhelut -numeroihin."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Soitonsiirtoasetuksia ei voi muuttaa puhelimella roaming-tilassa."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Palvelu otettiin käyttöön."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 5f2d3dc..264cf67 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Messagerie vocale"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problème de connexion ou code IHM incorrect"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Fonctionnalité non prise en charge."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Opération réservée aux numéros autorisés"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Impossible de modifier les paramètres de transfert d\'appel sur votre téléphone lorsque vous êtes en itinérance."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Le service a été activé."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 563fa58..0e4bb4c 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Messagerie vocale"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problème de connexion ou code IHM non valide."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Fonctionnalité non disponible."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Opération réservée aux numéros autorisés"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Impossible de modifier les paramètres de transfert d\'appel depuis votre téléphone lorsque vous êtes en itinérance."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Le service a été activé."</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index a931219..31da9fa 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Correo de voz"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problema de conexión ou código MMI non válido."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Función non compatible."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"A operación está restrinxida a números de marcación fixa."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Non se pode cambiar a configuración do desvío de chamadas desde o teléfono mentres estás en itinerancia."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Activouse o servizo."</string>
@@ -1978,13 +1979,13 @@
<string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"A configuración de Android TV non está dispoñible"</string>
<string name="app_streaming_blocked_title_for_settings_dialog" product="tablet" msgid="8222710146267948647">"A configuración da tableta non está dispoñible"</string>
<string name="app_streaming_blocked_title_for_settings_dialog" product="default" msgid="6895719984375299791">"A configuración do teléfono non está dispoñible"</string>
- <string name="app_streaming_blocked_message" product="tv" msgid="4003011766528814377">"Nestes momentos, non podes acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde o dispositivo con Android TV."</string>
+ <string name="app_streaming_blocked_message" product="tv" msgid="4003011766528814377">"Nestes momentos, non podes acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde o dispositivo Android TV."</string>
<string name="app_streaming_blocked_message" product="tablet" msgid="4242053045964946062">"Nestes momentos, non podes acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde a tableta."</string>
<string name="app_streaming_blocked_message" product="default" msgid="6159168735030739398">"Nestes momentos, non podes acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde o teléfono."</string>
- <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Esta aplicación solicita seguranza adicional. Proba a facelo desde o dispositivo con Android TV."</string>
+ <string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tv" msgid="3470977315395784567">"Esta aplicación solicita seguranza adicional. Proba a facelo desde o dispositivo Android TV."</string>
<string name="app_streaming_blocked_message_for_fingerprint_dialog" product="tablet" msgid="698460091901465092">"Esta aplicación solicita seguranza adicional. Proba a facelo desde a tableta."</string>
<string name="app_streaming_blocked_message_for_fingerprint_dialog" product="default" msgid="8552691971910603907">"Esta aplicación solicita seguranza adicional. Proba a facelo desde o teléfono."</string>
- <string name="app_streaming_blocked_message_for_settings_dialog" product="tv" msgid="820334666354451145">"Non se puido acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde o dispositivo con Android TV."</string>
+ <string name="app_streaming_blocked_message_for_settings_dialog" product="tv" msgid="820334666354451145">"Non se puido acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde o dispositivo Android TV."</string>
<string name="app_streaming_blocked_message_for_settings_dialog" product="tablet" msgid="3286849551133045896">"Non se puido acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde a tableta."</string>
<string name="app_streaming_blocked_message_for_settings_dialog" product="default" msgid="6264287556598916295">"Non se puido acceder a este contido desde o teu dispositivo (<xliff:g id="DEVICE">%1$s</xliff:g>). Proba a facelo desde o teléfono."</string>
<string name="deprecated_target_sdk_message" msgid="5246906284426844596">"Esta aplicación deseñouse para unha versión anterior de Android. Quizais non funcione correctamente e non inclúa as últimas medidas de protección de privacidade e seguranza. Comproba se hai actualizacións ou ponte en contacto co programador da aplicación."</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 418eb48..8351fbc 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"વૉઇસમેઇલ"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"કનેક્શન સમસ્યા અથવા અમાન્ય MMI કોડ."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"સુવિધાને સપોર્ટ આપવામાં આવતો નથી."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"ઑપરેશન ફક્ત સ્થિર ડાયલિંગ નંબર્સ પર પ્રતિબંધિત છે."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"તમે રોમિંગમાં હો તે વખતે તમારા ફોન પરથી કૉલ ફૉરવર્ડિગ સેટિંગ બદલી શકતાં નથી."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"સેવા સક્ષમ હતી."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 2406650..5bc7273 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"वॉइसमेल"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"कनेक्शन समस्या या अमान्य MMI कोड."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"यह सुविधा, इस नेटवर्क पर काम नहीं करती है."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"कार्रवाई केवल फ़िक्स्ड डायलिंग नंबर के लिए प्रतिबंधित है."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"आपके रोमिंग में होने पर, आपके फ़ोन से कॉल को दूसरे नंबर पर भेजने की सेटिंग नहीं बदली जा सकती."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"सेवा अक्षम थी."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 407eb4e..6d6d5fe 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Govorna pošta"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problem s vezom ili nevažeći MMI kôd."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Značajka nije podržana."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operacija je ograničena samo na brojeve s fiksnim biranjem."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Nije moguće promijeniti postavke preusmjeravanja poziva na telefonu dok ste u roamingu."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Usluga je omogućena."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 34ee8a3..05953f0 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Hangposta"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Kapcsolódási probléma vagy érvénytelen MMI-kód."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"A funkció nem támogatott."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"A művelet fix hívószámokra van korlátozva."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"A hívásátirányítási beállításokat roaming közben telefonról nem lehet módosítani."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"A szolgáltatás engedélyezésre került."</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 91646a4..7f8898e 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Ձայնային փոստ"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Միացման խնդիր կամ անվավեր MMI ծածակագիր:"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Գործառույթը չի աջակցվում։"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Գործողությունը սահմանափակված է միայն ամրակայված հեռախոսահամարների համար:"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Ռոումինգում չեք կարող փոխել զանգի վերահասցեավորման կարգավորումները ձեր հեռախոսից։"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Ծառայությունը միացված է:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index df7715bd..79ee0e8 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Pesan suara"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Masalah sambungan atau kode MMI tidak valid."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Fitur tidak didukung."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operasi dibatasi untuk nomor panggilan tetap saja."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Tidak dapat mengubah setelan penerusan panggilan dari ponsel saat roaming"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Layanan telah diaktifkan."</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index a97ac98..5343d23 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Talhólf"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Vandamál með tengingu eða ógild MMI-kóðaskipun."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Eiginleiki ekki studdur."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Aðgerð takmarkast við fast númeraval."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Ekki er hægt að breyta stillingum fyrir framsendingu símtala úr símanum á meðan þú ert í reiki."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Þjónustan var virkjuð."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index e27538a..64c4fd5 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Segreteria"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problema di connessione o codice MMI non valido."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funzionalità non supportata."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operazione limitata solo ai numeri di selezione fissa."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Impossibile modificare le impostazioni di deviazione chiamate dal telefono durante il roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Il servizio è stato attivato."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a074860..a6c0383 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"דואר קולי"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"בעיה בחיבור או קוד MMI לא חוקי."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"התכונה לא נתמכת."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"הפעולה מוגבלת למספרי חיוג קבועים בלבד."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"לא ניתן לשנות את הגדרות העברת השיחות מהטלפון במצב נדידה."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"השירות הופעל."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 140ba88..9bcde38 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"留守番電話"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"接続に問題があるか、MMIコードが正しくありません。"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"サポートされていません。"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"発信番号制限で指定された番号に対してのみ操作できます。"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"ローミング中はスマートフォンから着信転送設定の変更はできません。"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"サービスが有効になりました。"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index a5371d2..92a37ce 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"ხმოვანი ფოსტა"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"კავშირის პრობლემა ან არასწორი MMI კოდი."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"ფუნქცია მხარდაუჭერელია."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"ოპერაცია შეზღუდულია მხოლოდ დაშვებულ ნომრებზე."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"ზარის გადამისამართების პარამეტრების თქვენი ტელეფონიდან შეცვლა როუმინგისას ვერ მოხერხდება."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"სერვისი ჩართულია."</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 47afaa3..04f0445 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Дауыстық пошта"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Байланыс мәселесі немесе MMИ коды жарамсыз."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Функция қолданылмайды."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Әрекет анықталған сандарды теруге шектелген."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Роуминг кезінде телефоннан қоңырауды басқа нөмірге бағыттау параметрлері өзгертілмейді."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Қызмет қосылған."</string>
@@ -395,54 +396,30 @@
<string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"Қолданбаға өзінің бөліктерін жадта бекіндіру мүмкіндігін береді. Бұл басқа қолданбалардың жадқа қол жетімділігін шектеп, телефонды баяулатуы мүмкін."</string>
<string name="permlab_foregroundService" msgid="1768855976818467491">"басымдылығы жоғары қызметті іске қосу"</string>
<string name="permdesc_foregroundService" msgid="8720071450020922795">"Қолданбаға басымдылығы жоғары қызметтерді пайдалануға рұқсат береді."</string>
- <!-- no translation found for permlab_foregroundServiceCamera (7814751737955715297) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceCamera (6973701931250595727) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceConnectedDevice (3019650546176872501) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceConnectedDevice (1067457315741352963) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceDataSync (5847463514326881076) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceDataSync (2267140263423973050) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceLocation (3745428302378535690) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceLocation (118894034365177183) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaPlayback (4002687983891935514) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaPlayback (3638032446063968043) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaProjection (2630868915733312527) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaProjection (4805677128082002298) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMicrophone (7390033424890545399) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMicrophone (1206041516173483201) -->
- <skip />
- <!-- no translation found for permlab_foregroundServicePhoneCall (627937743867697892) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServicePhoneCall (5941660252587015147) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceHealth (3675776442080928184) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceHealth (2024586220562667185) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceRemoteMessaging (105670277002780950) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceRemoteMessaging (8767598075877576277) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSystemExempted (1597663713590612685) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSystemExempted (947381760834649622) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSpecialUse (7973536745876645082) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSpecialUse (646713654541885919) -->
- <skip />
+ <string name="permlab_foregroundServiceCamera" msgid="7814751737955715297">"\"camera\" түріне жататын экрандық режимдегі қызметті іске қосу"</string>
+ <string name="permdesc_foregroundServiceCamera" msgid="6973701931250595727">"Қолданбаға \"camera\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string>
+ <string name="permlab_foregroundServiceConnectedDevice" msgid="3019650546176872501">"\"health\" түріне жататын экрандық режимдегі қызметті іске қосу"</string>
+ <string name="permdesc_foregroundServiceConnectedDevice" msgid="1067457315741352963">"Қолданбаға \"connectedDevice\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string>
+ <string name="permlab_foregroundServiceDataSync" msgid="5847463514326881076">"\"dataSync\" түріне жататын экрандық режимдегі қызметті іске қосу"</string>
+ <string name="permdesc_foregroundServiceDataSync" msgid="2267140263423973050">"Қолданбаға \"dataSync\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string>
+ <string name="permlab_foregroundServiceLocation" msgid="3745428302378535690">"\"location\" түріне жататын экрандық режимдегі қызметті іске қосу"</string>
+ <string name="permdesc_foregroundServiceLocation" msgid="118894034365177183">"Қолданбаға \"location\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string>
+ <string name="permlab_foregroundServiceMediaPlayback" msgid="4002687983891935514">"\"mediaPlayback\" түріне жататын экрандық режимдегі қызметті іске қосу"</string>
+ <string name="permdesc_foregroundServiceMediaPlayback" msgid="3638032446063968043">"Қолданбаға \"mediaPlayback\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string>
+ <string name="permlab_foregroundServiceMediaProjection" msgid="2630868915733312527">"\"mediaProjection\" түріне жататын экрандық режимдегі қызметті іске қосу"</string>
+ <string name="permdesc_foregroundServiceMediaProjection" msgid="4805677128082002298">"Қолданбаға \"mediaProjection\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string>
+ <string name="permlab_foregroundServiceMicrophone" msgid="7390033424890545399">"\"microphone\" түріне жататын экрандық режимдегі қызметті іске қосу"</string>
+ <string name="permdesc_foregroundServiceMicrophone" msgid="1206041516173483201">"Қолданбаға \"microphone\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string>
+ <string name="permlab_foregroundServicePhoneCall" msgid="627937743867697892">"\"phoneCall\" түріне жататын экрандық режимдегі қызметті іске қосу"</string>
+ <string name="permdesc_foregroundServicePhoneCall" msgid="5941660252587015147">"Қолданбаға \"phoneCall\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string>
+ <string name="permlab_foregroundServiceHealth" msgid="3675776442080928184">"\"health\" түріне жататын экрандық режимдегі қызметті іске қосу"</string>
+ <string name="permdesc_foregroundServiceHealth" msgid="2024586220562667185">"Қолданбаға \"health\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string>
+ <string name="permlab_foregroundServiceRemoteMessaging" msgid="105670277002780950">"\"remoteMessaging\" түріне жататын экрандық режимдегі қызметті іске қосу"</string>
+ <string name="permdesc_foregroundServiceRemoteMessaging" msgid="8767598075877576277">"Қолданбаға \"remoteMessaging\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string>
+ <string name="permlab_foregroundServiceSystemExempted" msgid="1597663713590612685">"\"systemExempted\" түріне жататын экрандық режимдегі қызметті іске қосу"</string>
+ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Қолданбаға \"systemExempted\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string>
+ <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" түріне жататын экрандық режимдегі қызметті іске қосу"</string>
+ <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Қолданбаға \"specialUse\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string>
<string name="permlab_getPackageSize" msgid="375391550792886641">"қолданба жадындағы бос орынды өлшеу"</string>
<string name="permdesc_getPackageSize" msgid="742743530909966782">"Қолданбаға оның кодын, деректерін және кэш өлшемдерін шығарып алуға рұқсат береді"</string>
<string name="permlab_writeSettings" msgid="8057285063719277394">"жүйе параметрлерін өзгерту"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 3f0ae1f..1477713 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"សារជាសំឡេង"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"បញ្ហាក្នុងការតភ្ជាប់ ឬកូដ MMI មិនត្រឹមត្រូវ។"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"មិនអាចប្រើមុខងារនេះបានទេ។"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"ប្រតិបត្តិការត្រូវបានដាក់កម្រិតចំពោះលេខហៅថេរតែប៉ុណ្ណោះ។"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"មិនអាចប្តូរការកំណត់នៃការបញ្ជូនការហៅបន្តពីទូរសព្ទរបស់អ្នកបានទេ ខណៈពេលដែលអ្នកកំពុងប្រើសេវារ៉ូមីង។"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"បានបើកសេវាកម្ម។"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 2a550de..b5535c9 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"ಧ್ವನಿಮೇಲ್"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"ಸಂಪರ್ಕ ಸಮಸ್ಯೆ ಇಲ್ಲವೇ ಅಮಾನ್ಯ MMI ಕೋಡ್."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"ಫೀಚರ್ ಬಂಬಲಿಸುತ್ತಿಲ್ಲ."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"ಕಾರ್ಯಾಚರಣೆಯನ್ನು ಸ್ಥಿರ ದೂರವಾಣಿ ಸಂಖ್ಯೆಗಳಿಗೆ ಮಾತ್ರ ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"ನೀವು ರೋಮಿಂಗ್ನಲ್ಲಿರುವಾಗ ನಿಮ್ಮ ಫೋನ್ನಿಂದ ಕರೆ ಫಾರ್ವರ್ಡ್ ಮಾಡುವಿಕೆಯ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"ಸೇವೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f55dfab..aa6feae 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"음성사서함"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"연결에 문제가 있거나 MMI 코드가 잘못되었습니다."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"기능이 지원되지 않습니다."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"발신 허용 번호에서만 수행할 수 있는 작업입니다."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"로밍 중에는 착신 전환 설정을 변경할 수 없습니다."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"서비스를 사용하도록 설정했습니다."</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 26e5c1e4..8201c50 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Үн почтасы"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Туташууда көйгөй чыкты же MMI коду жараксыз."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Функция колдоого алынбайт."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Иш-аракет туруктуу терүү номерлери менен гана чектелет."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Роуминг учурунда чалууну башка номерге багыттоонун жөндөөлөрүн телефонуңуздан өзгөртүү мүмкүн эмес."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Кызмат иштетилди."</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 4b8e82b..d7b77bfc 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"ຂໍ້ຄວາມສຽງ"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"ມີບັນຫາໃນການເຊື່ອມຕໍ່ ຫຼືລະຫັດ MMI ບໍ່ຖືກຕ້ອງ."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"ບໍ່ຮອງຮັບຄຸນສົມບັດ."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"ການດຳເນີນການຖືກຈຳກັດເປັນ ຈຳກັດໝາຍເລກໂທອອກເທົ່ານັ້ນ."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Can not change call forwarding settings from your phone while you are roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"ບໍລິການຖືກເປີດໄວ້ແລ້ວ."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 341612c..eb74970 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Balso paštas"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Ryšio problema arba neteisingas MMI kodas."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funkcija nepalaikoma."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operacija ribojama tik naudojant fiksuoto rinkimo numerius."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Negalima pakeisti telefono skambučio peradresavimo nustatymų, kai naudojate tarptinklinį ryšį."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Paslauga įgalinta."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index b57de77..792ce6a 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Balss pasts"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Savienojuma problēma vai nederīgs MMI kods."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funkcija netiek atbalstīta."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Darbība ir atļauta tikai fiksēto numuru sastādīšanai."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Nevar mainīt zvanu pāradresēšanas iestatījumus tālrunī, kamēr izmantojat viesabonēšanu."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Pakalpojums tika iespējots."</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 51a6055..e5710cd 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Говорна пошта"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Проблем со поврзување или неважечки MMI код."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Функцијата не е поддржана."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Операцијата е ограничена на бирање само фиксни броеви."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Не може да се сменат поставките за проследување повик од телефонот додека сте во роаминг."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Услугата беше овозможена."</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 1b9fc94..65b2c5d 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"വോയ്സ് മെയില്"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"കണക്ഷൻ പ്രശ്നം അല്ലെങ്കിൽ MMI കോഡ് അസാധുവാണ്."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"ഫീച്ചർ പിന്തുണയ്ക്കുന്നില്ല."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"നിശ്ചയിച്ചുറപ്പിച്ച ഡയൽ ചെയ്യൽ നമ്പറുകൾക്ക് മാത്രമായി പ്രവർത്തനം പരിമിതപ്പെടുത്തിയിരിക്കുന്നു."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"റോമിംഗിൽ ആയിരിക്കുമ്പോൾ നിങ്ങളുടെ ഫോണിൽ നിന്ന് കോൾ കൈമാറ്റ ക്രമീകരണം സാധിക്കില്ല."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"സേവനം പ്രവർത്തനക്ഷമമാക്കി."</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 0fd3c6f..6d48c97 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"дуут шуудан"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Холболтын асуудал эсвэл буруу MMI код."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Онцлогийг дэмжээгүй."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Ажиллагаа зөвөх тогтсон дугаараар хязгаарлагдсан."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Таныг роуминг үйлчилгээг идэвхжүүлсэн үед таны утаснаас дуудлага дамжуулах тохиргоог өөрчлөх боломжгүй."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Үйлчилгээ идэвхжсэн."</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index a4121de..b33fb3fb 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"व्हॉइसमेल"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"कनेक्शन समस्या किंवा अवैध MMI कोड."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"वैशिष्ट्याला सपोर्ट नाही."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"कार्य फक्त निश्चित डायलिंग नंबरसाठी प्रतिबंधित आहे."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"तुम्ही रोमिंगमध्ये असताना आपल्या फोनवरील कॉल फॉरवर्डिंग सेटिंंग्ज बदलू शकत नाही."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"सेवा सक्षम केली."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 5faec0a..c6065c6 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Mel suara"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Masalah sambungan atau kod MMI tidak sah"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Ciri tidak disokong."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Pengendalian dihadkan kepada nombor dailan tetap sahaja."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Tidak dapat mengubah tetapan pemajuan panggilan daripad telefon anda semasa dalam perayauan."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Perkhidmatan telah didayakan."</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 6f45b93..0e92d8a 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"အသံမေးလ်"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"ဆက်သွယ်မှုဆိုင်ရာပြသနာ သို့မဟုတ် မမှန်ကန်သောMMIကုတ်"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"ဝန်ဆောင်မှုကို မပံ့ပိုးပါ။"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"သတ်မှတ်ခေါ်ဆိုနိုင်သောနံပါတ်များထံသာ ကန့်သတ်ထားသည်"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"ကွန်ရက်ပြင်ပဒေတာအသုံးပြုခြင်းကို ဖွင့်ထားသည့်အခါ သင့်ဖုန်းမှနေ၍ ခေါ်ဆိုမှုထပ်ဆင့်ပို့ခြင်းဆက်တင်အား ပြောင်း၍မရပါ။"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"ဝန်ဆောင်မှု လုပ်ဆောင်နိုင်မည်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 0a940f1..8b796dd 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Telefonsvarer"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Tilkoblingsproblem eller ugyldig MMI-kode."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funksjonen støttes ikke."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Handlingen kan kun utføres på numre med anropsbegrensning."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Får ikke endret innstillinger for viderekobling fra telefonen din når du bruker roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Tjenesten ble aktivert."</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 9b25f8a..54875ac 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"भ्वाइस मेल"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN१"</string>
<string name="mmiError" msgid="2862759606579822246">"जडान समस्या वा अमान्य MMI कोड।"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"यो सुविधा प्रयोग गर्न मिल्दैन।"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"अपरेशन निश्चित डायल नम्बरहरूको लागि मात्र प्रतिबन्धित छ।"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"तपाईं रोमिङमा हुनुहुँदा तपाईंको फोनबाट कल फर्वार्ड गर्ने सम्बन्धी सेटिङहरू परिवर्तन गर्न सकिँदैन।"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"सेवा सक्षम पारियो।"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 07413e6..e40a087 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Voicemail"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Verbindingsprobleem of ongeldige MMI-code."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Functie niet ondersteund."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Bewerking is beperkt tot vaste nummers."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Kan instellingen voor doorschakelen van gesprekken niet wijzigen vanaf je telefoon tijdens roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Service staat aan."</string>
@@ -257,7 +258,7 @@
<string name="global_action_toggle_silent_mode" msgid="8464352592860372188">"Stille modus"</string>
<string name="global_action_silent_mode_on_status" msgid="2371892537738632013">"Geluid is UIT"</string>
<string name="global_action_silent_mode_off_status" msgid="6608006545950920042">"Geluid is AAN"</string>
- <string name="global_actions_toggle_airplane_mode" msgid="6911684460146916206">"Vliegtuigmodus"</string>
+ <string name="global_actions_toggle_airplane_mode" msgid="6911684460146916206">"Vliegtuigmodus"</string>
<string name="global_actions_airplane_mode_on_status" msgid="5508025516695361936">"Vliegtuigmodus is AAN"</string>
<string name="global_actions_airplane_mode_off_status" msgid="8522219771500505475">"Vliegtuigmodus is UIT"</string>
<string name="global_action_settings" msgid="4671878836947494217">"Instellingen"</string>
@@ -1016,7 +1017,7 @@
<string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"Gebruikersselectie"</string>
<string name="keyguard_accessibility_status" msgid="6792745049712397237">"Status"</string>
<string name="keyguard_accessibility_camera" msgid="7862557559464986528">"Camera"</string>
- <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"Mediabediening"</string>
+ <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"Mediabediening"</string>
<string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"Opnieuw indelen van widget gestart."</string>
<string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"Opnieuw indelen van widget beëindigd."</string>
<string name="keyguard_accessibility_widget_deleted" msgid="1509738950119878705">"Widget <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> verwijderd."</string>
@@ -1509,7 +1510,7 @@
<string name="forward_intent_to_work" msgid="3620262405636021151">"U gebruikt deze app in je werkprofiel"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"Invoermethode"</string>
<string name="sync_binding_label" msgid="469249309424662147">"Synchroniseren"</string>
- <string name="accessibility_binding_label" msgid="1974602776545801715">"Toegankelijkheid"</string>
+ <string name="accessibility_binding_label" msgid="1974602776545801715">"Toegankelijkheid"</string>
<string name="wallpaper_binding_label" msgid="1197440498000786738">"Achtergrond"</string>
<string name="chooser_wallpaper" msgid="3082405680079923708">"Achtergrond wijzigen"</string>
<string name="notification_listener_binding_label" msgid="2702165274471499713">"Listener voor meldingen"</string>
@@ -2015,7 +2016,7 @@
<string name="app_category_news" msgid="1172762719574964544">"Nieuws en tijdschriften"</string>
<string name="app_category_maps" msgid="6395725487922533156">"Maps en navigatie"</string>
<string name="app_category_productivity" msgid="1844422703029557883">"Productiviteit"</string>
- <string name="app_category_accessibility" msgid="6643521607848547683">"Toegankelijkheid"</string>
+ <string name="app_category_accessibility" msgid="6643521607848547683">"Toegankelijkheid"</string>
<string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"Apparaatopslag"</string>
<string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"USB-foutopsporing"</string>
<string name="time_picker_hour_label" msgid="4208590187662336864">"uur"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 5206994..412409a 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"ଭଏସ୍ ମେଲ୍"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"ସଂଯୋଗରେ ସମସ୍ୟା ଅଛି କିମ୍ବା ଅମାନ୍ୟ MMI କୋଡ୍।"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"ଫିଚର ସମର୍ଥିତ ନୁହେଁ।"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"କେବଳ ସ୍ଥାୟୀ ଡାୟଲିଙ୍ଗ ନମ୍ବର୍ ପାଇଁ କାର୍ଯ୍ୟ ସୀମିତ ଅଟେ।"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"ଆପଣ ରୋମିଙ୍ଗରେ ଥିବାବେଳେ କଲ୍ ଫର୍ୱର୍ଡିଙ୍ଗ ସେଟିଙ୍ଗ ବଦଳାଇପାରିବେ ନାହିଁ।"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"ସେବା ସକ୍ଷମ କରାଯାଇଥିଲା।"</string>
@@ -87,7 +88,7 @@
<string name="notification_channel_network_alert" msgid="4788053066033851841">"ଆଲର୍ଟ"</string>
<string name="notification_channel_call_forward" msgid="8230490317314272406">"କଲ୍ ଫରୱାର୍ଡିଂ"</string>
<string name="notification_channel_emergency_callback" msgid="54074839059123159">"ଜରୁରୀକାଳୀନ କଲବ୍ୟାକ୍ ମୋଡ୍"</string>
- <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"ମୋବାଇଲ୍ ଡାଟା ଷ୍ଟାଟସ୍"</string>
+ <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"ମୋବାଇଲ ଡାଟା ଷ୍ଟାଟସ"</string>
<string name="notification_channel_sms" msgid="1243384981025535724">"SMS ମେସେଜ୍"</string>
<string name="notification_channel_voice_mail" msgid="8457433203106654172">"ଭଏସମେଲ୍ ମେସେଜ୍"</string>
<string name="notification_channel_wfc" msgid="9048240466765169038">"ୱାଇ-ଫାଇ କଲିଙ୍ଗ"</string>
@@ -825,30 +826,30 @@
<item msgid="8150904584178569699">"ୱାର୍କ ଫ୍ୟାକ୍ସ"</item>
<item msgid="4537253139152229577">"ହୋମ ଫାକ୍ସ"</item>
<item msgid="6751245029698664340">"ପେଜର୍"</item>
- <item msgid="1692790665884224905">"ଅନ୍ୟାନ୍ୟ"</item>
+ <item msgid="1692790665884224905">"ଅନ୍ୟ"</item>
<item msgid="6216981255272016212">"କଷ୍ଟମ୍"</item>
</string-array>
<string-array name="emailAddressTypes">
<item msgid="7786349763648997741">"ହୋମ"</item>
<item msgid="435564470865989199">"ୱାର୍କ"</item>
- <item msgid="4199433197875490373">"ଅନ୍ୟାନ୍ୟ"</item>
+ <item msgid="4199433197875490373">"ଅନ୍ୟ"</item>
<item msgid="3233938986670468328">"କଷ୍ଟମ୍"</item>
</string-array>
<string-array name="postalAddressTypes">
<item msgid="3861463339764243038">"ହୋମ"</item>
<item msgid="5472578890164979109">"ୱାର୍କ"</item>
- <item msgid="5718921296646594739">"ଅନ୍ୟାନ୍ୟ"</item>
+ <item msgid="5718921296646594739">"ଅନ୍ୟ"</item>
<item msgid="5523122236731783179">"କଷ୍ଟମ୍"</item>
</string-array>
<string-array name="imAddressTypes">
<item msgid="588088543406993772">"ହୋମ"</item>
<item msgid="5503060422020476757">"ୱାର୍କ"</item>
- <item msgid="2530391194653760297">"ଅନ୍ୟାନ୍ୟ"</item>
+ <item msgid="2530391194653760297">"ଅନ୍ୟ"</item>
<item msgid="7640927178025203330">"କଷ୍ଟମ୍"</item>
</string-array>
<string-array name="organizationTypes">
<item msgid="6144047813304847762">"ୱାର୍କ"</item>
- <item msgid="7402720230065674193">"ଅନ୍ୟାନ୍ୟ"</item>
+ <item msgid="7402720230065674193">"ଅନ୍ୟ"</item>
<item msgid="808230403067569648">"କଷ୍ଟମ୍"</item>
</string-array>
<string-array name="imProtocols">
@@ -868,7 +869,7 @@
<string name="phoneTypeFaxWork" msgid="6757519896109439123">"ୱାର୍କ ଫାକ୍ସ"</string>
<string name="phoneTypeFaxHome" msgid="6678559953115904345">"ହୋମ ଫାକ୍ସ"</string>
<string name="phoneTypePager" msgid="576402072263522767">"ପେଜର୍"</string>
- <string name="phoneTypeOther" msgid="6918196243648754715">"ଅନ୍ୟାନ୍ୟ"</string>
+ <string name="phoneTypeOther" msgid="6918196243648754715">"ଅନ୍ୟ"</string>
<string name="phoneTypeCallback" msgid="3455781500844157767">"କଲବ୍ୟାକ୍"</string>
<string name="phoneTypeCar" msgid="4604775148963129195">"କାର୍"</string>
<string name="phoneTypeCompanyMain" msgid="4482773154536455441">"କମ୍ପାନୀର ମୁଖ୍ୟ"</string>
@@ -889,16 +890,16 @@
<string name="emailTypeCustom" msgid="1809435350482181786">"କଷ୍ଟମ୍"</string>
<string name="emailTypeHome" msgid="1597116303154775999">"ହୋମ"</string>
<string name="emailTypeWork" msgid="2020095414401882111">"ୱାର୍କ"</string>
- <string name="emailTypeOther" msgid="5131130857030897465">"ଅନ୍ୟାନ୍ୟ"</string>
+ <string name="emailTypeOther" msgid="5131130857030897465">"ଅନ୍ୟ"</string>
<string name="emailTypeMobile" msgid="787155077375364230">"ମୋବାଇଲ୍"</string>
<string name="postalTypeCustom" msgid="5645590470242939129">"କଷ୍ଟମ୍"</string>
<string name="postalTypeHome" msgid="7562272480949727912">"ହୋମ"</string>
<string name="postalTypeWork" msgid="8553425424652012826">"ୱାର୍କ"</string>
- <string name="postalTypeOther" msgid="7094245413678857420">"ଅନ୍ୟାନ୍ୟ"</string>
+ <string name="postalTypeOther" msgid="7094245413678857420">"ଅନ୍ୟ"</string>
<string name="imTypeCustom" msgid="5653384545085765570">"କଷ୍ଟମ୍"</string>
<string name="imTypeHome" msgid="6996507981044278216">"ହୋମ"</string>
<string name="imTypeWork" msgid="2099668940169903123">"ୱାର୍କ"</string>
- <string name="imTypeOther" msgid="8068447383276219810">"ଅନ୍ୟାନ୍ୟ"</string>
+ <string name="imTypeOther" msgid="8068447383276219810">"ଅନ୍ୟ"</string>
<string name="imProtocolCustom" msgid="4437878287653764692">"କଷ୍ଟମ୍"</string>
<string name="imProtocolAim" msgid="4050198236506604378">"AIM"</string>
<string name="imProtocolMsn" msgid="2257148557766499232">"Windows Live"</string>
@@ -910,7 +911,7 @@
<string name="imProtocolJabber" msgid="7919269388889582015">"Jabber"</string>
<string name="imProtocolNetMeeting" msgid="4985002408136148256">"NetMeeting"</string>
<string name="orgTypeWork" msgid="8684458700669564172">"ୱାର୍କ"</string>
- <string name="orgTypeOther" msgid="5450675258408005553">"ଅନ୍ୟାନ୍ୟ"</string>
+ <string name="orgTypeOther" msgid="5450675258408005553">"ଅନ୍ୟ"</string>
<string name="orgTypeCustom" msgid="1126322047677329218">"କଷ୍ଟମ୍"</string>
<string name="relationTypeCustom" msgid="282938315217441351">"କଷ୍ଟମ୍"</string>
<string name="relationTypeAssistant" msgid="4057605157116589315">"Assistant"</string>
@@ -930,7 +931,7 @@
<string name="sipAddressTypeCustom" msgid="6283889809842649336">"କଷ୍ଟମ୍"</string>
<string name="sipAddressTypeHome" msgid="5918441930656878367">"ହୋମ"</string>
<string name="sipAddressTypeWork" msgid="7873967986701216770">"ୱାର୍କ"</string>
- <string name="sipAddressTypeOther" msgid="6317012577345187275">"ଅନ୍ୟାନ୍ୟ"</string>
+ <string name="sipAddressTypeOther" msgid="6317012577345187275">"ଅନ୍ୟ"</string>
<string name="quick_contacts_not_available" msgid="1262709196045052223">"ଏହି କଣ୍ଟାକ୍ଟ ଦେଖିବାକୁ କୌଣସି ଆପ୍ଲିକେସନ ମିଳିଲା ନାହିଁ।"</string>
<string name="keyguard_password_enter_pin_code" msgid="6401406801060956153">"PIN କୋଡ୍ ଟାଇପ୍ କରନ୍ତୁ"</string>
<string name="keyguard_password_enter_puk_code" msgid="3112256684547584093">"PUK ଓ ନୂଆ PIN କୋଡ୍ ଟାଇପ୍ କରନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index ace0d94..cb2886e 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"ਵੌਇਸਮੇਲ"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"ਕਨੈਕਸ਼ਨ ਸਮੱਸਿਆ ਜਾਂ ਅਵੈਧ MMI ਕੋਡ।"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"ਵਿਸ਼ੇਸ਼ਤਾ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ।"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"ਓਪਰੇਸ਼ਨ ਕੇਵਲ ਫਿਕਸਡ ਡਾਇਲਿੰਗ ਨੰਬਰਾਂ ਤੱਕ ਸੀਮਿਤ ਹੈ।"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"ਤੁਹਾਡੇ ਰੋਮਿੰਗ ਵਿੱਚ ਹੋਣ ਦੌਰਾਨ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਕਾਲ ਫਾਰਵਰਡਿੰਗ ਸੈਟਿੰਗਾਂ ਨੂੰ ਬਦਲਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ।"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"ਸੇਵਾ ਅਸਮਰੱਥ ਬਣਾਈ ਗਈ ਸੀ।"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index a62873e..70c9e32 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Poczta głosowa"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problem z połączeniem lub błędny kod MMI."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funkcja nie jest obsługiwana."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operacja jest ograniczona wyłącznie do numerów ustalonych."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Podczas roamingu nie można zmienić ustawień przekazywania połączeń z telefonu."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Usługa została włączona."</string>
@@ -397,54 +398,30 @@
<string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"Pozwala aplikacji na trwałe zapisywanie swoich fragmentów w pamięci. Może to zmniejszyć ilość pamięci dostępnej dla innych aplikacji i spowolnić działanie telefonu."</string>
<string name="permlab_foregroundService" msgid="1768855976818467491">"uruchom usługę na pierwszym planie"</string>
<string name="permdesc_foregroundService" msgid="8720071450020922795">"Zezwala na korzystanie przez aplikację z usług na pierwszym planie."</string>
- <!-- no translation found for permlab_foregroundServiceCamera (7814751737955715297) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceCamera (6973701931250595727) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceConnectedDevice (3019650546176872501) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceConnectedDevice (1067457315741352963) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceDataSync (5847463514326881076) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceDataSync (2267140263423973050) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceLocation (3745428302378535690) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceLocation (118894034365177183) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaPlayback (4002687983891935514) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaPlayback (3638032446063968043) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaProjection (2630868915733312527) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaProjection (4805677128082002298) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMicrophone (7390033424890545399) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMicrophone (1206041516173483201) -->
- <skip />
- <!-- no translation found for permlab_foregroundServicePhoneCall (627937743867697892) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServicePhoneCall (5941660252587015147) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceHealth (3675776442080928184) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceHealth (2024586220562667185) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceRemoteMessaging (105670277002780950) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceRemoteMessaging (8767598075877576277) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSystemExempted (1597663713590612685) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSystemExempted (947381760834649622) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSpecialUse (7973536745876645082) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSpecialUse (646713654541885919) -->
- <skip />
+ <string name="permlab_foregroundServiceCamera" msgid="7814751737955715297">"uruchamianie usług działających na pierwszym planie typu „camera”"</string>
+ <string name="permdesc_foregroundServiceCamera" msgid="6973701931250595727">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „camera”"</string>
+ <string name="permlab_foregroundServiceConnectedDevice" msgid="3019650546176872501">"uruchamianie usług działających na pierwszym planie typu „connectedDevice”"</string>
+ <string name="permdesc_foregroundServiceConnectedDevice" msgid="1067457315741352963">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „connectedDevice”"</string>
+ <string name="permlab_foregroundServiceDataSync" msgid="5847463514326881076">"uruchamianie usług działających na pierwszym planie typu „dataSync”"</string>
+ <string name="permdesc_foregroundServiceDataSync" msgid="2267140263423973050">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „dataSync”"</string>
+ <string name="permlab_foregroundServiceLocation" msgid="3745428302378535690">"uruchamianie usług działających na pierwszym planie typu „location”"</string>
+ <string name="permdesc_foregroundServiceLocation" msgid="118894034365177183">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „location”"</string>
+ <string name="permlab_foregroundServiceMediaPlayback" msgid="4002687983891935514">"uruchamianie usług działających na pierwszym planie typu „mediaPlayback”"</string>
+ <string name="permdesc_foregroundServiceMediaPlayback" msgid="3638032446063968043">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „mediaPlayback”"</string>
+ <string name="permlab_foregroundServiceMediaProjection" msgid="2630868915733312527">"uruchamianie usług działających na pierwszym planie typu „mediaProjection”"</string>
+ <string name="permdesc_foregroundServiceMediaProjection" msgid="4805677128082002298">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „mediaProjection”"</string>
+ <string name="permlab_foregroundServiceMicrophone" msgid="7390033424890545399">"uruchamianie usług działających na pierwszym planie typu „microphone”"</string>
+ <string name="permdesc_foregroundServiceMicrophone" msgid="1206041516173483201">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „microphone”"</string>
+ <string name="permlab_foregroundServicePhoneCall" msgid="627937743867697892">"uruchamianie usług działających na pierwszym planie typu „phoneCall”"</string>
+ <string name="permdesc_foregroundServicePhoneCall" msgid="5941660252587015147">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „phoneCall”"</string>
+ <string name="permlab_foregroundServiceHealth" msgid="3675776442080928184">"uruchamianie usług działających na pierwszym planie typu „health”"</string>
+ <string name="permdesc_foregroundServiceHealth" msgid="2024586220562667185">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „health”"</string>
+ <string name="permlab_foregroundServiceRemoteMessaging" msgid="105670277002780950">"uruchamianie usług działających na pierwszym planie typu „remoteMessaging”"</string>
+ <string name="permdesc_foregroundServiceRemoteMessaging" msgid="8767598075877576277">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „remoteMessaging”"</string>
+ <string name="permlab_foregroundServiceSystemExempted" msgid="1597663713590612685">"uruchamianie usług działających na pierwszym planie typu „systemExempted”"</string>
+ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „systemExempted”"</string>
+ <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"uruchamianie usług działających na pierwszym planie typu „specialUse”"</string>
+ <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „specialUse”"</string>
<string name="permlab_getPackageSize" msgid="375391550792886641">"mierzenie rozmiaru pamięci aplikacji"</string>
<string name="permdesc_getPackageSize" msgid="742743530909966782">"Pozwala aplikacji na pobieranie własnego kodu, danych oraz rozmiarów pamięci podręcznej."</string>
<string name="permlab_writeSettings" msgid="8057285063719277394">"modyfikowanie ustawień systemu"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index a9830e7..255ed46 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Correio de voz"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problema de conexão ou código MMI inválido."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Recurso indisponível."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"A operação é limitada somente a números de discagem fixa."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Não é possível alterar as configurações de encaminhamento de chamada do seu smartphone em roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"O serviço foi ativado."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index e2966a2..480de87 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Correio de voz"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problema de ligação ou código MMI inválido."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funcionalidade não suportada."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"A operação está restringida a números fixos autorizados."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Não é possível alterar as definições do encaminhamento de chamadas no telemóvel quando está em roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"O serviço foi ativado."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index a9830e7..255ed46 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Correio de voz"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problema de conexão ou código MMI inválido."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Recurso indisponível."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"A operação é limitada somente a números de discagem fixa."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Não é possível alterar as configurações de encaminhamento de chamada do seu smartphone em roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"O serviço foi ativado."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index d300dfa..4d8d96b4 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Mesagerie vocală"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problemă de conexiune sau cod MMI nevalid."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funcția nu este acceptată."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operația este limitată la numerele cu apelări restricționate."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Nu poți schimba setările de redirecționare a apelurilor de pe telefon când ești în roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Serviciul a fost activat."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 36fa51b..353131e 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Голосовая почта"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Неполадки подключения или неверный код MMI."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Функция не поддерживается."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Операция возможна только для разрешенных номеров."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Вы не можете изменить настройки переадресации вызовов, поскольку находитесь в роуминге."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Служба включена."</string>
@@ -89,7 +90,7 @@
<string name="notification_channel_network_alert" msgid="4788053066033851841">"Оповещения"</string>
<string name="notification_channel_call_forward" msgid="8230490317314272406">"Переадресация вызовов"</string>
<string name="notification_channel_emergency_callback" msgid="54074839059123159">"Режим экстренных обратных вызовов"</string>
- <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"Состояние мобильного Интернета"</string>
+ <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"Состояние мобильного интернета"</string>
<string name="notification_channel_sms" msgid="1243384981025535724">"SMS"</string>
<string name="notification_channel_voice_mail" msgid="8457433203106654172">"Голосовые сообщения"</string>
<string name="notification_channel_wfc" msgid="9048240466765169038">"Звонки по Wi-Fi"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 4f9fb41..7bee4de 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"කටහඬ තැපෑල"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"සම්බන්ධතා ගැටළුවක් හෝ අවලංගු MMI කේතයකි."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"විශේෂාංගය සහාය නොදක්වයි."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"ස්ථාවර ඇමතීම් අංක වලට පමණක් මෙහෙයුම සීමාකර ඇත."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"ඔබ රෝමිං තුළ සිටින අතරතුර ඔබේ දුරකථනයෙන් ඇමතුම් ප්රතියොමු සැකසීම් වෙනස් කළ නොහැකිය."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"සේවාව සබල කරන ලදි."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 74d11ff..7fa87e4 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Hlasová schránka"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problém s pripojením alebo neplatný kód MMI."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funkcia nie je podporovaná."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operácia je obmedzená len na povolené čísla."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Nastavenia presmerovania hovorov nie je možné zmeniť z telefónu počas roamingu."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Služba bola povolená."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 0111719..d98a130 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Glasovna pošta"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Težava s povezavo ali neveljavna koda MMI."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funkcija ni podprta."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Operacija je omejena na dovoljene telefonske številke, za katere ne velja zapora odhodnega klica."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Nastavitev preusmerjanja klicev ni mogoče spremeniti v telefonu med gostovanjem v tujem omrežju."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Storitev je omogočena."</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 799f483..17c1f63a 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Posta zanore"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problem në lidhje ose kod i pavlefshëm MMI-je."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Veçoria nuk mbështetet."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Veprimi është i kufizuar vetëm kundrejt numrave me telefonim të përzgjedhur"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Cilësimet e transferimit të telefonatave nuk mund të ndryshohen nga telefoni yt kur je në roaming."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Shërbimi u aktivizua."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index f5de284..e7b1b12 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Гласовна пошта"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Проблеми са везом или неважећи MMI кôд."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Функција није подржана."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Рад је ограничен само на бројеве фиксног бирања."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Не можете да промените подешавања преусмеравања позива са телефона док сте у ромингу."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Услуга је омогућена."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index dec226a..7d4ba74 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Röstbrevlåda"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Anslutningsproblem eller ogiltig MMI-kod."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Funktionen stöds inte."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Endast fasta nummer kan användas."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Det går inte att ändra inställningarna för vidarebefordran av samtal medan mobilen är i roaming-läge."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Tjänsten har aktiverats."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index a68fcc8..7c27b96 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -28,6 +28,8 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Ujumbe wa sauti"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Tatizo la muunganisho au msimbo batili MMI."</string>
+ <!-- no translation found for mmiErrorNotSupported (5001803469335286099) -->
+ <skip />
<string name="mmiFdnError" msgid="3975490266767565852">"Ni matumizi yanayohusisha nambari za simu zilizobainishwa pekee yatakayowezekana."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Haiwezi kubadilisha mipangilio ya kusambaza simu kutoka kwenye simu yako ukiwa unatumia mitandao mingine."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Huduma iliwezeshwa"</string>
@@ -395,54 +397,30 @@
<string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"Inaruhusu programu kuendelesha vijisehemu vyake kwenye kumbukumbu. Hii inaweza kupunguza kumbukumbu inayopatikana katika programu nyingine ikipunguza kasi ya simu."</string>
<string name="permlab_foregroundService" msgid="1768855976818467491">"tumia huduma zinazoonekana kwenye skrini"</string>
<string name="permdesc_foregroundService" msgid="8720071450020922795">"Huruhusu programu kutumia huduma zinazoonekana kwenye skrini."</string>
- <!-- no translation found for permlab_foregroundServiceCamera (7814751737955715297) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceCamera (6973701931250595727) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceConnectedDevice (3019650546176872501) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceConnectedDevice (1067457315741352963) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceDataSync (5847463514326881076) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceDataSync (2267140263423973050) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceLocation (3745428302378535690) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceLocation (118894034365177183) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaPlayback (4002687983891935514) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaPlayback (3638032446063968043) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaProjection (2630868915733312527) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaProjection (4805677128082002298) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMicrophone (7390033424890545399) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMicrophone (1206041516173483201) -->
- <skip />
- <!-- no translation found for permlab_foregroundServicePhoneCall (627937743867697892) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServicePhoneCall (5941660252587015147) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceHealth (3675776442080928184) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceHealth (2024586220562667185) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceRemoteMessaging (105670277002780950) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceRemoteMessaging (8767598075877576277) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSystemExempted (1597663713590612685) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSystemExempted (947381760834649622) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSpecialUse (7973536745876645082) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSpecialUse (646713654541885919) -->
- <skip />
+ <string name="permlab_foregroundServiceCamera" msgid="7814751737955715297">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"camera\""</string>
+ <string name="permdesc_foregroundServiceCamera" msgid="6973701931250595727">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"camera\""</string>
+ <string name="permlab_foregroundServiceConnectedDevice" msgid="3019650546176872501">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"connectedDevice\""</string>
+ <string name="permdesc_foregroundServiceConnectedDevice" msgid="1067457315741352963">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"connectedDevice\""</string>
+ <string name="permlab_foregroundServiceDataSync" msgid="5847463514326881076">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"dataSync\""</string>
+ <string name="permdesc_foregroundServiceDataSync" msgid="2267140263423973050">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"dataSync\""</string>
+ <string name="permlab_foregroundServiceLocation" msgid="3745428302378535690">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"location\""</string>
+ <string name="permdesc_foregroundServiceLocation" msgid="118894034365177183">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"health\""</string>
+ <string name="permlab_foregroundServiceMediaPlayback" msgid="4002687983891935514">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"mediaPlayback\""</string>
+ <string name="permdesc_foregroundServiceMediaPlayback" msgid="3638032446063968043">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"mediaPlayback\""</string>
+ <string name="permlab_foregroundServiceMediaProjection" msgid="2630868915733312527">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"mediaProjection\""</string>
+ <string name="permdesc_foregroundServiceMediaProjection" msgid="4805677128082002298">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"mediaProjection\""</string>
+ <string name="permlab_foregroundServiceMicrophone" msgid="7390033424890545399">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"microphone\""</string>
+ <string name="permdesc_foregroundServiceMicrophone" msgid="1206041516173483201">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"microphone\""</string>
+ <string name="permlab_foregroundServicePhoneCall" msgid="627937743867697892">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"phoneCall\""</string>
+ <string name="permdesc_foregroundServicePhoneCall" msgid="5941660252587015147">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"phoneCall\""</string>
+ <string name="permlab_foregroundServiceHealth" msgid="3675776442080928184">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"health\""</string>
+ <string name="permdesc_foregroundServiceHealth" msgid="2024586220562667185">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"health\""</string>
+ <string name="permlab_foregroundServiceRemoteMessaging" msgid="105670277002780950">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"remoteMessaging\""</string>
+ <string name="permdesc_foregroundServiceRemoteMessaging" msgid="8767598075877576277">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"remoteMessaging\""</string>
+ <string name="permlab_foregroundServiceSystemExempted" msgid="1597663713590612685">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"systemExempted\""</string>
+ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"systemExempted\""</string>
+ <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"specialUse\""</string>
+ <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"specialUse\""</string>
<string name="permlab_getPackageSize" msgid="375391550792886641">"Pima nafasi ya hifadhi ya programu"</string>
<string name="permdesc_getPackageSize" msgid="742743530909966782">"Huruhusu Programu kupata tena msimbo, data na ukubwa wa akiba yake"</string>
<string name="permlab_writeSettings" msgid="8057285063719277394">"rekebisha mipangilio ya mfumo"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 20875bb..7e1ad9e 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"குரலஞ்சல்"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"இணைப்பு சிக்கல் அல்லது தவறான MMI குறியீடு."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"அம்சம் ஆதரிக்கப்படவில்லை."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"நிலையான அழைப்பு எண்களுக்கு மட்டுமே எனச் செயல்பாடு வரையறுக்கப்பட்டுள்ளது."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"ரோமிங்கில் இருக்கும் போது, உங்கள் மொபைலிலிருந்து அழைப்புப் பகிர்வு அமைப்புகளை மாற்ற முடியாது."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"சேவை இயக்கப்பட்டுள்ளது."</string>
@@ -395,54 +396,30 @@
<string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"நினைவகத்தில் நிலையாக இருக்கும் தன்னுடைய பகுதிகளை உருவாக்கப் ஆப்ஸை அனுமதிக்கிறது. இதனால பிற பயன்பாடுகளுக்குக் கிடைக்கும் நினைவகம் வரையறுக்கப்பட்டு, மொபைலின் வேகத்தைக் குறைக்கலாம்"</string>
<string name="permlab_foregroundService" msgid="1768855976818467491">"முன்புலத்தில் இயங்கும் சேவையை இயக்குதல்"</string>
<string name="permdesc_foregroundService" msgid="8720071450020922795">"முன்புலத்தில் இயங்கும் சேவைகளை உபயோகிக்க, ஆப்ஸை அனுமதிக்கிறது."</string>
- <!-- no translation found for permlab_foregroundServiceCamera (7814751737955715297) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceCamera (6973701931250595727) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceConnectedDevice (3019650546176872501) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceConnectedDevice (1067457315741352963) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceDataSync (5847463514326881076) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceDataSync (2267140263423973050) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceLocation (3745428302378535690) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceLocation (118894034365177183) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaPlayback (4002687983891935514) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaPlayback (3638032446063968043) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMediaProjection (2630868915733312527) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMediaProjection (4805677128082002298) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceMicrophone (7390033424890545399) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceMicrophone (1206041516173483201) -->
- <skip />
- <!-- no translation found for permlab_foregroundServicePhoneCall (627937743867697892) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServicePhoneCall (5941660252587015147) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceHealth (3675776442080928184) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceHealth (2024586220562667185) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceRemoteMessaging (105670277002780950) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceRemoteMessaging (8767598075877576277) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSystemExempted (1597663713590612685) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSystemExempted (947381760834649622) -->
- <skip />
- <!-- no translation found for permlab_foregroundServiceSpecialUse (7973536745876645082) -->
- <skip />
- <!-- no translation found for permdesc_foregroundServiceSpecialUse (646713654541885919) -->
- <skip />
+ <string name="permlab_foregroundServiceCamera" msgid="7814751737955715297">"\"camera\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string>
+ <string name="permdesc_foregroundServiceCamera" msgid="6973701931250595727">"\"camera\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string>
+ <string name="permlab_foregroundServiceConnectedDevice" msgid="3019650546176872501">"\"connectedDevice\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string>
+ <string name="permdesc_foregroundServiceConnectedDevice" msgid="1067457315741352963">"\"connectedDevice\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string>
+ <string name="permlab_foregroundServiceDataSync" msgid="5847463514326881076">"\"dataSync\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string>
+ <string name="permdesc_foregroundServiceDataSync" msgid="2267140263423973050">"\"dataSync\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string>
+ <string name="permlab_foregroundServiceLocation" msgid="3745428302378535690">"\"location\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string>
+ <string name="permdesc_foregroundServiceLocation" msgid="118894034365177183">"\"location\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string>
+ <string name="permlab_foregroundServiceMediaPlayback" msgid="4002687983891935514">"\"mediaPlayback\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string>
+ <string name="permdesc_foregroundServiceMediaPlayback" msgid="3638032446063968043">"\"mediaPlayback\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string>
+ <string name="permlab_foregroundServiceMediaProjection" msgid="2630868915733312527">"\"mediaProjection\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string>
+ <string name="permdesc_foregroundServiceMediaProjection" msgid="4805677128082002298">"\"mediaProjection\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string>
+ <string name="permlab_foregroundServiceMicrophone" msgid="7390033424890545399">"\"microphone\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string>
+ <string name="permdesc_foregroundServiceMicrophone" msgid="1206041516173483201">"\"microphone\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string>
+ <string name="permlab_foregroundServicePhoneCall" msgid="627937743867697892">"\"phoneCall\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string>
+ <string name="permdesc_foregroundServicePhoneCall" msgid="5941660252587015147">"\"phoneCall\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string>
+ <string name="permlab_foregroundServiceHealth" msgid="3675776442080928184">"\"health\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string>
+ <string name="permdesc_foregroundServiceHealth" msgid="2024586220562667185">"\"health\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string>
+ <string name="permlab_foregroundServiceRemoteMessaging" msgid="105670277002780950">"\"remoteMessaging\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string>
+ <string name="permdesc_foregroundServiceRemoteMessaging" msgid="8767598075877576277">"\"remoteMessaging\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string>
+ <string name="permlab_foregroundServiceSystemExempted" msgid="1597663713590612685">"\"systemExempted\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string>
+ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"\"systemExempted\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string>
+ <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string>
+ <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"\"specialUse\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string>
<string name="permlab_getPackageSize" msgid="375391550792886641">"ஆப்ஸ் சேமிப்பு இடத்தை அளவிடல்"</string>
<string name="permdesc_getPackageSize" msgid="742743530909966782">"ஆப்ஸ், அதன் குறியீடு, தரவு, மற்றும் தற்காலிகச் சேமிப்பு அளவுகளை மீட்டெடுக்க அனுமதிக்கிறது"</string>
<string name="permlab_writeSettings" msgid="8057285063719277394">"சாதன அமைப்புகளை மாற்றுதல்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index df8d773..5355f6f 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"వాయిస్ మెయిల్"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"కనెక్షన్ సమస్య లేదా చెల్లని MMI కోడ్."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"ప్రస్తుత మొబైల్ నెట్వర్క్లో ఫీచర్ సపోర్ట్ చేయడం లేదు."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"చర్య స్థిరమైన డయలింగ్ నంబర్లకు మాత్రమే పరిమితం చేయబడింది."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"మీరు రోమింగ్లో ఉన్నప్పుడు మీ ఫోన్ నుండి కాల్ ఫార్వార్డింగ్ సెట్టింగ్లను మార్చలేరు."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"సేవ ప్రారంభించబడింది."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b5af3de..1bdaa50 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"ข้อความเสียง"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"ปัญหาการเชื่อมต่อหรือรหัส MMI ไม่ถูกต้อง"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"ไม่รองรับฟีเจอร์"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"การดำเนินการถูกจำกัดไว้ที่การจำกัดหมายเลขโทรออกเท่านั้น"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"ไม่สามารถเปลี่ยนการตั้งค่าการโอนสายจากโทรศัพท์ในขณะที่โรมมิ่ง"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"เปิดใช้งานบริการแล้ว"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 097abd6..bb17eb9 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Voicemail"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Problema sa koneksyon o di-wastong MMI code."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Hindi sinusuportahan ang feature."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Pinaghihigpitan ang pagpapatakbo sa mga fixed dialing number lang."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Hindi maaaring baguhin ang mga setting ng pagpapasa ng tawag mula sa iyong telepono habang naka-roaming ka."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Pinagana ang serbisyo."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 4bf637a..3e974e3 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Sesli Mesaj"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Bağlantı sorunu veya geçersiz MMI kodu."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Özellik desteklenmiyor."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"İşlem sadece sabit arama numaralarıyla sınırlandırılmıştır."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Dolaşımdayken telefonunuzdan çağrı yönlendirme ayarları değiştirilemiyor."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Hizmet etkindi."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 6e114dd..6434c2c 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Голосова пошта"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Пробл. підключення чи недійсний код MMI."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Функція не підтримується."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Операція лише для номерів фіксованого набору."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"У роумінгу на телефоні не можна змінити налаштування переадресації викликів."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Послугу ввімкнено."</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 8afb2c8..9d15d64 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"صوتی میل"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"کنکشن مسئلہ یا غلط MMI کوڈ۔"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"خصوصیت تعاون یافتہ نہیں ہے۔"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"آپریشن صرف متعین ڈائلنگ نمبرز تک محدود ہے۔"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"جب آپ رومنگ پر ہوں تو اپنے فون سے کال فارورڈنگ کی ترتیبات تبدیل نہیں کی جا سکتیں۔"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"سروس فعال کی گئی۔"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 984981d..f987eae 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Ovozli pochta"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Tarmoqda xato yoki MMI kod noto‘g‘ri."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Ishlamaydigan funksiya."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Bu amal faqat ruxsat etilgan raqamlar uchun mavjud."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Rouming vaqtida telefondagi chaqiruvni boshqa raqamga uzatish sozlamalarini o‘zgartirib bo‘lmadi."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Xizmat yoqildi."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 4e2dceb..af1ae05 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Thư thoại"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Sự cố kết nối hoặc mã MMI không hợp lệ."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Tính năng không được hỗ trợ."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Chỉ hạn chế thao tác đối với số quay số định sẵn."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Không thể thay đổi cài đặt chuyển tiếp cuộc gọi từ điện thoại của bạn khi bạn đang chuyển vùng."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Dịch vụ đã được bật."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index d4bfe15..73f5b034 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"语音信箱"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"出现连接问题或 MMI 码无效。"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"不支持此功能。"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"只能对固定拨号号码执行此类操作。"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"漫游时无法通过您的手机来更改来电转接设置。"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"已启用服务。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 8344683..4993c89 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"留言信箱"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"連線發生問題或 MMI 碼無效。"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"不支援的功能。"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"僅限對固定撥號號碼執行這項運作。"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"使用漫遊服務時,不可從手機變更來電轉駁設定。"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"服務已啟用。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 0f48935..7dde343 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"語音留言"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"連線發生問題或錯誤的 MMI 碼。"</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"不支援的功能。"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"僅限對固定撥號號碼執行此作業。"</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"漫遊時無法透過你的手機變更來電轉接設定。"</string>
<string name="serviceEnabled" msgid="7549025003394765639">"服務已啟用。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index cd8fcc7..86f869d 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -28,6 +28,7 @@
<string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"Ivoyisimeyili"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"Inkinga yoxhumano noma ikhadi ye-MMI engalungile."</string>
+ <string name="mmiErrorNotSupported" msgid="5001803469335286099">"Isakhi asisekelwa."</string>
<string name="mmiFdnError" msgid="3975490266767565852">"Umsebenzi uvinjelwe ekudayeleni izinombolo ezingaguquki kuphela."</string>
<string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Ayikwazi ukushintsha izilungiselelo zokudluliselwa kwekholi kusuka efonini yakho ngenkathi uzula."</string>
<string name="serviceEnabled" msgid="7549025003394765639">"Isevisi ivaliwe."</string>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index eb70344..abbff58 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -3165,20 +3165,20 @@
<attr name="canDisplayOnRemoteDevices" format="boolean"/>
<attr name="allowUntrustedActivityEmbedding" />
<attr name="knownActivityEmbeddingCerts" />
- <!-- Specifies the category of the target display the activity is expected to run on. Upon
- creation, a virtual display can specify which display categories it supports and one of
- the category must be present in the activity's manifest to allow this activity to run.
- The default value is {@code null}, which indicates the activity does not belong to a
- restricted display category and thus can only run on a display that didn't specify any
- display categories. Each activity can only specify one category it targets to but a
- virtual display can accommodate multiple restricted categories.
+ <!-- Specifies the required display category of the activity. Upon creation, a display can
+ specify which display categories it supports and one of the categories must be present
+ in the {@code <activity>} element to allow this activity to run. The default value is
+ {@code null}, which indicates the activity does not have a required display category
+ and thus can only run on a display that didn't specify any display categories. Each
+ activity can only specify one required category but a display can accommodate multiple
+ display categories.
<p> This field should be formatted as a Java-language-style free form string(for
example, com.google.automotive_entertainment), which may contain uppercase or lowercase
letters ('A' through 'Z'), numbers, and underscores ('_') but may only start with
letters.
-->
- <attr name="targetDisplayCategory" format="string"/>
+ <attr name="requiredDisplayCategory" format="string"/>
</declare-styleable>
<!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2ab5b75..9a585a1 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2078,6 +2078,13 @@
<!-- Flag indicating whether the current device supports "Ask every time" for sms-->
<bool name="config_sms_ask_every_time_support">true</bool>
+ <!-- Flag indicating whether the current device allows acknowledgement of SIM operation like
+ SM-PP or saving SMS to SIM can be done via the IMS interfaces.
+ If true,this means that the device supports sending of sim operation response via the
+ IMS interface APIs. This can be overridden to false for devices which can't send
+ sim operation acknowledgements via IMS interface APIs. -->
+ <bool name="config_smppsim_response_via_ims">false</bool>
+
<!-- Flag indicating whether the current device allows data.
If true, this means that the device supports data connectivity through
the telephony network.
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index bc5878a..a9bec7a9 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -116,7 +116,7 @@
<public name="handwritingBoundsOffsetBottom" />
<public name="accessibilityDataPrivate" />
<public name="enableTextStylingShortcuts" />
- <public name="targetDisplayCategory"/>
+ <public name="requiredDisplayCategory"/>
<public name="maxConcurrentSessionsCount" />
</staging-public-group>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 168806a..ace7e4c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -315,6 +315,7 @@
<java-symbol type="bool" name="config_sms_ask_every_time_support" />
<java-symbol type="bool" name="config_sms_capable" />
<java-symbol type="bool" name="config_sms_utf8_support" />
+ <java-symbol type="bool" name="config_smppsim_response_via_ims" />
<java-symbol type="bool" name="config_mobile_data_capable" />
<java-symbol type="bool" name="config_suspendWhenScreenOffDueToProximity" />
<java-symbol type="bool" name="config_swipeDisambiguation" />
diff --git a/core/tests/coretests/src/android/app/backup/BackupManagerTest.java b/core/tests/coretests/src/android/app/backup/BackupManagerTest.java
new file mode 100644
index 0000000..cbf167c
--- /dev/null
+++ b/core/tests/coretests/src/android/app/backup/BackupManagerTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.app.backup;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+
+import android.app.backup.BackupAnnotations.BackupDestination;
+import android.app.backup.BackupAnnotations.OperationType;
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.function.ThrowingRunnable;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.IOException;
+
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class BackupManagerTest {
+ private BackupManager mBackupManager;
+
+ @Mock
+ Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mBackupManager = new BackupManager(mContext);
+ }
+
+ @Test
+ public void testGetBackupRestoreEventLogger_returnsBackupLoggerForBackup() {
+ BackupAgent agent = getTestAgent();
+ agent.onCreate(UserHandle.SYSTEM, BackupDestination.CLOUD,
+ OperationType.BACKUP);
+
+ BackupRestoreEventLogger logger = mBackupManager.getBackupRestoreEventLogger(agent);
+
+ assertThat(logger.getOperationType()).isEqualTo(OperationType.BACKUP);
+ }
+
+ @Test
+ public void testGetBackupRestoreEventLogger_returnsRestoreLoggerForRestore() {
+ BackupAgent agent = getTestAgent();
+ agent.onCreate(UserHandle.SYSTEM, BackupDestination.CLOUD,
+ OperationType.RESTORE);
+
+ BackupRestoreEventLogger logger = mBackupManager.getBackupRestoreEventLogger(agent);
+
+ assertThat(logger.getOperationType()).isEqualTo(OperationType.RESTORE);
+ }
+
+ @Test
+ public void testGetBackupRestoreEventLogger_uninitialisedAgent_throwsException() {
+ BackupAgent agent = getTestAgent();
+
+ assertThrows(IllegalStateException.class,
+ () -> mBackupManager.getBackupRestoreEventLogger(agent));
+ }
+
+ private static BackupAgent getTestAgent() {
+ return new BackupAgent() {
+ @Override
+ public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+ ParcelFileDescriptor newState) throws IOException {
+
+ }
+
+ @Override
+ public void onRestore(BackupDataInput data, int appVersionCode,
+ ParcelFileDescriptor newState) throws IOException {
+
+ }
+ };
+ }
+
+}
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
index cfca037..625c318 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
@@ -18,8 +18,12 @@
import androidx.core.util.forEach
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import kotlin.math.ceil
+import kotlin.math.floor
import org.junit.Test
import org.junit.runner.RunWith
@@ -72,7 +76,70 @@
}
}
+ @LargeTest
+ @Test
+ fun allFeasibleScalesAndConversionsDoNotCrash() {
+ generateSequenceOfFractions(-10000f..10000f, step = 0.01f)
+ .mapNotNull{ FontScaleConverterFactory.forScale(it) }
+ .flatMap{ table ->
+ generateSequenceOfFractions(-10000f..10000f, step = 0.01f)
+ .map{ Pair(table, it) }
+ }
+ .forEach { (table, sp) ->
+ try {
+ assertWithMessage(
+ "convertSpToDp(%s) on table: %s",
+ sp.toString(),
+ table.toString()
+ )
+ .that(table.convertSpToDp(sp))
+ .isFinite()
+ } catch (e: Exception) {
+ throw AssertionError("Exception during convertSpToDp($sp) on table: $table", e)
+ }
+ }
+ }
+
+ @Test
+ fun testGenerateSequenceOfFractions() {
+ val fractions = generateSequenceOfFractions(-1000f..1000f, step = 0.1f)
+ .toList()
+ fractions.forEach {
+ assertThat(it).isAtLeast(-1000f)
+ assertThat(it).isAtMost(1000f)
+ }
+
+ assertThat(fractions).isInStrictOrder()
+ assertThat(fractions).hasSize(1000 * 2 * 10 + 1) // Don't forget the 0 in the middle!
+
+ assertThat(fractions).contains(100f)
+ assertThat(fractions).contains(500.1f)
+ assertThat(fractions).contains(500.2f)
+ assertThat(fractions).contains(0.2f)
+ assertThat(fractions).contains(0f)
+ assertThat(fractions).contains(-10f)
+ assertThat(fractions).contains(-10f)
+ assertThat(fractions).contains(-10.3f)
+
+ assertThat(fractions).doesNotContain(-10.31f)
+ assertThat(fractions).doesNotContain(0.35f)
+ assertThat(fractions).doesNotContain(0.31f)
+ assertThat(fractions).doesNotContain(-.35f)
+ }
+
companion object {
private const val CONVERSION_TOLERANCE = 0.05f
}
}
+
+fun generateSequenceOfFractions(
+ range: ClosedFloatingPointRange<Float>,
+ step: Float
+): Sequence<Float> {
+ val multiplier = 1f / step
+ val start = floor(range.start * multiplier).toInt()
+ val endInclusive = ceil(range.endInclusive * multiplier).toInt()
+ return generateSequence(start) { it + 1 }
+ .takeWhile { it <= endInclusive }
+ .map{ it.toFloat() / multiplier }
+}
diff --git a/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigTest.java b/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigTest.java
index caec365..0f30cfe 100644
--- a/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigTest.java
+++ b/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigTest.java
@@ -286,6 +286,39 @@
}
@Test
+ public void testPartialConfigPartitionPrecedence() throws IOException {
+ createFile("/odm/overlay/config/config.xml",
+ "<config>"
+ + " <overlay package=\"two\" enabled=\"true\" />"
+ + "</config>");
+
+ mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
+ 1);
+ mScannerRule.addOverlay(createFile("/odm/overlay/two.apk"), "two");
+ mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three", "android", 0,
+ true, 0);
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", false, true, 0);
+ assertConfig(overlayConfig, "two", true, true, 1);
+ assertConfig(overlayConfig, "three", false, true, 2);
+ }
+
+ @Test
+ public void testNoConfigPartitionPrecedence() throws IOException {
+ mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
+ 1);
+ mScannerRule.addOverlay(createFile("/odm/overlay/two.apk"), "two", "android", 0, true, 2);
+ mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three", "android", 0,
+ true, 0);
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", false, true, 0);
+ assertConfig(overlayConfig, "two", false, true, 1);
+ assertConfig(overlayConfig, "three", false, true, 2);
+ }
+
+ @Test
public void testImmutable() throws IOException {
createFile("/product/overlay/config/config.xml",
"<config>"
@@ -507,37 +540,6 @@
}
@Test
- public void testNoConfigsAllowPartitionReordering() throws IOException {
- mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
- 1);
- mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 0, true,
- 0);
-
- final OverlayConfig overlayConfig = createConfigImpl();
- assertConfig(overlayConfig, "one", false, true, 1);
- assertConfig(overlayConfig, "two", false, true, 0);
- }
-
- @Test
- public void testConfigDisablesPartitionReordering() throws IOException {
- createFile("/odm/overlay/config/config.xml",
- "<config>"
- + " <overlay package=\"two\" enabled=\"true\" />"
- + "</config>");
-
- mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
- 1);
- mScannerRule.addOverlay(createFile("/odm/overlay/two.apk"), "two");
- mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three", "android", 0,
- true, 0);
-
- final OverlayConfig overlayConfig = createConfigImpl();
- assertConfig(overlayConfig, "one", false, true, 0);
- assertConfig(overlayConfig, "two", true, true, 1);
- assertConfig(overlayConfig, "three", false, true, 2);
- }
-
- @Test
public void testStaticOverlayOutsideOverlayDir() throws IOException {
mScannerRule.addOverlay(createFile("/product/app/one.apk"), "one", "android", 0, true, 0);
@@ -550,7 +552,7 @@
@Test
public void testSortStaticOverlaysDifferentTargets() throws IOException {
mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "other", 0, true, 0);
- mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 0, true,
+ mScannerRule.addOverlay(createFile("/vendor/overlay/two.apk"), "two", "android", 0, true,
0);
final OverlayConfig overlayConfig = createConfigImpl();
@@ -559,15 +561,33 @@
}
@Test
+ public void testSortStaticOverlaysDifferentPartitions() throws IOException {
+ mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
+ 2);
+ mScannerRule.addOverlay(createFile("/vendor/overlay/two.apk"), "two", "android", 0, true,
+ 3);
+ mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three", "android", 0,
+ true, 0);
+ mScannerRule.addOverlay(createFile("/product/overlay/four.apk"), "four", "android", 0,
+ true, 1);
+
+ final OverlayConfig overlayConfig = createConfigImpl();
+ assertConfig(overlayConfig, "one", false, true, 0);
+ assertConfig(overlayConfig, "two", false, true, 1);
+ assertConfig(overlayConfig, "three", false, true, 2);
+ assertConfig(overlayConfig, "four", false, true, 3);
+ }
+
+ @Test
public void testSortStaticOverlaysSamePriority() throws IOException {
mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
0);
- mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 0, true,
+ mScannerRule.addOverlay(createFile("/vendor/overlay/two.apk"), "two", "android", 0, true,
0);
final OverlayConfig overlayConfig = createConfigImpl();
- assertConfig(overlayConfig, "one", false, true, 1);
- assertConfig(overlayConfig, "two", false, true, 0);
+ assertConfig(overlayConfig, "one", false, true, 0);
+ assertConfig(overlayConfig, "two", false, true, 1);
}
@Test
diff --git a/core/tests/fuzzers/FuzzService/FuzzBinder.java b/core/tests/fuzzers/FuzzService/FuzzBinder.java
index 7096f52..52aafeb 100644
--- a/core/tests/fuzzers/FuzzService/FuzzBinder.java
+++ b/core/tests/fuzzers/FuzzService/FuzzBinder.java
@@ -15,6 +15,7 @@
*/
package randomparcel;
import android.os.IBinder;
+import android.os.Parcel;
public class FuzzBinder {
static {
@@ -33,6 +34,12 @@
fuzzServiceInternal(binder, data);
}
+ // This API creates random parcel object
+ public static void createRandomParcel(Parcel parcel, byte[] data) {
+ getRandomParcel(parcel, data);
+ }
+
private static native void fuzzServiceInternal(IBinder binder, byte[] data);
+ private static native void getRandomParcel(Parcel parcel, byte[] data);
private static native int registerNatives();
}
diff --git a/core/tests/fuzzers/FuzzService/random_parcel_jni.cpp b/core/tests/fuzzers/FuzzService/random_parcel_jni.cpp
index c0528d5..dbeae87 100644
--- a/core/tests/fuzzers/FuzzService/random_parcel_jni.cpp
+++ b/core/tests/fuzzers/FuzzService/random_parcel_jni.cpp
@@ -16,7 +16,9 @@
#include "random_parcel_jni.h"
#include <android_util_Binder.h>
+#include <android_os_Parcel.h>
#include <fuzzbinder/libbinder_driver.h>
+#include <fuzzbinder/random_parcel.h>
#include <fuzzer/FuzzedDataProvider.h>
using namespace android;
@@ -35,3 +37,15 @@
JNIEXPORT jint JNICALL Java_randomparcel_FuzzBinder_registerNatives(JNIEnv* env) {
return registerFrameworkNatives(env);
}
+
+JNIEXPORT void JNICALL Java_randomparcel_FuzzBinder_getRandomParcel(JNIEnv *env, jobject thiz, jobject jparcel, jbyteArray fuzzData) {
+ size_t len = static_cast<size_t>(env->GetArrayLength(fuzzData));
+ uint8_t data[len];
+ env->GetByteArrayRegion(fuzzData, 0, len, reinterpret_cast<jbyte*>(data));
+
+ FuzzedDataProvider provider(data, len);
+ RandomParcelOptions options;
+
+ Parcel* parcel = parcelForJavaObject(env, jparcel);
+ fillRandomParcel(parcel, std::move(provider), &options);
+}
diff --git a/core/tests/fuzzers/FuzzService/random_parcel_jni.h b/core/tests/fuzzers/FuzzService/random_parcel_jni.h
index 20a4c9d..bc18b2f 100644
--- a/core/tests/fuzzers/FuzzService/random_parcel_jni.h
+++ b/core/tests/fuzzers/FuzzService/random_parcel_jni.h
@@ -23,4 +23,6 @@
// Function from AndroidRuntime
jint registerFrameworkNatives(JNIEnv* env);
+
+ JNIEXPORT void JNICALL Java_randomparcel_FuzzBinder_getRandomParcel(JNIEnv *env, jobject thiz, jobject parcel, jbyteArray fuzzData);
}
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index 54d6428..e62ac46 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -96,7 +96,7 @@
// These are also implemented in RecordingCanvas so that we can
// selectively apply on them
// Everything below here is copy/pasted from Canvas.java
- // The JNI registration is handled by android_view_Canvas.cpp
+ // The JNI registration is handled by android_graphics_Canvas.cpp
// ---------------------------------------------------------------------------
public void drawArc(float left, float top, float right, float bottom, float startAngle,
@@ -670,6 +670,17 @@
/**
* @hide
*/
+ public void drawMesh(Mesh mesh, BlendMode blendMode, Paint paint) {
+ if (!isHardwareAccelerated() && onHwFeatureInSwMode()) {
+ throw new RuntimeException("software rendering doesn't support meshes");
+ }
+ nDrawMesh(this.mNativeCanvasWrapper, mesh.getNativeWrapperInstance(),
+ blendMode.getXfermode().porterDuffMode, paint.getNativeInstance());
+ }
+
+ /**
+ * @hide
+ */
public void punchHole(float left, float top, float right, float bottom, float rx, float ry,
float alpha) {
nPunchHole(mNativeCanvasWrapper, left, top, right, bottom, rx, ry, alpha);
@@ -801,6 +812,9 @@
int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset,
short[] indices, int indexOffset, int indexCount, long nativePaint);
+ private static native void nDrawMesh(
+ long nativeCanvas, long nativeMesh, int mode, long nativePaint);
+
private static native void nDrawGlyphs(long nativeCanvas, int[] glyphIds, float[] positions,
int glyphIdStart, int positionStart, int glyphCount, long nativeFont, long nativePaint);
diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java
index 1ba79b8..eeff694 100644
--- a/graphics/java/android/graphics/BaseRecordingCanvas.java
+++ b/graphics/java/android/graphics/BaseRecordingCanvas.java
@@ -606,6 +606,12 @@
indices, indexOffset, indexCount, paint.getNativeInstance());
}
+ @Override
+ public final void drawMesh(Mesh mesh, BlendMode blendMode, Paint paint) {
+ nDrawMesh(mNativeCanvasWrapper, mesh.getNativeWrapperInstance(),
+ blendMode.getXfermode().porterDuffMode, paint.getNativeInstance());
+ }
+
/**
* @hide
*/
@@ -708,6 +714,10 @@
long nativePaint);
@FastNative
+ private static native void nDrawMesh(
+ long canvasHandle, long nativeMesh, int mode, long nativePaint);
+
+ @FastNative
private static native void nDrawVertices(long nativeCanvas, int mode, int n, float[] verts,
int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset,
short[] indices, int indexOffset, int indexCount, long nativePaint);
diff --git a/graphics/java/android/graphics/Mesh.java b/graphics/java/android/graphics/Mesh.java
index f0a0cf4..f32e0ee 100644
--- a/graphics/java/android/graphics/Mesh.java
+++ b/graphics/java/android/graphics/Mesh.java
@@ -196,7 +196,6 @@
}
nativeUpdateUniforms(
mNativeMeshWrapper, uniformName, value1, value2, value3, value4, count);
- nativeUpdateMesh(mNativeMeshWrapper);
}
private void setUniform(String uniformName, float[] values, boolean isColor) {
@@ -208,7 +207,6 @@
}
nativeUpdateUniforms(mNativeMeshWrapper, uniformName, values, isColor);
- nativeUpdateMesh(mNativeMeshWrapper);
}
/**
@@ -271,7 +269,14 @@
throw new NullPointerException("The uniform values parameter must not be null");
}
nativeUpdateUniforms(mNativeMeshWrapper, uniformName, values);
- nativeUpdateMesh(mNativeMeshWrapper);
+ }
+
+ /**
+ * @hide so only calls from module can utilize it
+ */
+ long getNativeWrapperInstance() {
+ nativeUpdateMesh(mNativeMeshWrapper, mIsIndexed);
+ return mNativeMeshWrapper;
}
private void setIntUniform(
@@ -282,7 +287,6 @@
nativeUpdateUniforms(
mNativeMeshWrapper, uniformName, value1, value2, value3, value4, count);
- nativeUpdateMesh(mNativeMeshWrapper);
}
private Mesh(long nativeMeshWrapper, boolean isIndexed) {
@@ -313,5 +317,5 @@
private static native void nativeUpdateUniforms(long builder, String uniformName, int[] values);
- private static native void nativeUpdateMesh(long nativeMeshWrapper);
+ private static native void nativeUpdateMesh(long nativeMeshWrapper, boolean mIsIndexed);
}
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 4df2d7d..6f9a4ff8 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -965,10 +965,16 @@
@VisibleForTesting
@GuardedBy("mLock")
void onActivityDestroyed(@NonNull Activity activity) {
+ if (!activity.isFinishing()) {
+ // onDestroyed is triggered without finishing. This happens when the activity is
+ // relaunched. In this case, we don't want to cleanup the record.
+ return;
+ }
// Remove any pending appeared activity, as the server won't send finished activity to the
// organizer.
+ final IBinder activityToken = activity.getActivityToken();
for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
- mTaskContainers.valueAt(i).onActivityDestroyed(activity);
+ mTaskContainers.valueAt(i).onActivityDestroyed(activityToken);
}
// We didn't trigger the callback if there were any pending appeared activities, so check
// again after the pending is removed.
@@ -1170,16 +1176,33 @@
* Returns a container that this activity is registered with. An activity can only belong to one
* container, or no container at all.
*/
+ @GuardedBy("mLock")
@Nullable
TaskFragmentContainer getContainerWithActivity(@NonNull Activity activity) {
- final IBinder activityToken = activity.getActivityToken();
+ return getContainerWithActivity(activity.getActivityToken());
+ }
+
+ @GuardedBy("mLock")
+ @Nullable
+ TaskFragmentContainer getContainerWithActivity(@NonNull IBinder activityToken) {
+ // Check pending appeared activity first because there can be a delay for the server
+ // update.
for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i).mContainers;
- // Traverse from top to bottom in case an activity is added to top pending, and hasn't
- // received update from server yet.
for (int j = containers.size() - 1; j >= 0; j--) {
final TaskFragmentContainer container = containers.get(j);
- if (container.hasActivity(activityToken)) {
+ if (container.hasPendingAppearedActivity(activityToken)) {
+ return container;
+ }
+ }
+ }
+
+ // Check appeared activity if there is no such pending appeared activity.
+ for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
+ final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i).mContainers;
+ for (int j = containers.size() - 1; j >= 0; j--) {
+ final TaskFragmentContainer container = containers.get(j);
+ if (container.hasAppearedActivity(activityToken)) {
return container;
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index dba5a7a..03f4dc9 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -166,16 +166,16 @@
}
/** Called when the activity is destroyed. */
- void onActivityDestroyed(@NonNull Activity activity) {
+ void onActivityDestroyed(@NonNull IBinder activityToken) {
for (TaskFragmentContainer container : mContainers) {
- container.onActivityDestroyed(activity);
+ container.onActivityDestroyed(activityToken);
}
}
/** Removes the pending appeared activity from all TaskFragments in this Task. */
- void cleanupPendingAppearedActivity(@NonNull Activity pendingAppearedActivity) {
+ void cleanupPendingAppearedActivity(@NonNull IBinder activityToken) {
for (TaskFragmentContainer container : mContainers) {
- container.removePendingAppearedActivity(pendingAppearedActivity);
+ container.removePendingAppearedActivity(activityToken);
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java
index af5d8c5..33220c4 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java
@@ -18,7 +18,9 @@
import static android.graphics.Matrix.MTRANS_X;
import static android.graphics.Matrix.MTRANS_Y;
+import static android.view.RemoteAnimationTarget.MODE_CLOSING;
+import android.graphics.Point;
import android.graphics.Rect;
import android.view.Choreographer;
import android.view.RemoteAnimationTarget;
@@ -49,6 +51,16 @@
/** Area in absolute coordinate that the animation surface shouldn't go beyond. */
@NonNull
private final Rect mWholeAnimationBounds = new Rect();
+ /**
+ * Area in absolute coordinate that should represent all the content to show for this window.
+ * This should be the end bounds for opening window, and start bounds for closing window in case
+ * the window is resizing during the open/close transition.
+ */
+ @NonNull
+ private final Rect mContentBounds = new Rect();
+ /** Offset relative to the window parent surface for {@link #mContentBounds}. */
+ @NonNull
+ private final Point mContentRelOffset = new Point();
@NonNull
final Transformation mTransformation = new Transformation();
@@ -78,6 +90,21 @@
mTarget = target;
mLeash = leash;
mWholeAnimationBounds.set(wholeAnimationBounds);
+ if (target.mode == MODE_CLOSING) {
+ // When it is closing, we want to show the content at the start position in case the
+ // window is resizing as well. For example, when the activities is changing from split
+ // to stack, the bottom TaskFragment will be resized to fullscreen when hiding.
+ final Rect startBounds = target.startBounds;
+ final Rect endBounds = target.screenSpaceBounds;
+ mContentBounds.set(startBounds);
+ mContentRelOffset.set(target.localBounds.left, target.localBounds.top);
+ mContentRelOffset.offset(
+ startBounds.left - endBounds.left,
+ startBounds.top - endBounds.top);
+ } else {
+ mContentBounds.set(target.screenSpaceBounds);
+ mContentRelOffset.set(target.localBounds.left, target.localBounds.top);
+ }
}
/**
@@ -108,8 +135,7 @@
/** To be overridden by subclasses to adjust the animation surface change. */
void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) {
// Update the surface position and alpha.
- mTransformation.getMatrix().postTranslate(
- mTarget.localBounds.left, mTarget.localBounds.top);
+ mTransformation.getMatrix().postTranslate(mContentRelOffset.x, mContentRelOffset.y);
t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix);
t.setAlpha(mLeash, mTransformation.getAlpha());
@@ -117,9 +143,8 @@
// positionX/Y are in local coordinate, so minus the local offset to get the slide amount.
final int positionX = Math.round(mMatrix[MTRANS_X]);
final int positionY = Math.round(mMatrix[MTRANS_Y]);
- final Rect cropRect = new Rect(mTarget.screenSpaceBounds);
- final Rect localBounds = mTarget.localBounds;
- cropRect.offset(positionX - localBounds.left, positionY - localBounds.top);
+ final Rect cropRect = new Rect(mContentBounds);
+ cropRect.offset(positionX - mContentRelOffset.x, positionY - mContentRelOffset.y);
// Store the current offset of the surface top left from (0,0) in absolute coordinate.
final int offsetX = cropRect.left;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
index 0e13c59..322f854 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
@@ -17,6 +17,7 @@
package androidx.window.extensions.embedding;
import static android.os.Process.THREAD_PRIORITY_DISPLAY;
+import static android.view.RemoteAnimationTarget.MODE_CHANGING;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
@@ -254,7 +255,7 @@
@NonNull RemoteAnimationTarget[] targets) {
final List<TaskFragmentAnimationAdapter> adapters = new ArrayList<>();
for (RemoteAnimationTarget target : targets) {
- if (target.startBounds != null) {
+ if (target.mode == MODE_CHANGING) {
// This is the target with bounds change.
final Animation[] animations =
mAnimationSpec.createChangeBoundsChangeAnimations(target);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
index 13afa49..1f866c3 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
@@ -114,8 +114,8 @@
@NonNull
Animation createChangeBoundsCloseAnimation(@NonNull RemoteAnimationTarget target) {
final Rect parentBounds = target.taskInfo.configuration.windowConfiguration.getBounds();
- // TODO(b/258126915): we want to keep track of the closing start bounds
- final Rect bounds = target.screenSpaceBounds;
+ // Use startBounds if the window is closing in case it may also resize.
+ final Rect bounds = target.startBounds;
final int endTop;
final int endLeft;
if (parentBounds.top == bounds.top && parentBounds.bottom == bounds.bottom) {
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 71b8840..e31792a 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -43,6 +43,9 @@
* Client-side container for a stack of activities. Corresponds to an instance of TaskFragment
* on the server side.
*/
+// Suppress GuardedBy warning because all the TaskFragmentContainers are stored in
+// SplitController.mTaskContainers which is guarded.
+@SuppressWarnings("GuardedBy")
class TaskFragmentContainer {
private static final int APPEAR_EMPTY_TIMEOUT_MS = 3000;
@@ -66,11 +69,11 @@
TaskFragmentInfo mInfo;
/**
- * Activities that are being reparented or being started to this container, but haven't been
- * added to {@link #mInfo} yet.
+ * Activity tokens that are being reparented or being started to this container, but haven't
+ * been added to {@link #mInfo} yet.
*/
@VisibleForTesting
- final ArrayList<Activity> mPendingAppearedActivities = new ArrayList<>();
+ final ArrayList<IBinder> mPendingAppearedActivities = new ArrayList<>();
/**
* When this container is created for an {@link Intent} to start within, we store that Intent
@@ -84,8 +87,11 @@
private final List<TaskFragmentContainer> mContainersToFinishOnExit =
new ArrayList<>();
- /** Individual associated activities in different containers that should be finished on exit. */
- private final List<Activity> mActivitiesToFinishOnExit = new ArrayList<>();
+ /**
+ * Individual associated activity tokens in different containers that should be finished on
+ * exit.
+ */
+ private final List<IBinder> mActivitiesToFinishOnExit = new ArrayList<>();
/** Indicates whether the container was cleaned up after the last activity was removed. */
private boolean mIsFinished;
@@ -158,8 +164,9 @@
// in this intermediate state.
// Place those on top of the list since they will be on the top after reported from the
// server.
- for (Activity activity : mPendingAppearedActivities) {
- if (!activity.isFinishing()) {
+ for (IBinder token : mPendingAppearedActivities) {
+ final Activity activity = mController.getActivity(token);
+ if (activity != null && !activity.isFinishing()) {
allActivities.add(activity);
}
}
@@ -203,55 +210,58 @@
/** Adds the activity that will be reparented to this container. */
void addPendingAppearedActivity(@NonNull Activity pendingAppearedActivity) {
- if (hasActivity(pendingAppearedActivity.getActivityToken())) {
+ final IBinder activityToken = pendingAppearedActivity.getActivityToken();
+ if (hasActivity(activityToken)) {
return;
}
- // Remove the pending activity from other TaskFragments.
- mTaskContainer.cleanupPendingAppearedActivity(pendingAppearedActivity);
- mPendingAppearedActivities.add(pendingAppearedActivity);
- updateActivityClientRecordTaskFragmentToken(pendingAppearedActivity);
+ // Remove the pending activity from other TaskFragments in case the activity is reparented
+ // again before the server update.
+ mTaskContainer.cleanupPendingAppearedActivity(activityToken);
+ mPendingAppearedActivities.add(activityToken);
+ updateActivityClientRecordTaskFragmentToken(activityToken);
}
/**
* Updates the {@link ActivityThread.ActivityClientRecord#mTaskFragmentToken} for the
* activity. This makes sure the token is up-to-date if the activity is relaunched later.
*/
- private void updateActivityClientRecordTaskFragmentToken(@NonNull Activity activity) {
+ private void updateActivityClientRecordTaskFragmentToken(@NonNull IBinder activityToken) {
final ActivityThread.ActivityClientRecord record = ActivityThread
- .currentActivityThread().getActivityClient(activity.getActivityToken());
+ .currentActivityThread().getActivityClient(activityToken);
if (record != null) {
record.mTaskFragmentToken = mToken;
}
}
- void removePendingAppearedActivity(@NonNull Activity pendingAppearedActivity) {
- mPendingAppearedActivities.remove(pendingAppearedActivity);
+ void removePendingAppearedActivity(@NonNull IBinder activityToken) {
+ mPendingAppearedActivities.remove(activityToken);
}
void clearPendingAppearedActivities() {
- final List<Activity> cleanupActivities = new ArrayList<>(mPendingAppearedActivities);
+ final List<IBinder> cleanupActivities = new ArrayList<>(mPendingAppearedActivities);
// Clear mPendingAppearedActivities so that #getContainerWithActivity won't return the
// current TaskFragment.
mPendingAppearedActivities.clear();
mPendingAppearedIntent = null;
// For removed pending activities, we need to update the them to their previous containers.
- for (Activity activity : cleanupActivities) {
+ for (IBinder activityToken : cleanupActivities) {
final TaskFragmentContainer curContainer = mController.getContainerWithActivity(
- activity);
+ activityToken);
if (curContainer != null) {
- curContainer.updateActivityClientRecordTaskFragmentToken(activity);
+ curContainer.updateActivityClientRecordTaskFragmentToken(activityToken);
}
}
}
/** Called when the activity is destroyed. */
- void onActivityDestroyed(@NonNull Activity activity) {
- removePendingAppearedActivity(activity);
+ void onActivityDestroyed(@NonNull IBinder activityToken) {
+ removePendingAppearedActivity(activityToken);
if (mInfo != null) {
// Remove the activity now because there can be a delay before the server callback.
- mInfo.getActivities().remove(activity.getActivityToken());
+ mInfo.getActivities().remove(activityToken);
}
+ mActivitiesToFinishOnExit.remove(activityToken);
}
@Nullable
@@ -275,16 +285,24 @@
mPendingAppearedIntent = null;
}
- boolean hasActivity(@NonNull IBinder token) {
- if (mInfo != null && mInfo.getActivities().contains(token)) {
- return true;
- }
- for (Activity activity : mPendingAppearedActivities) {
- if (activity.getActivityToken().equals(token)) {
- return true;
- }
- }
- return false;
+ boolean hasActivity(@NonNull IBinder activityToken) {
+ // Instead of using (hasAppearedActivity() || hasPendingAppearedActivity), we want to make
+ // sure the controller considers this container as the one containing the activity.
+ // This is needed when the activity is added as pending appeared activity to one
+ // TaskFragment while it is also an appeared activity in another.
+ return mController.getContainerWithActivity(activityToken) == this;
+ }
+
+ /** Whether this activity has appeared in the TaskFragment on the server side. */
+ boolean hasAppearedActivity(@NonNull IBinder activityToken) {
+ return mInfo != null && mInfo.getActivities().contains(activityToken);
+ }
+
+ /**
+ * Whether we are waiting for this activity to appear in the TaskFragment on the server side.
+ */
+ boolean hasPendingAppearedActivity(@NonNull IBinder activityToken) {
+ return mPendingAppearedActivities.contains(activityToken);
}
int getRunningActivityCount() {
@@ -342,8 +360,8 @@
// Cleanup activities that were being re-parented
List<IBinder> infoActivities = mInfo.getActivities();
for (int i = mPendingAppearedActivities.size() - 1; i >= 0; --i) {
- final Activity activity = mPendingAppearedActivities.get(i);
- if (infoActivities.contains(activity.getActivityToken())) {
+ final IBinder activityToken = mPendingAppearedActivities.get(i);
+ if (infoActivities.contains(activityToken)) {
mPendingAppearedActivities.remove(i);
}
}
@@ -392,7 +410,7 @@
if (mIsFinished) {
return;
}
- mActivitiesToFinishOnExit.add(activityToFinish);
+ mActivitiesToFinishOnExit.add(activityToFinish.getActivityToken());
}
/**
@@ -402,7 +420,7 @@
if (mIsFinished) {
return;
}
- mActivitiesToFinishOnExit.remove(activityToRemove);
+ mActivitiesToFinishOnExit.remove(activityToRemove.getActivityToken());
}
/** Removes all dependencies that should be finished when this container is finished. */
@@ -470,8 +488,9 @@
mContainersToFinishOnExit.clear();
// Finish associated activities
- for (Activity activity : mActivitiesToFinishOnExit) {
- if (activity.isFinishing()
+ for (IBinder activityToken : mActivitiesToFinishOnExit) {
+ final Activity activity = mController.getActivity(activityToken);
+ if (activity == null || activity.isFinishing()
|| controller.shouldRetainAssociatedActivity(this, activity)) {
continue;
}
@@ -540,7 +559,8 @@
}
int maxMinWidth = mInfo.getMinimumWidth();
int maxMinHeight = mInfo.getMinimumHeight();
- for (Activity activity : mPendingAppearedActivities) {
+ for (IBinder activityToken : mPendingAppearedActivities) {
+ final Activity activity = mController.getActivity(activityToken);
final Size minDimensions = SplitPresenter.getMinDimensions(activity);
if (minDimensions == null) {
continue;
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 92011af..bc03e4e 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
@@ -21,6 +21,7 @@
import static androidx.window.extensions.embedding.SplitRule.FINISH_ALWAYS;
import static androidx.window.extensions.embedding.SplitRule.FINISH_NEVER;
+import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -45,6 +46,8 @@
import java.util.Collections;
import java.util.List;
+// Suppress GuardedBy warning on unit tests
+@SuppressWarnings("GuardedBy")
public class EmbeddingTestUtils {
static final Rect TASK_BOUNDS = new Rect(0, 0, 600, 1200);
static final int TASK_ID = 10;
@@ -191,6 +194,15 @@
return new TaskContainer(TASK_ID, activity);
}
+ static TaskContainer createTestTaskContainer(@NonNull SplitController controller) {
+ final TaskContainer taskContainer = createTestTaskContainer();
+ final int taskId = taskContainer.getTaskId();
+ // Should not call to create TaskContainer with the same task id twice.
+ assertFalse(controller.mTaskContainers.contains(taskId));
+ controller.mTaskContainers.put(taskId, taskContainer);
+ return taskContainer;
+ }
+
static WindowLayoutInfo createWindowLayoutInfo() {
final FoldingFeature foldingFeature = new FoldingFeature(
new Rect(
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 8c1b87a..221c764 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
@@ -242,6 +242,14 @@
assertTrue(tf.hasActivity(mActivity.getActivityToken()));
+ // When the activity is not finishing, do not clear the record.
+ doReturn(false).when(mActivity).isFinishing();
+ mSplitController.onActivityDestroyed(mActivity);
+
+ assertTrue(tf.hasActivity(mActivity.getActivityToken()));
+
+ // Clear the record when the activity is finishing and destroyed.
+ doReturn(true).when(mActivity).isFinishing();
mSplitController.onActivityDestroyed(mActivity);
assertFalse(tf.hasActivity(mActivity.getActivityToken()));
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
index d43c471..99f56b4 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
@@ -161,7 +161,8 @@
final TaskFragmentContainer pendingActivityContainer = new TaskFragmentContainer(mActivity,
null /* pendingAppearedIntent */, taskContainer, mController);
- assertTrue(pendingActivityContainer.mPendingAppearedActivities.contains(mActivity));
+ assertTrue(pendingActivityContainer.mPendingAppearedActivities.contains(
+ mActivity.getActivityToken()));
final TaskFragmentInfo info0 = createMockTaskFragmentInfo(pendingActivityContainer,
mActivity);
@@ -317,7 +318,7 @@
@Test
public void testOnActivityDestroyed() {
- final TaskContainer taskContainer = createTestTaskContainer();
+ final TaskContainer taskContainer = createTestTaskContainer(mController);
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
mIntent, taskContainer, mController);
container.addPendingAppearedActivity(mActivity);
@@ -328,7 +329,7 @@
assertTrue(container.hasActivity(mActivity.getActivityToken()));
- taskContainer.onActivityDestroyed(mActivity);
+ taskContainer.onActivityDestroyed(mActivity.getActivityToken());
// It should not contain the destroyed Activity.
assertFalse(container.hasActivity(mActivity.getActivityToken()));
@@ -398,6 +399,79 @@
assertFalse(taskContainer.isInIntermediateState());
}
+ @Test
+ public void testHasAppearedActivity() {
+ final TaskContainer taskContainer = createTestTaskContainer();
+ final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
+ mIntent, taskContainer, mController);
+ container.addPendingAppearedActivity(mActivity);
+
+ assertFalse(container.hasAppearedActivity(mActivity.getActivityToken()));
+
+ final List<IBinder> activities = new ArrayList<>();
+ activities.add(mActivity.getActivityToken());
+ doReturn(activities).when(mInfo).getActivities();
+ container.setInfo(mTransaction, mInfo);
+
+ assertTrue(container.hasAppearedActivity(mActivity.getActivityToken()));
+ }
+
+ @Test
+ public void testHasPendingAppearedActivity() {
+ final TaskContainer taskContainer = createTestTaskContainer();
+ final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
+ mIntent, taskContainer, mController);
+ container.addPendingAppearedActivity(mActivity);
+
+ assertTrue(container.hasPendingAppearedActivity(mActivity.getActivityToken()));
+
+ final List<IBinder> activities = new ArrayList<>();
+ activities.add(mActivity.getActivityToken());
+ doReturn(activities).when(mInfo).getActivities();
+ container.setInfo(mTransaction, mInfo);
+
+ assertFalse(container.hasPendingAppearedActivity(mActivity.getActivityToken()));
+ }
+
+ @Test
+ public void testHasActivity() {
+ final TaskContainer taskContainer = createTestTaskContainer(mController);
+ final TaskFragmentContainer container1 = new TaskFragmentContainer(null /* activity */,
+ mIntent, taskContainer, mController);
+ final TaskFragmentContainer container2 = new TaskFragmentContainer(null /* activity */,
+ mIntent, taskContainer, mController);
+
+ // Activity is pending appeared on container2.
+ container2.addPendingAppearedActivity(mActivity);
+
+ assertFalse(container1.hasActivity(mActivity.getActivityToken()));
+ assertTrue(container2.hasActivity(mActivity.getActivityToken()));
+
+ // Activity is pending appeared on container1 (removed from container2).
+ container1.addPendingAppearedActivity(mActivity);
+
+ assertTrue(container1.hasActivity(mActivity.getActivityToken()));
+ assertFalse(container2.hasActivity(mActivity.getActivityToken()));
+
+ final List<IBinder> activities = new ArrayList<>();
+ activities.add(mActivity.getActivityToken());
+ doReturn(activities).when(mInfo).getActivities();
+
+ // Although Activity is appeared on container2, we prioritize pending appeared record on
+ // container1.
+ container2.setInfo(mTransaction, mInfo);
+
+ assertTrue(container1.hasActivity(mActivity.getActivityToken()));
+ assertFalse(container2.hasActivity(mActivity.getActivityToken()));
+
+ // When the pending appeared record is removed from container1, we respect the appeared
+ // record in container2.
+ container1.removePendingAppearedActivity(mActivity.getActivityToken());
+
+ assertFalse(container1.hasActivity(mActivity.getActivityToken()));
+ assertTrue(container2.hasActivity(mActivity.getActivityToken()));
+ }
+
/** Creates a mock activity in the organizer process. */
private Activity createMockActivity() {
final Activity activity = mock(Activity.class);
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index 27c245c..904ae86 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Laat los"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Program sal dalk nie met verdeelde skerm werk nie."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Program steun nie verdeelde skerm nie."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Hierdie app kan net in 1 venster oopgemaak word."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Program sal dalk nie op \'n sekondêre skerm werk nie."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Program steun nie begin op sekondêre skerms nie."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Skermverdeler"</string>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index aafcfe7..788fd5c 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"দেখুৱাওক"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"এপ্টোৱে বিভাজিত স্ক্ৰীনৰ সৈতে কাম নকৰিব পাৰে।"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"এপ্টোৱে বিভাজিত স্ক্ৰীন সমৰ্থন নকৰে।"</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"এই এপ্টো কেৱল ১ খন ৱিণ্ড’ত খুলিব পাৰি।"</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"গৌণ ডিছপ্লেত এপে সঠিকভাৱে কাম নকৰিব পাৰে।"</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"গৌণ ডিছপ্লেত এপ্ লঞ্চ কৰিব নোৱাৰি।"</string>
<string name="accessibility_divider" msgid="703810061635792791">"স্প্লিট স্ক্ৰীনৰ বিভাজক"</string>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index d4b5bad..a56918d 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Güvənli məkandan çıxarın"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Tətbiq bölünmüş ekran ilə işləməyə bilər."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Tətbiq ekran bölünməsini dəstəkləmir."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Bu tətbiq yalnız 1 pəncərədə açıla bilər."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Tətbiq ikinci ekranda işləməyə bilər."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Tətbiq ikinci ekranda başlamağı dəstəkləmir."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Bölünmüş ekran ayırıcısı"</string>
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
index c2ee13b..dcb03aa 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Uklonite iz tajne memorije"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Aplikacija možda neće raditi sa podeljenim ekranom."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Aplikacija ne podržava podeljeni ekran."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Ova aplikacija može da se otvori samo u jednom prozoru."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikacija možda neće funkcionisati na sekundarnom ekranu."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikacija ne podržava pokretanje na sekundarnim ekranima."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Razdelnik podeljenog ekrana"</string>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index ea205ef..f6b285a 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Паказаць"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Праграма можа не працаваць у рэжыме падзеленага экрана."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Праграма не падтрымлівае функцыю дзялення экрана."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Гэту праграму можна адкрыць толькі ў адным акне."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Праграма можа не працаваць на дадатковых экранах."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Праграма не падтрымлівае запуск на дадатковых экранах."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Раздзяляльнік падзеленага экрана"</string>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index f91dda0..044f2a7 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Отмяна на съхраняването"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Приложението може да не работи в режим на разделен екран."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Приложението не поддържа разделен екран."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Това приложение може да се отвори само в 1 прозорец."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Възможно е приложението да не работи на алтернативни дисплеи."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Приложението не поддържа използването на алтернативни дисплеи."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Разделител в режима за разделен екран"</string>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index 0cc798c..1fb0292 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"আনস্ট্যাস করুন"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"অ্যাপটি স্প্লিট স্ক্রিনে কাজ নাও করতে পারে।"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"অ্যাপ্লিকেশান বিভক্ত-স্ক্রিন সমর্থন করে না৷"</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"এই অ্যাপটি শুধু ১টি উইন্ডোয় খোলা যেতে পারে।"</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"সেকেন্ডারি ডিসপ্লেতে অ্যাপটি কাজ নাও করতে পারে।"</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"সেকেন্ডারি ডিসপ্লেতে অ্যাপ লঞ্চ করা যাবে না।"</string>
<string name="accessibility_divider" msgid="703810061635792791">"বিভক্ত-স্ক্রিন বিভাজক"</string>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index e235179..8e52d78 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Vađenje iz stasha"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Aplikacija možda neće raditi na podijeljenom ekranu."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Aplikacija ne podržava dijeljenje ekrana."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Ova aplikacija se može otvoriti samo u 1 prozoru."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikacija možda neće raditi na sekundarnom ekranu."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikacija ne podržava pokretanje na sekundarnim ekranima."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Razdjelnik podijeljenog ekrana"</string>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index 30b8d09..6bc4f99 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Deixa d\'amagar"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"És possible que l\'aplicació no funcioni amb la pantalla dividida."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"L\'aplicació no admet la pantalla dividida."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Aquesta aplicació només pot obrir-se en 1 finestra."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"És possible que l\'aplicació no funcioni en una pantalla secundària."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"L\'aplicació no es pot obrir en pantalles secundàries."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Divisor de pantalles"</string>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index b78e93a..b638b0e 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Zrušit uložení"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Aplikace v režimu rozdělené obrazovky nemusí fungovat."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Aplikace nepodporuje režim rozdělené obrazovky."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Tuto aplikaci lze otevřít jen na jednom okně."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikace na sekundárním displeji nemusí fungovat."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikace nepodporuje spuštění na sekundárních displejích."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Čára rozdělující obrazovku"</string>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index 1544099..e0b7a8c 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Vis"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Appen fungerer muligvis ikke i opdelt skærm."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Appen understøtter ikke opdelt skærm."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Denne app kan kun åbnes i 1 vindue."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Appen fungerer muligvis ikke på sekundære skærme."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Appen kan ikke åbnes på sekundære skærme."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Adskiller til opdelt skærm"</string>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index 9a4b20e..caca8b4 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Aus Stash entfernen"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Die App funktioniert unter Umständen im Modus für geteilten Bildschirm nicht."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Das Teilen des Bildschirms wird in dieser App nicht unterstützt."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Diese App kann nur in einem einzigen Fenster geöffnet werden."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Die App funktioniert auf einem sekundären Display möglicherweise nicht."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Die App unterstützt den Start auf sekundären Displays nicht."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Bildschirmteiler"</string>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index 8aca81e..ffb4fb0 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Κατάργηση απόκρυψης"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Η εφαρμογή ενδέχεται να μην λειτουργεί με διαχωρισμό οθόνης."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Η εφαρμογή δεν υποστηρίζει διαχωρισμό οθόνης."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Αυτή η εφαρμογή μπορεί να ανοιχθεί μόνο σε 1 παράθυρο."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Η εφαρμογή ίσως να μην λειτουργήσει σε δευτερεύουσα οθόνη."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Η εφαρμογή δεν υποστηρίζει την εκκίνηση σε δευτερεύουσες οθόνες."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Διαχωριστικό οθόνης"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
index ec44597..c71011d 100644
--- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Unstash"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"App may not work with split-screen."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"App does not support split-screen."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"This app can only be opened in one window."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"App may not work on a secondary display."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"App does not support launch on secondary displays."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Split screen divider"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
index 91875c5..05091fb 100644
--- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Unstash"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"App may not work with split-screen."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"App does not support split-screen."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"This app can only be opened in 1 window."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"App may not work on a secondary display."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"App does not support launch on secondary displays."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Split-screen divider"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
index ec44597..c71011d 100644
--- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Unstash"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"App may not work with split-screen."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"App does not support split-screen."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"This app can only be opened in one window."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"App may not work on a secondary display."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"App does not support launch on secondary displays."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Split screen divider"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
index ec44597..c71011d 100644
--- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Unstash"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"App may not work with split-screen."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"App does not support split-screen."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"This app can only be opened in one window."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"App may not work on a secondary display."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"App does not support launch on secondary displays."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Split screen divider"</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
index ace1387..2993fe7 100644
--- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Unstash"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"App may not work with split-screen."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"App does not support split-screen."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"This app can only be opened in 1 window."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"App may not work on a secondary display."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"App does not support launch on secondary displays."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Split-screen divider"</string>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
index 704e696..0eaca8b 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Dejar de almacenar de manera segura"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Es posible que la app no funcione en el modo de pantalla dividida."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"La app no es compatible con la función de pantalla dividida."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Esta app solo puede estar abierta en 1 ventana."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Es posible que la app no funcione en una pantalla secundaria."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"La app no puede iniciarse en pantallas secundarias."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Divisor de pantalla dividida"</string>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index 2ad8b53..9c8fed1 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"No esconder"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Es posible que la aplicación no funcione con la pantalla dividida."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"La aplicación no admite la pantalla dividida."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Esta aplicación solo puede abrirse en una ventana."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Es posible que la aplicación no funcione en una pantalla secundaria."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"La aplicación no se puede abrir en pantallas secundarias."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Dividir la pantalla"</string>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index 359a06d..e8cbe53 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Eemalda hoidlast"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Rakendus ei pruugi poolitatud ekraaniga töötada."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Rakendus ei toeta jagatud ekraani."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Selle rakenduse saab avada ainult ühes aknas."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Rakendus ei pruugi teisesel ekraanil töötada."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Rakendus ei toeta teisestel ekraanidel käivitamist."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Ekraanijagaja"</string>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index 58f221e..7375faf 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"لغو مخفیسازی"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"ممکن است برنامه با «صفحهٔ دونیمه» کار نکند."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"برنامه از تقسیم صفحه پشتیبانی نمیکند."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"این برنامه فقط در ۱ پنجره میتواند باز شود."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ممکن است برنامه در نمایشگر ثانویه کار نکند."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"برنامه از راهاندازی در نمایشگرهای ثانویه پشتیبانی نمیکند."</string>
<string name="accessibility_divider" msgid="703810061635792791">"تقسیمکننده صفحه"</string>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index 191a21e1..7729d1c 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Poista turvasäilytyksestä"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Sovellus ei ehkä toimi jaetulla näytöllä."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Sovellus ei tue jaetun näytön tilaa."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Tämän sovelluksen voi avata vain yhdessä ikkunassa."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Sovellus ei ehkä toimi toissijaisella näytöllä."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Sovellus ei tue käynnistämistä toissijaisilla näytöillä."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Näytön jakaja"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index 587c295..6348800 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Retirer de la réserve"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Il est possible que l\'application ne fonctionne pas en mode Écran partagé."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"L\'application n\'est pas compatible avec l\'écran partagé."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Cette application ne peut être ouverte que dans une fenêtre."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Il est possible que l\'application ne fonctionne pas sur un écran secondaire."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"L\'application ne peut pas être lancée sur des écrans secondaires."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Séparateur d\'écran partagé"</string>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index 0ede879..1842213 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Unstash"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Il est possible que l\'application ne fonctionne pas en mode Écran partagé."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Application incompatible avec l\'écran partagé."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Cette appli ne peut être ouverte que dans 1 fenêtre."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Il est possible que l\'application ne fonctionne pas sur un écran secondaire."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"L\'application ne peut pas être lancée sur des écrans secondaires."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Séparateur d\'écran partagé"</string>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index 1c69214..2e05d4c 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Non esconder"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Pode que a aplicación non funcione coa pantalla dividida."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"A aplicación non é compatible coa función de pantalla dividida."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Esta aplicación só se pode abrir en 1 ventá."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"É posible que a aplicación non funcione nunha pantalla secundaria."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"A aplicación non se pode iniciar en pantallas secundarias."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Divisor de pantalla dividida"</string>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml
index bf54411..23a5970 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Poništite sakrivanje"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Aplikacija možda neće funkcionirati s podijeljenim zaslonom."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Aplikacija ne podržava podijeljeni zaslon."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Ova se aplikacija može otvoriti samo u jednom prozoru."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikacija možda neće funkcionirati na sekundarnom zaslonu."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikacija ne podržava pokretanje na sekundarnim zaslonima."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Razdjelnik podijeljenog zaslona"</string>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index 01f533f..1bbbdb7 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Félretevés megszüntetése"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Lehet, hogy az alkalmazás nem működik osztott képernyős nézetben."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Az alkalmazás nem támogatja az osztott képernyős nézetet."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Ez az alkalmazás csak egy ablakban nyitható meg."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Előfordulhat, hogy az alkalmazás nem működik másodlagos kijelzőn."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Az alkalmazást nem lehet másodlagos kijelzőn elindítani."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Elválasztó az osztott nézetben"</string>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index f8ead65..6eef4af 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Ցուցադրել"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Հավելվածը չի կարող աշխատել տրոհված էկրանի ռեժիմում։"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Հավելվածը չի աջակցում էկրանի տրոհումը:"</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Այս հավելվածը հնարավոր է բացել միայն մեկ պատուհանում։"</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Հավելվածը կարող է չաշխատել լրացուցիչ էկրանի վրա"</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Հավելվածը չի աջակցում գործարկումը լրացուցիչ էկրանների վրա"</string>
<string name="accessibility_divider" msgid="703810061635792791">"Տրոհված էկրանի բաժանիչ"</string>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index dce6b38..61a9558 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Batalkan stash"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Aplikasi mungkin tidak berfungsi dengan layar terpisah."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"App tidak mendukung layar terpisah."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Aplikasi ini hanya dapat dibuka di 1 jendela."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikasi mungkin tidak berfungsi pada layar sekunder."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikasi tidak mendukung peluncuran pada layar sekunder."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Pembagi layar terpisah"</string>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index f4c2221..0b873bc 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Taka úr geymslu"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Hugsanlega virkar forritið ekki með skjáskiptingu."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Forritið styður ekki að skjánum sé skipt."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Aðeins er hægt að opna þetta forrit í 1 glugga."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Hugsanlegt er að forritið virki ekki á öðrum skjá."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Forrit styður ekki opnun á öðrum skjá."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Skjáskipting"</string>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index af5a0fb..da4d0bb 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Annulla accantonamento"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"L\'app potrebbe non funzionare con lo schermo diviso."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"L\'app non supporta la modalità Schermo diviso."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Questa app può essere aperta soltanto in 1 finestra."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"L\'app potrebbe non funzionare su un display secondario."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"L\'app non supporta l\'avvio su display secondari."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Strumento per schermo diviso"</string>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index 7a07e6c..e9a53dd 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"ביטול ההסתרה הזמנית"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"ייתכן שהאפליקציה לא תפעל במסך מפוצל."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"האפליקציה אינה תומכת במסך מפוצל."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"ניתן לפתוח את האפליקציה הזו רק בחלון אחד."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ייתכן שהאפליקציה לא תפעל במסך משני."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"האפליקציה אינה תומכת בהפעלה במסכים משניים."</string>
<string name="accessibility_divider" msgid="703810061635792791">"מחלק מסך מפוצל"</string>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index f3da095..2930cc3 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"表示"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"アプリは分割画面では動作しないことがあります。"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"アプリで分割画面がサポートされていません。"</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"このアプリはウィンドウが 1 つの場合のみ開くことができます。"</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"アプリはセカンダリ ディスプレイでは動作しないことがあります。"</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"アプリはセカンダリ ディスプレイでの起動に対応していません。"</string>
<string name="accessibility_divider" msgid="703810061635792791">"分割画面の分割線"</string>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index 36d4be0..848be3f 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"გადანახვის გაუქმება"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"აპმა შეიძლება არ იმუშაოს გაყოფილი ეკრანის რეჟიმში."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"ეკრანის გაყოფა არ არის მხარდაჭერილი აპის მიერ."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"ამ აპის გახსნა შესაძლებელია მხოლოდ 1 ფანჯარაში."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"აპმა შეიძლება არ იმუშაოს მეორეულ ეკრანზე."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"აპს არ გააჩნია მეორეული ეკრანის მხარდაჭერა."</string>
<string name="accessibility_divider" msgid="703810061635792791">"გაყოფილი ეკრანის რეჟიმის გამყოფი"</string>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index e7bcc99..8d08ccab 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Көрсету"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Қолданба экранды бөлу режимінде жұмыс істемеуі мүмкін."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Қодланба бөлінген экранды қолдамайды."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Бұл қолданбаны тек 1 терезеден ашуға болады."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Қолданба қосымша дисплейде жұмыс істемеуі мүмкін."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Қолданба қосымша дисплейлерде іске қосуды қолдамайды."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Бөлінген экран бөлгіші"</string>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index 04142d7..7c4ea57e 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"ឈប់លាក់ជាបណ្ដោះអាសន្ន"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"កម្មវិធីអាចនឹងមិនដំណើរការជាមួយមុខងារបំបែកអេក្រង់ទេ។"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"កម្មវិធីមិនគាំទ្រអេក្រង់បំបែកជាពីរទេ"</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"កម្មវិធីនេះអាចបើកនៅក្នុងវិនដូតែ 1 ប៉ុណ្ណោះ។"</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"កម្មវិធីនេះប្រហែលជាមិនដំណើរការនៅលើអេក្រង់បន្ទាប់បន្សំទេ។"</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"កម្មវិធីនេះមិនអាចចាប់ផ្តើមនៅលើអេក្រង់បន្ទាប់បន្សំបានទេ។"</string>
<string name="accessibility_divider" msgid="703810061635792791">"កម្មវិធីចែកអេក្រង់បំបែក"</string>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index e2c86a9..7290617 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"ಅನ್ಸ್ಟ್ಯಾಶ್ ಮಾಡಿ"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"ವಿಭಜಿಸಿದ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ಆ್ಯಪ್ ಕೆಲಸ ಮಾಡದೇ ಇರಬಹುದು."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"ಈ ಆ್ಯಪ್ ಅನ್ನು 1 ವಿಂಡೋದಲ್ಲಿ ಮಾತ್ರ ತೆರೆಯಬಹುದು."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ಸೆಕೆಂಡರಿ ಡಿಸ್ಪ್ಲೇಗಳಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಕಾರ್ಯ ನಿರ್ವಹಿಸದೇ ಇರಬಹುದು."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ಸೆಕೆಂಡರಿ ಡಿಸ್ಪ್ಲೇಗಳಲ್ಲಿ ಪ್ರಾರಂಭಿಸುವಿಕೆಯನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string>
<string name="accessibility_divider" msgid="703810061635792791">"ಸ್ಪ್ಲಿಟ್-ಪರದೆ ಡಿವೈಡರ್"</string>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index baa245a..59b405f 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"숨기기 취소"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"앱이 분할 화면에서 작동하지 않을 수 있습니다."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"앱이 화면 분할을 지원하지 않습니다."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"이 앱은 창 1개에서만 열 수 있습니다."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"앱이 보조 디스플레이에서 작동하지 않을 수도 있습니다."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"앱이 보조 디스플레이에서의 실행을 지원하지 않습니다."</string>
<string name="accessibility_divider" msgid="703810061635792791">"화면 분할기"</string>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index fdf3391..69ec8eb 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Сейфтен чыгаруу"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Колдонмодо экран бөлүнбөшү мүмкүн."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Колдонмодо экран бөлүнбөйт."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Бул колдонмону 1 терезеде гана ачууга болот."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Колдонмо кошумча экранда иштебей коюшу мүмкүн."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Колдонмону кошумча экрандарда иштетүүгө болбойт."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Экранды бөлгүч"</string>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index 30631f9..d5ea3cf 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"ເອົາອອກຈາກບ່ອນເກັບສ່ວນຕົວ"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"ແອັບອາດໃຊ້ບໍ່ໄດ້ກັບການແບ່ງໜ້າຈໍ."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"ແອັບບໍ່ຮອງຮັບໜ້າຈໍແບບແຍກກັນ."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"ແອັບນີ້ສາມາດເປີດໄດ້ໃນ 1 ໜ້າຈໍເທົ່ານັ້ນ."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ແອັບອາດບໍ່ສາມາດໃຊ້ໄດ້ໃນໜ້າຈໍທີສອງ."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ແອັບບໍ່ຮອງຮັບການເປີດໃນໜ້າຈໍທີສອງ."</string>
<string name="accessibility_divider" msgid="703810061635792791">"ຕົວຂັ້ນການແບ່ງໜ້າຈໍ"</string>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml
index bac3681..922f5b5 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Nebeslėpti"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Programa gali neveikti naudojant išskaidyto ekrano režimą."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Programoje nepalaikomas skaidytas ekranas."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Šią programą galima atidaryti tik viename lange."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Programa gali neveikti antriniame ekrane."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Programa nepalaiko paleisties antriniuose ekranuose."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Skaidyto ekrano daliklis"</string>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index c74d4f9..08ac928 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Rādīt"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Iespējams, lietotne nedarbosies ekrāna sadalīšanas režīmā."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Lietotnē netiek atbalstīta ekrāna sadalīšana."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Šo lietotni var atvērt tikai vienā logā."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Lietotne, iespējams, nedarbosies sekundārajā displejā."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Lietotnē netiek atbalstīta palaišana sekundārajos displejos."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Ekrāna sadalītājs"</string>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml
index d64097f..ae71ae9 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Прикажете"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Апликацијата може да не работи со поделен екран."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Апликацијата не поддржува поделен екран."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Апликацијава може да се отвори само во еден прозорец."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Апликацијата може да не функционира на друг екран."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Апликацијата не поддржува стартување на други екрани."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Разделник на поделен екран"</string>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index b9cf945..c1950a1 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Ил гаргах"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Апп хуваагдсан дэлгэц дээр ажиллахгүй байж болзошгүй."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Энэ апп нь дэлгэц хуваах тохиргоог дэмждэггүй."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Энэ аппыг зөвхөн 1 цонхонд нээх боломжтой."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Апп хоёрдогч дэлгэцэд ажиллахгүй."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Аппыг хоёрдогч дэлгэцэд эхлүүлэх боломжгүй."</string>
<string name="accessibility_divider" msgid="703810061635792791">"\"Дэлгэц хуваах\" хуваагч"</string>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index 19de976..29821f6 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"अनस्टॅश करा"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"अॅप कदाचित स्प्लिट स्क्रीनसह काम करू शकत नाही."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"अॅप स्क्रीन-विभाजनास समर्थन देत नाही."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"हे अॅप फक्त एका विंडोमध्ये उघडले जाऊ शकते."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"दुसऱ्या डिस्प्लेवर अॅप कदाचित चालणार नाही."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"दुसऱ्या डिस्प्लेवर अॅप लाँच होणार नाही."</string>
<string name="accessibility_divider" msgid="703810061635792791">"विभाजित-स्क्रीन विभाजक"</string>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml
index 4581a77..c3db19d 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Tunjukkan"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Apl mungkin tidak berfungsi dengan skrin pisah."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Apl tidak menyokong skrin pisah."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Apl ini hanya boleh dibuka dalam 1 tetingkap."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Apl mungkin tidak berfungsi pada paparan kedua."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Apl tidak menyokong pelancaran pada paparan kedua."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Pembahagi skrin pisah"</string>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index e0108e3..90b9dfc 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Avslutt oppbevaring"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Det kan hende at appen ikke fungerer med delt skjerm."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Appen støtter ikke delt skjerm."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Denne appen kan bare åpnes i ett vindu."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Appen fungerer kanskje ikke på en sekundær skjerm."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Appen kan ikke kjøres på sekundære skjermer."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Skilleelement for delt skjerm"</string>
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index f6a6975..f9f4ef4 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Niet meer verbergen"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"De app werkt mogelijk niet met gesplitst scherm."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"App biedt geen ondersteuning voor gesplitst scherm."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Deze app kan slechts in 1 venster worden geopend."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"App werkt mogelijk niet op een secundair scherm."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"App kan niet op secundaire displays worden gestart."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Scheiding voor gesplitst scherm"</string>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index e3e8b84..5a76a6f 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"ଦେଖାନ୍ତୁ"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"ସ୍ପ୍ଲିଟ୍-ସ୍କ୍ରିନରେ ଆପ୍ କାମ କରିନପାରେ।"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"ଆପ୍ ସ୍ପ୍ଲିଟ୍-ସ୍କ୍ରୀନକୁ ସପୋର୍ଟ କରେ ନାହିଁ।"</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"ଏହି ଆପକୁ କେବଳ 1ଟି ୱିଣ୍ଡୋରେ ଖୋଲାଯାଇପାରିବ।"</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ସେକେଣ୍ଡାରୀ ଡିସପ୍ଲେରେ ଆପ୍ କାମ ନକରିପାରେ।"</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ସେକେଣ୍ଡାରୀ ଡିସପ୍ଲେରେ ଆପ୍ ଲଞ୍ଚ ସପୋର୍ଟ କରେ ନାହିଁ।"</string>
<string name="accessibility_divider" msgid="703810061635792791">"ସ୍ପ୍ଲିଟ୍-ସ୍କ୍ରୀନ ବିଭାଜକ"</string>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index 16310ffe..617c95e 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"ਅਣਸਟੈਸ਼"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ।"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ।"</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"ਇਹ ਐਪ ਸਿਰਫ਼ 1 ਵਿੰਡੋ ਵਿੱਚ ਖੋਲ੍ਹੀ ਜਾ ਸਕਦੀ ਹੈ।"</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਐਪ ਸੈਕੰਡਰੀ ਡਿਸਪਲੇ \'ਤੇ ਕੰਮ ਨਾ ਕਰੇ।"</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ਐਪ ਸੈਕੰਡਰੀ ਡਿਸਪਲੇਆਂ \'ਤੇ ਲਾਂਚ ਕਰਨ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ"</string>
<string name="accessibility_divider" msgid="703810061635792791">"ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਡਿਵਾਈਡਰ"</string>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index fd6434a..4a17ec7 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Zabierz ze schowka"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Aplikacja może nie działać przy podzielonym ekranie."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Aplikacja nie obsługuje dzielonego ekranu."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Ta aplikacja może być otwarta tylko w 1 oknie."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikacja może nie działać na dodatkowym ekranie."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikacja nie obsługuje uruchamiania na dodatkowych ekranach."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Linia dzielenia ekranu"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
index d4d5ae6..13e83ac 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Remover do armazenamento"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"A app pode não funcionar com o ecrã dividido."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"A app não é compatível com o ecrã dividido."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Esta app só pode ser aberta em 1 janela."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"A app pode não funcionar num ecrã secundário."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"A app não é compatível com o início em ecrãs secundários."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Divisor do ecrã dividido"</string>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index 44220da..c112a9d 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Anulează stocarea"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Este posibil ca aplicația să nu funcționeze cu ecranul împărțit."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Aplicația nu acceptă ecranul împărțit."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Aplicația poate fi deschisă într-o singură fereastră."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Este posibil ca aplicația să nu funcționeze pe un ecran secundar."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplicația nu acceptă lansare pe ecrane secundare."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Separator pentru ecranul împărțit"</string>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index 8816895..489adc0 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Показать"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"В режиме разделения экрана приложение может работать нестабильно."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Приложение не поддерживает разделение экрана."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Это приложение можно открыть только в одном окне."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Приложение может не работать на дополнительном экране"</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Приложение не поддерживает запуск на дополнительных экранах"</string>
<string name="accessibility_divider" msgid="703810061635792791">"Разделитель экрана"</string>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index 37c1205..3237114 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"සඟවා තැබීම ඉවත් කරන්න"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"යෙදුම බෙදුම් තිරය සමග ක්රියා නොකළ හැකිය"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"යෙදුම බෙදුණු-තිරය සඳහා සහාය නොදක්වයි."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"මෙම යෙදුම විවෘත කළ හැක්කේ 1 කවුළුවක පමණයි."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"යෙදුම ද්විතියික සංදර්ශකයක ක්රියා නොකළ හැකිය."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"යෙදුම ද්විතීයික සංදර්ශක මත දියත් කිරීම සඳහා සහාය නොදක්වයි."</string>
<string name="accessibility_divider" msgid="703810061635792791">"බෙදුම්-තිර වෙන්කරණය"</string>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml
index d6900d0..a753021 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Zrušiť skrytie"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Aplikácia nemusí fungovať s rozdelenou obrazovkou."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Aplikácia nepodporuje rozdelenú obrazovku."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Táto aplikácia môže byť otvorená iba v jednom okne."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikácia nemusí fungovať na sekundárnej obrazovke."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikácia nepodporuje spúšťanie na sekundárnych obrazovkách."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Rozdeľovač obrazovky"</string>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index b0a8587..b5d8733 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Razkrij"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Aplikacija morda ne deluje v načinu razdeljenega zaslona."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Aplikacija ne podpira načina razdeljenega zaslona."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"To aplikacijo je mogoče odpreti samo v enem oknu."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikacija morda ne bo delovala na sekundarnem zaslonu."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikacija ne podpira zagona na sekundarnih zaslonih."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Razdelilnik zaslonov"</string>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index f4a22d4..ebd644c 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Mos e fshih"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Aplikacioni mund të mos funksionojë me ekranin e ndarë."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Aplikacioni nuk mbështet ekranin e ndarë."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Ky aplikacion mund të hapet vetëm në 1 dritare."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Aplikacioni mund të mos funksionojë në një ekran dytësor."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Aplikacioni nuk mbështet nisjen në ekrane dytësore."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Ndarësi i ekranit të ndarë"</string>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index 3d96c65..d051ca3 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Уклоните из тајне меморије"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Апликација можда неће радити са подељеним екраном."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Апликација не подржава подељени екран."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Ова апликација може да се отвори само у једном прозору."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Апликација можда неће функционисати на секундарном екрану."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Апликација не подржава покретање на секундарним екранима."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Разделник подељеног екрана"</string>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index b7d2584..cd46039 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Återställ stash"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Appen kanske inte fungerar med delad skärm."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Appen har inte stöd för delad skärm."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Denna app kan bara vara öppen i ett fönster."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Appen kanske inte fungerar på en sekundär skärm."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Appen kan inte köras på en sekundär skärm."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Avdelare för delad skärm"</string>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index f0daac9..0c0114a 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"ఆన్స్టాచ్"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"స్క్రీన్ విభజనతో యాప్ పని చేయకపోవచ్చు."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"యాప్లో స్క్రీన్ విభజనకు మద్దతు లేదు."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"ఈ యాప్ను 1 విండోలో మాత్రమే తెరవవచ్చు."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ప్రత్యామ్నాయ డిస్ప్లేలో యాప్ పని చేయకపోవచ్చు."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ప్రత్యామ్నాయ డిస్ప్లేల్లో ప్రారంభానికి యాప్ మద్దతు లేదు."</string>
<string name="accessibility_divider" msgid="703810061635792791">"విభజన స్క్రీన్ విభాగిని"</string>
diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml
index 74a55c3..9f3a146 100644
--- a/libs/WindowManager/Shell/res/values-th/strings.xml
+++ b/libs/WindowManager/Shell/res/values-th/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"เอาออกจากที่เก็บส่วนตัว"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"แอปอาจใช้ไม่ได้กับโหมดแบ่งหน้าจอ"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"แอปไม่สนับสนุนการแยกหน้าจอ"</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"แอปนี้เปิดได้ใน 1 หน้าต่างเท่านั้น"</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"แอปอาจไม่ทำงานในจอแสดงผลรอง"</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"แอปไม่รองรับการเรียกใช้ในจอแสดงผลรอง"</string>
<string name="accessibility_divider" msgid="703810061635792791">"เส้นแบ่งหน้าจอ"</string>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml
index 58ef31b..c20a07f 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"I-unstash"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Posibleng hindi gumana ang app sa split screen."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Hindi sinusuportahan ng app ang split-screen."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Sa 1 window lang puwedeng buksan ang app na ito."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Maaaring hindi gumana ang app sa pangalawang display."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Hindi sinusuportahan ng app ang paglulunsad sa mga pangalawang display."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Divider ng split-screen"</string>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index 6ca9598..aeb86da 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Depolama"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Uygulama bölünmüş ekranda çalışmayabilir."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Uygulama bölünmüş ekranı desteklemiyor."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Bu uygulama yalnızca 1 pencerede açılabilir."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Uygulama ikincil ekranda çalışmayabilir."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Uygulama ikincil ekranlarda başlatılmayı desteklemiyor."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Bölünmüş ekran ayırıcı"</string>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index 645be37..81672bf 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Unstash"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"ممکن ہے کہ ایپ اسپلٹ اسکرین کے ساتھ کام نہ کرے۔"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"ایپ سپلٹ اسکرین کو سپورٹ نہیں کرتی۔"</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"یہ ایپ صرف 1 ونڈو میں کھولی جا سکتی ہے۔"</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"ممکن ہے ایپ ثانوی ڈسپلے پر کام نہ کرے۔"</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"ایپ ثانوی ڈسپلیز پر شروعات کا تعاون نہیں کرتی۔"</string>
<string name="accessibility_divider" msgid="703810061635792791">"سپلٹ اسکرین تقسیم کار"</string>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml
index 923e7b2..d0384e9 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Chiqarish"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Bu ilova ekranni ikkiga ajratish rejimini dastaklamaydi."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Bu ilova ekranni bo‘lish xususiyatini qo‘llab-quvvatlamaydi."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Bu ilovani faqat 1 ta oynada ochish mumkin."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Bu ilova qo‘shimcha ekranda ishlamasligi mumkin."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Bu ilova qo‘shimcha ekranlarda ishga tushmaydi."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Ekranni ikkiga bo‘lish chizig‘i"</string>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index b151d72..49986b5 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Hiện"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Ứng dụng có thể không hoạt động với tính năng chia đôi màn hình."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Ứng dụng không hỗ trợ chia đôi màn hình."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Ứng dụng này chỉ có thể mở 1 cửa sổ."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Ứng dụng có thể không hoạt động trên màn hình phụ."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Ứng dụng không hỗ trợ khởi chạy trên màn hình phụ."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Bộ chia chia đôi màn hình"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index 66b5a4b..acdb252 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"取消隐藏"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"应用可能无法在分屏模式下正常运行。"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"应用不支持分屏。"</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"此应用只能在 1 个窗口中打开。"</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"应用可能无法在辅显示屏上正常运行。"</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"应用不支持在辅显示屏上启动。"</string>
<string name="accessibility_divider" msgid="703810061635792791">"分屏分隔线"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index 1a2e377..b1a957e5 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"取消保護"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"應用程式可能無法在分割畫面中運作。"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"應用程式不支援分割畫面。"</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"此應用程式只可在 1 個視窗中開啟"</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"應用程式可能無法在次要顯示屏上運作。"</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"應用程式無法在次要顯示屏上啟動。"</string>
<string name="accessibility_divider" msgid="703810061635792791">"分割畫面分隔線"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index 99a79cf..bb3dba1 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"取消暫時隱藏"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"應用程式可能無法在分割畫面中運作。"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"這個應用程式不支援分割畫面。"</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"這個應用程式只能在 1 個視窗中開啟。"</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"應用程式可能無法在次要顯示器上運作。"</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"應用程式無法在次要顯示器上啟動。"</string>
<string name="accessibility_divider" msgid="703810061635792791">"分割畫面分隔線"</string>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index cfafb61..51a23ff 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -34,8 +34,7 @@
<string name="accessibility_action_pip_unstash" msgid="7467499339610437646">"Susa isiteshi"</string>
<string name="dock_forced_resizable" msgid="1749750436092293116">"Izinhlelo zokusebenza kungenzeka zingasebenzi ngesikrini esihlukanisiwe."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="7408396418008948957">"Uhlelo lokusebenza alusekeli isikrini esihlukanisiwe."</string>
- <!-- no translation found for dock_multi_instances_not_supported_text (5242868470666346929) -->
- <skip />
+ <string name="dock_multi_instances_not_supported_text" msgid="5242868470666346929">"Le-app ingavulwa kuphela ewindini eli-1."</string>
<string name="forced_resizable_secondary_display" msgid="1768046938673582671">"Uhlelo lokusebenza kungenzeka lungasebenzi kusibonisi sesibili."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="4226485344988071769">"Uhlelo lokusebenza alusekeli ukuqalisa kuzibonisi zesibili."</string>
<string name="accessibility_divider" msgid="703810061635792791">"Isihlukanisi sokuhlukanisa isikrini"</string>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 1fd91de..9674b69 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -475,8 +475,13 @@
@VisibleForTesting
public void onStatusBarStateChanged(boolean isShade) {
+ boolean didChange = mIsStatusBarShade != isShade;
+ if (DEBUG_BUBBLE_CONTROLLER) {
+ Log.d(TAG, "onStatusBarStateChanged isShade=" + isShade + " didChange=" + didChange);
+ }
mIsStatusBarShade = isShade;
- if (!mIsStatusBarShade) {
+ if (!mIsStatusBarShade && didChange) {
+ // Only collapse stack on change
collapseStack();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index f621351..04d62f6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -1955,6 +1955,7 @@
if (wasExpanded) {
stopMonitoringSwipeUpGesture();
animateCollapse();
+ showManageMenu(false);
logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED);
} else {
animateExpansion();
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 ae49616..45b234a 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
@@ -122,6 +122,7 @@
private int mDensity;
private final boolean mDimNonImeSide;
+ private ValueAnimator mDividerFlingAnimator;
public SplitLayout(String windowName, Context context, Configuration configuration,
SplitLayoutHandler splitLayoutHandler,
@@ -395,6 +396,10 @@
mSplitWindowManager.release(t);
mDisplayImeController.removePositionProcessor(mImePositionProcessor);
mImePositionProcessor.reset();
+ if (mDividerFlingAnimator != null) {
+ mDividerFlingAnimator.cancel();
+ }
+ resetDividerPosition();
}
public void release() {
@@ -577,13 +582,18 @@
CUJ_SPLIT_SCREEN_RESIZE);
return;
}
- ValueAnimator animator = ValueAnimator
+
+ if (mDividerFlingAnimator != null) {
+ mDividerFlingAnimator.cancel();
+ }
+
+ mDividerFlingAnimator = ValueAnimator
.ofInt(from, to)
.setDuration(duration);
- animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- animator.addUpdateListener(
+ mDividerFlingAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mDividerFlingAnimator.addUpdateListener(
animation -> updateDivideBounds((int) animation.getAnimatedValue()));
- animator.addListener(new AnimatorListenerAdapter() {
+ mDividerFlingAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (flingFinishedCallback != null) {
@@ -591,14 +601,15 @@
}
InteractionJankMonitorUtils.endTracing(
CUJ_SPLIT_SCREEN_RESIZE);
+ mDividerFlingAnimator = null;
}
@Override
public void onAnimationCancel(Animator animation) {
- setDividePosition(to, true /* applyLayoutChange */);
+ mDividerFlingAnimator = null;
}
});
- animator.start();
+ mDividerFlingAnimator.start();
}
/** Switch both surface position with animation. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index 90b35a5..44bcdb2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -82,7 +82,7 @@
mTasks.put(taskInfo.taskId, state);
if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- mWindowDecorationViewModel.createWindowDecoration(taskInfo, leash, t, t);
+ mWindowDecorationViewModel.onTaskOpening(taskInfo, leash, t, t);
t.apply();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java
index 168f6d7..60e5ff2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java
@@ -90,7 +90,7 @@
// This logic relies on 2 assumptions: 1 is that child tasks will be visited before
// parents (due to how z-order works). 2 is that no non-tasks are interleaved
// between tasks (hierarchically).
- taskParents.add(change.getContainer());
+ taskParents.add(change.getParent());
}
if (taskParents.contains(change.getContainer())) {
continue;
@@ -120,7 +120,7 @@
TransitionInfo.Change change,
SurfaceControl.Transaction startT,
SurfaceControl.Transaction finishT) {
- mWindowDecorViewModel.createWindowDecoration(
+ mWindowDecorViewModel.onTaskOpening(
change.getTaskInfo(), change.getLeash(), startT, finishT);
}
@@ -128,31 +128,23 @@
TransitionInfo.Change change,
SurfaceControl.Transaction startT,
SurfaceControl.Transaction finishT) {
- mWindowDecorViewModel.setupWindowDecorationForTransition(
- change.getTaskInfo(), startT, finishT);
+ mWindowDecorViewModel.onTaskClosing(change.getTaskInfo(), startT, finishT);
}
private void onChangeTransitionReady(
TransitionInfo.Change change,
SurfaceControl.Transaction startT,
SurfaceControl.Transaction finishT) {
- mWindowDecorViewModel.setupWindowDecorationForTransition(
- change.getTaskInfo(), startT, finishT);
+ mWindowDecorViewModel.onTaskChanging(
+ change.getTaskInfo(), change.getLeash(), startT, finishT);
}
private void onToFrontTransitionReady(
TransitionInfo.Change change,
SurfaceControl.Transaction startT,
SurfaceControl.Transaction finishT) {
- boolean exists = mWindowDecorViewModel.setupWindowDecorationForTransition(
- change.getTaskInfo(),
- startT,
- finishT);
- if (!exists) {
- // Window caption does not exist, create it
- mWindowDecorViewModel.createWindowDecoration(
- change.getTaskInfo(), change.getLeash(), startT, finishT);
- }
+ mWindowDecorViewModel.onTaskChanging(
+ change.getTaskInfo(), change.getLeash(), startT, finishT);
}
@Override
@@ -188,4 +180,4 @@
mWindowDecorViewModel.destroyWindowDecoration(taskInfo.get(i));
}
}
-}
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
index 75a4091..6623f5c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
@@ -103,7 +103,7 @@
if (mWindowDecorViewModelOptional.isPresent()) {
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
createdWindowDecor = mWindowDecorViewModelOptional.get()
- .createWindowDecoration(taskInfo, leash, t, t);
+ .onTaskOpening(taskInfo, leash, t, t);
t.apply();
}
if (!createdWindowDecor) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
index 17d7f5d..5376ae3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
@@ -97,6 +97,8 @@
private int mShelfHeight;
/** Whether the user has resized the PIP manually. */
private boolean mHasUserResizedPip;
+ /** Whether the user has moved the PIP manually. */
+ private boolean mHasUserMovedPip;
/**
* Areas defined by currently visible apps that they prefer to keep clear from overlays such as
* the PiP. Restricted areas may only move the PiP a limited amount from its anchor position.
@@ -279,6 +281,7 @@
if (changed) {
clearReentryState();
setHasUserResizedPip(false);
+ setHasUserMovedPip(false);
}
}
@@ -442,6 +445,16 @@
mHasUserResizedPip = hasUserResizedPip;
}
+ /** Returns whether the user has moved the PIP. */
+ public boolean hasUserMovedPip() {
+ return mHasUserMovedPip;
+ }
+
+ /** Set whether the user has moved the PIP. */
+ public void setHasUserMovedPip(boolean hasUserMovedPip) {
+ mHasUserMovedPip = hasUserMovedPip;
+ }
+
/**
* Registers a callback when the minimal size of PIP that is set by the app changes.
*/
@@ -577,6 +590,8 @@
pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
pw.println(innerPrefix + "mIsShelfShowing=" + mIsShelfShowing);
pw.println(innerPrefix + "mShelfHeight=" + mShelfHeight);
+ pw.println(innerPrefix + "mHasUserMovedPip=" + mHasUserMovedPip);
+ pw.println(innerPrefix + "mHasUserResizedPip=" + mHasUserResizedPip);
if (mPipReentryState == null) {
pw.println(innerPrefix + "mPipReentryState=null");
} else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
index 84071e0..690505e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
+import android.os.SystemProperties;
import android.util.ArraySet;
import android.view.Gravity;
@@ -34,6 +35,10 @@
*/
public class PhonePipKeepClearAlgorithm implements PipKeepClearAlgorithm {
+ private boolean mKeepClearAreaGravityEnabled =
+ SystemProperties.getBoolean(
+ "persist.wm.debug.enable_pip_keep_clear_algorithm_gravity", false);
+
protected int mKeepClearAreasPadding;
public PhonePipKeepClearAlgorithm(Context context) {
@@ -53,31 +58,36 @@
Rect startingBounds = pipBoundsState.getBounds().isEmpty()
? pipBoundsAlgorithm.getEntryDestinationBoundsIgnoringKeepClearAreas()
: pipBoundsState.getBounds();
- float snapFraction = pipBoundsAlgorithm.getSnapFraction(startingBounds);
- int verticalGravity = Gravity.BOTTOM;
- int horizontalGravity;
- if (snapFraction >= 0.5f && snapFraction < 2.5f) {
- horizontalGravity = Gravity.RIGHT;
- } else {
- horizontalGravity = Gravity.LEFT;
- }
- // push the bounds based on the gravity
Rect insets = new Rect();
pipBoundsAlgorithm.getInsetBounds(insets);
if (pipBoundsState.isImeShowing()) {
insets.bottom -= pipBoundsState.getImeHeight();
}
- Rect pushedBounds = new Rect(startingBounds);
- if (verticalGravity == Gravity.BOTTOM) {
- pushedBounds.offsetTo(pushedBounds.left,
- insets.bottom - pushedBounds.height());
+ Rect pipBounds = new Rect(startingBounds);
+
+ // move PiP towards corner if user hasn't moved it manually or the flag is on
+ if (mKeepClearAreaGravityEnabled
+ || (!pipBoundsState.hasUserMovedPip() && !pipBoundsState.hasUserResizedPip())) {
+ float snapFraction = pipBoundsAlgorithm.getSnapFraction(startingBounds);
+ int verticalGravity = Gravity.BOTTOM;
+ int horizontalGravity;
+ if (snapFraction >= 0.5f && snapFraction < 2.5f) {
+ horizontalGravity = Gravity.RIGHT;
+ } else {
+ horizontalGravity = Gravity.LEFT;
+ }
+ if (verticalGravity == Gravity.BOTTOM) {
+ pipBounds.offsetTo(pipBounds.left,
+ insets.bottom - pipBounds.height());
+ }
+ if (horizontalGravity == Gravity.RIGHT) {
+ pipBounds.offsetTo(insets.right - pipBounds.width(), pipBounds.top);
+ } else {
+ pipBounds.offsetTo(insets.left, pipBounds.top);
+ }
}
- if (horizontalGravity == Gravity.RIGHT) {
- pushedBounds.offsetTo(insets.right - pushedBounds.width(), pushedBounds.top);
- } else {
- pushedBounds.offsetTo(insets.left, pushedBounds.top);
- }
- return findUnoccludedPosition(pushedBounds, pipBoundsState.getRestrictedKeepClearAreas(),
+
+ return findUnoccludedPosition(pipBounds, pipBoundsState.getRestrictedKeepClearAreas(),
pipBoundsState.getUnrestrictedKeepClearAreas(), insets);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index a9a97be..83bc7c0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -875,6 +875,8 @@
}
if (touchState.isDragging()) {
+ mPipBoundsState.setHasUserMovedPip(true);
+
// Move the pinned stack freely
final PointF lastDelta = touchState.getLastTouchDelta();
float lastX = mStartPosition.x + mDelta.x;
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 94ca9d3..4cb7623 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
@@ -1040,7 +1040,7 @@
mIsDividerRemoteAnimating = false;
mSplitLayout.getInvisibleBounds(mTempRect1);
- if (childrenToTop == null) {
+ if (childrenToTop == null || childrenToTop.getTopVisibleChildTaskId() == INVALID_TASK_ID) {
mSideStage.removeAllTasks(wct, false /* toTop */);
mMainStage.deactivate(wct, false /* toTop */);
wct.reorder(mRootTaskInfo.token, false /* onTop */);
@@ -1299,13 +1299,6 @@
}
}
- private void onStageChildTaskEnterPip() {
- // When the exit split-screen is caused by one of the task enters auto pip,
- // we want both tasks to be put to bottom instead of top, otherwise it will end up
- // a fullscreen plus a pinned task instead of pinned only at the end of the transition.
- exitSplitScreen(null, EXIT_REASON_CHILD_TASK_ENTER_PIP);
- }
-
private void updateRecentTasksSplitPair() {
if (!mShouldUpdateRecents) {
return;
@@ -2068,7 +2061,6 @@
// Update divider state after animation so that it is still around and positioned
// properly for the animation itself.
mSplitLayout.release();
- mSplitLayout.resetDividerPosition();
mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
}
}
@@ -2345,11 +2337,6 @@
}
@Override
- public void onChildTaskEnterPip() {
- StageCoordinator.this.onStageChildTaskEnterPip();
- }
-
- @Override
public void onRootTaskVanished() {
reset();
StageCoordinator.this.onRootTaskVanished();
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 bcf900b..358f712 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
@@ -18,7 +18,6 @@
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
@@ -74,8 +73,6 @@
void onChildTaskStatusChanged(int taskId, boolean present, boolean visible);
- void onChildTaskEnterPip();
-
void onRootTaskVanished();
void onNoLongerSupportMultiWindow();
@@ -257,9 +254,6 @@
// Status is managed/synchronized by the transition lifecycle.
return;
}
- if (taskInfo.getWindowingMode() == WINDOWING_MODE_PINNED) {
- mCallbacks.onChildTaskEnterPip();
- }
sendStatusChanged();
} else {
throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 8369569..e40db4e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -55,6 +55,8 @@
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
import com.android.wm.shell.transition.Transitions;
+import java.util.function.Supplier;
+
/**
* View model for the window decoration with a caption and shadows. Works with
* {@link CaptionWindowDecoration}.
@@ -62,6 +64,8 @@
public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
private static final String TAG = "CaptionViewModel";
+ private final CaptionWindowDecoration.Factory mCaptionWindowDecorFactory;
+ private final Supplier<InputManager> mInputManagerSupplier;
private final ActivityTaskManager mActivityTaskManager;
private final ShellTaskOrganizer mTaskOrganizer;
private final Context mContext;
@@ -77,6 +81,7 @@
private final SparseArray<CaptionWindowDecoration> mWindowDecorByTaskId = new SparseArray<>();
private final DragStartListenerImpl mDragStartListener = new DragStartListenerImpl();
+ private EventReceiverFactory mEventReceiverFactory = new EventReceiverFactory();
public CaptionWindowDecorViewModel(
Context context,
@@ -86,6 +91,29 @@
DisplayController displayController,
SyncTransactionQueue syncQueue,
DesktopModeController desktopModeController) {
+ this(
+ context,
+ mainHandler,
+ mainChoreographer,
+ taskOrganizer,
+ displayController,
+ syncQueue,
+ desktopModeController,
+ new CaptionWindowDecoration.Factory(),
+ InputManager::getInstance);
+ }
+
+ public CaptionWindowDecorViewModel(
+ Context context,
+ Handler mainHandler,
+ Choreographer mainChoreographer,
+ ShellTaskOrganizer taskOrganizer,
+ DisplayController displayController,
+ SyncTransactionQueue syncQueue,
+ DesktopModeController desktopModeController,
+ CaptionWindowDecoration.Factory captionWindowDecorFactory,
+ Supplier<InputManager> inputManagerSupplier) {
+
mContext = context;
mMainHandler = mainHandler;
mMainChoreographer = mainChoreographer;
@@ -94,7 +122,13 @@
mDisplayController = displayController;
mSyncQueue = syncQueue;
mDesktopModeController = desktopModeController;
- mTransitionDragActive = false;
+
+ mCaptionWindowDecorFactory = captionWindowDecorFactory;
+ mInputManagerSupplier = inputManagerSupplier;
+ }
+
+ void setEventReceiverFactory(EventReceiverFactory eventReceiverFactory) {
+ mEventReceiverFactory = eventReceiverFactory;
}
@Override
@@ -103,42 +137,13 @@
}
@Override
- public boolean createWindowDecoration(
+ public boolean onTaskOpening(
ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
SurfaceControl.Transaction startT,
SurfaceControl.Transaction finishT) {
if (!shouldShowWindowDecor(taskInfo)) return false;
- CaptionWindowDecoration oldDecoration = mWindowDecorByTaskId.get(taskInfo.taskId);
- if (oldDecoration != null) {
- // close the old decoration if it exists to avoid two window decorations being added
- oldDecoration.close();
- }
- final CaptionWindowDecoration windowDecoration = new CaptionWindowDecoration(
- mContext,
- mDisplayController,
- mTaskOrganizer,
- taskInfo,
- taskSurface,
- mMainHandler,
- mMainChoreographer,
- mSyncQueue);
- mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
-
- TaskPositioner taskPositioner = new TaskPositioner(mTaskOrganizer, windowDecoration,
- mDragStartListener);
- CaptionTouchEventListener touchEventListener =
- new CaptionTouchEventListener(taskInfo, taskPositioner,
- windowDecoration.getDragDetector());
- windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
- windowDecoration.setDragResizeCallback(taskPositioner);
- setupWindowDecorationForTransition(taskInfo, startT, finishT);
- if (mInputMonitor == null) {
- mInputMonitor = InputManager.getInstance().monitorGestureInput(
- "caption-touch", mContext.getDisplayId());
- mEventReceiver = new EventReceiver(
- mInputMonitor.getInputChannel(), Looper.myLooper());
- }
+ createWindowDecoration(taskInfo, taskSurface, startT, finishT);
return true;
}
@@ -151,25 +156,45 @@
}
@Override
- public boolean setupWindowDecorationForTransition(
+ public void onTaskChanging(
+ RunningTaskInfo taskInfo,
+ SurfaceControl taskSurface,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+
+ if (!shouldShowWindowDecor(taskInfo)) {
+ if (decoration != null) {
+ destroyWindowDecoration(taskInfo);
+ }
+ return;
+ }
+
+ if (decoration == null) {
+ createWindowDecoration(taskInfo, taskSurface, startT, finishT);
+ } else {
+ decoration.relayout(taskInfo, startT, finishT);
+ }
+ }
+
+ @Override
+ public void onTaskClosing(
RunningTaskInfo taskInfo,
SurfaceControl.Transaction startT,
SurfaceControl.Transaction finishT) {
final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
- if (decoration == null) return false;
+ if (decoration == null) return;
decoration.relayout(taskInfo, startT, finishT);
- return true;
}
@Override
- public boolean destroyWindowDecoration(RunningTaskInfo taskInfo) {
+ public void destroyWindowDecoration(RunningTaskInfo taskInfo) {
final CaptionWindowDecoration decoration =
mWindowDecorByTaskId.removeReturnOld(taskInfo.taskId);
- if (decoration == null) return false;
+ if (decoration == null) return;
decoration.close();
- return true;
}
private class CaptionTouchEventListener implements
@@ -217,6 +242,7 @@
decoration.setButtonVisibility();
}
}
+
private void injectBackKey() {
sendBackEvent(KeyEvent.ACTION_DOWN);
sendBackEvent(KeyEvent.ACTION_UP);
@@ -266,7 +292,7 @@
*/
private void handleEventForMove(MotionEvent e) {
RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
- int windowingMode = mDesktopModeController
+ int windowingMode = mDesktopModeController
.getDisplayAreaWindowingMode(taskInfo.displayId);
if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
return;
@@ -302,7 +328,7 @@
}
// InputEventReceiver to listen for touch input outside of caption bounds
- private class EventReceiver extends InputEventReceiver {
+ class EventReceiver extends InputEventReceiver {
EventReceiver(InputChannel channel, Looper looper) {
super(channel, looper);
}
@@ -318,8 +344,15 @@
}
}
+ class EventReceiverFactory {
+ EventReceiver create(InputChannel channel, Looper looper) {
+ return new EventReceiver(channel, looper);
+ }
+ }
+
/**
* Handle MotionEvents relevant to focused task's caption that don't directly touch it
+ *
* @param ev the {@link MotionEvent} received by {@link EventReceiver}
*/
private void handleReceivedMotionEvent(MotionEvent ev) {
@@ -401,7 +434,6 @@
return focusedDecor;
}
-
private boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) return true;
return DesktopModeStatus.IS_SUPPORTED
@@ -410,7 +442,47 @@
.getResources().getConfiguration().smallestScreenWidthDp >= 600;
}
- private class DragStartListenerImpl implements TaskPositioner.DragStartListener{
+ private void createWindowDecoration(
+ ActivityManager.RunningTaskInfo taskInfo,
+ SurfaceControl taskSurface,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT) {
+ CaptionWindowDecoration oldDecoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+ if (oldDecoration != null) {
+ // close the old decoration if it exists to avoid two window decorations being added
+ oldDecoration.close();
+ }
+ final CaptionWindowDecoration windowDecoration =
+ mCaptionWindowDecorFactory.create(
+ mContext,
+ mDisplayController,
+ mTaskOrganizer,
+ taskInfo,
+ taskSurface,
+ mMainHandler,
+ mMainChoreographer,
+ mSyncQueue);
+ mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
+
+ TaskPositioner taskPositioner =
+ new TaskPositioner(mTaskOrganizer, windowDecoration, mDragStartListener);
+ CaptionTouchEventListener touchEventListener =
+ new CaptionTouchEventListener(
+ taskInfo, taskPositioner, windowDecoration.getDragDetector());
+ windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
+ windowDecoration.setDragResizeCallback(taskPositioner);
+ windowDecoration.relayout(taskInfo, startT, finishT);
+ if (mInputMonitor == null) {
+ InputManager inputManager = mInputManagerSupplier.get();
+ mInputMonitor =
+ inputManager.monitorGestureInput("caption-touch", mContext.getDisplayId());
+ mEventReceiver =
+ mEventReceiverFactory.create(
+ mInputMonitor.getInputChannel(), Looper.myLooper());
+ }
+ }
+
+ private class DragStartListenerImpl implements TaskPositioner.DragStartListener {
@Override
public void onDragStart(int taskId) {
mWindowDecorByTaskId.get(taskId).closeHandleMenu();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index 59576cd..037ca20 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -42,7 +42,8 @@
/**
* Defines visuals and behaviors of a window decoration of a caption bar and shadows. It works with
- * {@link CaptionWindowDecorViewModel}. The caption bar contains a handle, back button, and close button.
+ * {@link CaptionWindowDecorViewModel}. The caption bar contains a handle, back button, and close
+ * button.
*
* The shadow's thickness is 20dp when the window is in focus and 5dp when the window isn't.
*/
@@ -181,12 +182,12 @@
if (oldDecorationSurface != mDecorationContainerSurface || mDragResizeListener == null) {
closeDragResizeListener();
mDragResizeListener = new DragResizeInputListener(
- mContext,
- mHandler,
- mChoreographer,
- mDisplay.getDisplayId(),
- mDecorationContainerSurface,
- mDragResizeCallback);
+ mContext,
+ mHandler,
+ mChoreographer,
+ mDisplay.getDisplayId(),
+ mDecorationContainerSurface,
+ mDragResizeCallback);
}
int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext()).getScaledTouchSlop();
@@ -242,7 +243,6 @@
/**
* Sets the visibility of buttons and color of caption based on desktop mode status
- *
*/
void setButtonVisibility() {
mDesktopActive = DesktopModeStatus.isActive(mContext);
@@ -313,6 +313,7 @@
/**
* Close an open handle menu if input is outside of menu coordinates
+ *
* @param ev the tapped point to compare against
*/
void closeHandleMenuIfNeeded(MotionEvent ev) {
@@ -329,6 +330,7 @@
/**
* Offset the coordinates of a {@link MotionEvent} to be in the same coordinate space as caption
+ *
* @param ev the {@link MotionEvent} to offset
* @return the point of the input in local space
*/
@@ -343,7 +345,8 @@
/**
* Determine if a passed MotionEvent is in a view in caption
- * @param ev the {@link MotionEvent} to check
+ *
+ * @param ev the {@link MotionEvent} to check
* @param layoutId the id of the view
* @return {@code true} if event is inside the specified view, {@code false} if not
*/
@@ -363,6 +366,7 @@
* Check a passed MotionEvent if a click has occurred on any button on this caption
* Note this should only be called when a regular onClick is not possible
* (i.e. the button was clicked through status bar layer)
+ *
* @param ev the MotionEvent to compare
*/
void checkClickEvent(MotionEvent ev) {
@@ -399,4 +403,27 @@
closeHandleMenu();
super.close();
}
+
+ static class Factory {
+
+ CaptionWindowDecoration create(
+ Context context,
+ DisplayController displayController,
+ ShellTaskOrganizer taskOrganizer,
+ ActivityManager.RunningTaskInfo taskInfo,
+ SurfaceControl taskSurface,
+ Handler handler,
+ Choreographer choreographer,
+ SyncTransactionQueue syncQueue) {
+ return new CaptionWindowDecoration(
+ context,
+ displayController,
+ taskOrganizer,
+ taskInfo,
+ taskSurface,
+ handler,
+ choreographer,
+ syncQueue);
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
index 2ce4d04..907977c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java
@@ -28,7 +28,6 @@
* servers.
*/
public interface WindowDecorViewModel {
-
/**
* Sets the transition starter that starts freeform task transitions.
*
@@ -37,16 +36,16 @@
void setFreeformTaskTransitionStarter(FreeformTaskTransitionStarter transitionStarter);
/**
- * Creates a window decoration for the given task.
- * Can be {@code null} for Fullscreen tasks but not Freeform ones.
+ * Creates a window decoration for the given task. Can be {@code null} for Fullscreen tasks but
+ * not Freeform ones.
*
- * @param taskInfo the initial task info of the task
+ * @param taskInfo the initial task info of the task
* @param taskSurface the surface of the task
- * @param startT the start transaction to be applied before the transition
- * @param finishT the finish transaction to restore states after the transition
+ * @param startT the start transaction to be applied before the transition
+ * @param finishT the finish transaction to restore states after the transition
* @return {@code true} if window decoration was created, {@code false} otherwise
*/
- boolean createWindowDecoration(
+ boolean onTaskOpening(
ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
SurfaceControl.Transaction startT,
@@ -54,7 +53,7 @@
/**
* Notifies a task info update on the given task, with the window decoration created previously
- * for this task by {@link #createWindowDecoration}.
+ * for this task by {@link #onTaskOpening}.
*
* @param taskInfo the new task info of the task
*/
@@ -62,13 +61,29 @@
/**
* Notifies a transition is about to start about the given task to give the window decoration a
- * chance to prepare for this transition.
+ * chance to prepare for this transition. Unlike {@link #onTaskInfoChanged}, this method creates
+ * a window decoration if one does not exist but is required.
*
- * @param startT the start transaction to be applied before the transition
- * @param finishT the finish transaction to restore states after the transition
- * @return {@code true} if window decoration exists, {@code false} otherwise
+ * @param taskInfo the initial task info of the task
+ * @param taskSurface the surface of the task
+ * @param startT the start transaction to be applied before the transition
+ * @param finishT the finish transaction to restore states after the transition
*/
- boolean setupWindowDecorationForTransition(
+ void onTaskChanging(
+ ActivityManager.RunningTaskInfo taskInfo,
+ SurfaceControl taskSurface,
+ SurfaceControl.Transaction startT,
+ SurfaceControl.Transaction finishT);
+
+ /**
+ * Notifies that the given task is about to close to give the window decoration a chance to
+ * prepare for this transition.
+ *
+ * @param taskInfo the initial task info of the task
+ * @param startT the start transaction to be applied before the transition
+ * @param finishT the finish transaction to restore states after the transition
+ */
+ void onTaskClosing(
ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl.Transaction startT,
SurfaceControl.Transaction finishT);
@@ -77,7 +92,6 @@
* Destroys the window decoration of the give task.
*
* @param taskInfo the info of the task
- * @return {@code true} if window decoration was destroyed, {@code false} otherwise
*/
- boolean destroyWindowDecoration(ActivityManager.RunningTaskInfo taskInfo);
-}
+ void destroyWindowDecoration(ActivityManager.RunningTaskInfo taskInfo);
+}
\ No newline at end of file
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 7ecb3f3..9215496 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
@@ -251,7 +251,9 @@
}
final int captionHeight = loadDimensionPixelSize(resources, params.mCaptionHeightId);
- final int captionWidth = loadDimensionPixelSize(resources, params.mCaptionWidthId);
+ final int captionWidth = params.mCaptionWidthId == Resources.ID_NULL
+ ? taskBounds.width()
+ : loadDimensionPixelSize(resources, params.mCaptionWidthId);
startT.setPosition(
mCaptionContainerSurface,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java
index 7068a84..48415d4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserverTest.java
@@ -103,7 +103,7 @@
mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
mTransitionObserver.onTransitionStarting(transition);
- verify(mWindowDecorViewModel).createWindowDecoration(
+ verify(mWindowDecorViewModel).onTaskOpening(
change.getTaskInfo(), change.getLeash(), startT, finishT);
}
@@ -120,7 +120,7 @@
mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
mTransitionObserver.onTransitionStarting(transition);
- verify(mWindowDecorViewModel).setupWindowDecorationForTransition(
+ verify(mWindowDecorViewModel).onTaskClosing(
change.getTaskInfo(), startT, finishT);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModelTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModelTests.java
new file mode 100644
index 0000000..8b134ed
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModelTests.java
@@ -0,0 +1,217 @@
+/*
+ * 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 com.android.wm.shell.windowdecor;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.hardware.input.InputManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.view.Choreographer;
+import android.view.Display;
+import android.view.InputChannel;
+import android.view.InputMonitor;
+import android.view.SurfaceControl;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.GrantPermissionRule;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.TestRunningTaskInfoBuilder;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.desktopmode.DesktopModeController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Supplier;
+
+/** Tests of {@link CaptionWindowDecorViewModel} */
+@SmallTest
+public class CaptionWindowDecorViewModelTests extends ShellTestCase {
+ @Mock private CaptionWindowDecoration mCaptionWindowDecoration;
+
+ @Mock private CaptionWindowDecoration.Factory mCaptionWindowDecorFactory;
+
+ @Mock private Handler mMainHandler;
+
+ @Mock private Choreographer mMainChoreographer;
+
+ @Mock private ShellTaskOrganizer mTaskOrganizer;
+
+ @Mock private DisplayController mDisplayController;
+
+ @Mock private SyncTransactionQueue mSyncQueue;
+
+ @Mock private DesktopModeController mDesktopModeController;
+
+ @Mock private InputMonitor mInputMonitor;
+
+ @Mock private InputChannel mInputChannel;
+
+ @Mock private CaptionWindowDecorViewModel.EventReceiverFactory mEventReceiverFactory;
+
+ @Mock private CaptionWindowDecorViewModel.EventReceiver mEventReceiver;
+
+ @Mock private InputManager mInputManager;
+
+ private final List<InputManager> mMockInputManagers = new ArrayList<>();
+
+ private CaptionWindowDecorViewModel mCaptionWindowDecorViewModel;
+
+ @Before
+ public void setUp() {
+ mMockInputManagers.add(mInputManager);
+
+ mCaptionWindowDecorViewModel =
+ new CaptionWindowDecorViewModel(
+ mContext,
+ mMainHandler,
+ mMainChoreographer,
+ mTaskOrganizer,
+ mDisplayController,
+ mSyncQueue,
+ mDesktopModeController,
+ mCaptionWindowDecorFactory,
+ new MockObjectSupplier<>(mMockInputManagers, () -> mock(InputManager.class)));
+ mCaptionWindowDecorViewModel.setEventReceiverFactory(mEventReceiverFactory);
+
+ doReturn(mCaptionWindowDecoration)
+ .when(mCaptionWindowDecorFactory)
+ .create(any(), any(), any(), any(), any(), any(), any(), any());
+
+ when(mInputManager.monitorGestureInput(any(), anyInt())).thenReturn(mInputMonitor);
+ when(mEventReceiverFactory.create(any(), any())).thenReturn(mEventReceiver);
+ when(mInputMonitor.getInputChannel()).thenReturn(mInputChannel);
+ }
+
+ @Test
+ public void testDeleteCaptionOnChangeTransitionWhenNecessary() throws Exception {
+ Looper.prepare();
+ final int taskId = 1;
+ final ActivityManager.RunningTaskInfo taskInfo =
+ createTaskInfo(taskId, WINDOWING_MODE_FREEFORM);
+ SurfaceControl surfaceControl = mock(SurfaceControl.class);
+ final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
+ GrantPermissionRule.grant(android.Manifest.permission.MONITOR_INPUT);
+
+ mCaptionWindowDecorViewModel.onTaskOpening(taskInfo, surfaceControl, startT, finishT);
+ verify(mCaptionWindowDecorFactory)
+ .create(
+ mContext,
+ mDisplayController,
+ mTaskOrganizer,
+ taskInfo,
+ surfaceControl,
+ mMainHandler,
+ mMainChoreographer,
+ mSyncQueue);
+
+ taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_UNDEFINED);
+ taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
+ mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT);
+ verify(mCaptionWindowDecoration).close();
+ }
+
+ @Test
+ public void testCreateCaptionOnChangeTransitionWhenNecessary() throws Exception {
+ final int taskId = 1;
+ final ActivityManager.RunningTaskInfo taskInfo =
+ createTaskInfo(taskId, WINDOWING_MODE_UNDEFINED);
+ SurfaceControl surfaceControl = mock(SurfaceControl.class);
+ final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
+ taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
+
+ mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT);
+
+ verify(mCaptionWindowDecorFactory, never())
+ .create(
+ mContext,
+ mDisplayController,
+ mTaskOrganizer,
+ taskInfo,
+ surfaceControl,
+ mMainHandler,
+ mMainChoreographer,
+ mSyncQueue);
+
+ taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD);
+
+ mCaptionWindowDecorViewModel.onTaskChanging(taskInfo, surfaceControl, startT, finishT);
+
+ verify(mCaptionWindowDecorFactory)
+ .create(
+ mContext,
+ mDisplayController,
+ mTaskOrganizer,
+ taskInfo,
+ surfaceControl,
+ mMainHandler,
+ mMainChoreographer,
+ mSyncQueue);
+ }
+
+ private static ActivityManager.RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
+ ActivityManager.RunningTaskInfo taskInfo =
+ new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setVisible(true)
+ .build();
+ taskInfo.taskId = taskId;
+ taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
+ return taskInfo;
+ }
+
+ private static class MockObjectSupplier<T> implements Supplier<T> {
+ private final List<T> mObjects;
+ private final Supplier<T> mDefaultSupplier;
+ private int mNumOfCalls = 0;
+
+ private MockObjectSupplier(List<T> objects, Supplier<T> defaultSupplier) {
+ mObjects = objects;
+ mDefaultSupplier = defaultSupplier;
+ }
+
+ @Override
+ public T get() {
+ final T mock =
+ mNumOfCalls < mObjects.size() ? mObjects.get(mNumOfCalls)
+ : mDefaultSupplier.get();
+ ++mNumOfCalls;
+ return mock;
+ }
+ }
+}
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 15181b1..dd9ab98 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
@@ -113,6 +113,12 @@
mMockSurfaceControlFinishT = createMockSurfaceControlTransaction();
mMockSurfaceControlAddWindowT = createMockSurfaceControlTransaction();
+ mRelayoutParams.mLayoutResId = 0;
+ mRelayoutParams.mCaptionHeightId = R.dimen.test_freeform_decor_caption_height;
+ // Caption should have fixed width except in testLayoutResultCalculation_fullWidthCaption()
+ mRelayoutParams.mCaptionWidthId = R.dimen.test_freeform_decor_caption_width;
+ mRelayoutParams.mShadowRadiusId = R.dimen.test_window_decor_shadow_radius;
+
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
.create(any(), any(), any());
}
@@ -435,6 +441,58 @@
assertThat(additionalWindow.mWindowSurface).isNull();
}
+ @Test
+ public void testLayoutResultCalculation_fullWidthCaption() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+
+ final SurfaceControl decorContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder decorContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(decorContainerSurface);
+ mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder);
+ final SurfaceControl taskBackgroundSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder taskBackgroundSurfaceBuilder =
+ createMockSurfaceControlBuilder(taskBackgroundSurface);
+ mMockSurfaceControlBuilders.add(taskBackgroundSurfaceBuilder);
+ final SurfaceControl captionContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder captionContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(captionContainerSurface);
+ mMockSurfaceControlBuilders.add(captionContainerSurfaceBuilder);
+
+ final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
+ mMockSurfaceControlTransactions.add(t);
+ final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
+ new ActivityManager.TaskDescription.Builder()
+ .setBackgroundColor(Color.YELLOW);
+ final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setTaskDescriptionBuilder(taskDescriptionBuilder)
+ .setBounds(TASK_BOUNDS)
+ .setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y)
+ .setVisible(true)
+ .build();
+ taskInfo.isFocused = true;
+ taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
+ mRelayoutParams.setOutsets(
+ R.dimen.test_window_decor_left_outset,
+ R.dimen.test_window_decor_top_outset,
+ R.dimen.test_window_decor_right_outset,
+ R.dimen.test_window_decor_bottom_outset);
+ final SurfaceControl taskSurface = mock(SurfaceControl.class);
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+
+ mRelayoutParams.mCaptionWidthId = Resources.ID_NULL;
+ windowDecor.relayout(taskInfo);
+
+ verify(captionContainerSurfaceBuilder).setParent(decorContainerSurface);
+ verify(captionContainerSurfaceBuilder).setContainerLayer();
+ verify(mMockSurfaceControlStartT).setPosition(captionContainerSurface, 20, 40);
+ // Width of the captionContainerSurface should match the width of TASK_BOUNDS
+ verify(mMockSurfaceControlStartT).setWindowCrop(captionContainerSurface, 300, 64);
+ verify(mMockSurfaceControlStartT).show(captionContainerSurface);
+ }
+
private TestWindowDecoration createWindowDecoration(
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
return new TestWindowDecoration(InstrumentationRegistry.getInstrumentation().getContext(),
@@ -490,11 +548,6 @@
@Override
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
- mRelayoutParams.mLayoutResId = 0;
- mRelayoutParams.mCaptionHeightId = R.dimen.test_freeform_decor_caption_height;
- mRelayoutParams.mCaptionWidthId = R.dimen.test_freeform_decor_caption_width;
- mRelayoutParams.mShadowRadiusId = R.dimen.test_window_decor_shadow_radius;
-
relayout(mRelayoutParams, mMockSurfaceControlStartT, mMockSurfaceControlFinishT,
mMockWindowContainerTransaction, mMockView, mRelayoutResult);
}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 88cfed9..3e3d77b 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -340,6 +340,8 @@
"jni/Graphics.cpp",
"jni/ImageDecoder.cpp",
"jni/Interpolator.cpp",
+ "jni/MeshSpecification.cpp",
+ "jni/Mesh.cpp",
"jni/MaskFilter.cpp",
"jni/NinePatch.cpp",
"jni/NinePatchPeeker.cpp",
@@ -570,6 +572,7 @@
"renderthread/VulkanSurface.cpp",
"renderthread/RenderProxy.cpp",
"renderthread/RenderThread.cpp",
+ "renderthread/HintSessionWrapper.cpp",
"service/GraphicsStatsService.cpp",
"thread/CommonPool.cpp",
"utils/GLUtils.cpp",
diff --git a/libs/hwui/CanvasTransform.cpp b/libs/hwui/CanvasTransform.cpp
index 673041a..cd4fae8 100644
--- a/libs/hwui/CanvasTransform.cpp
+++ b/libs/hwui/CanvasTransform.cpp
@@ -17,6 +17,7 @@
#include "CanvasTransform.h"
#include <SkAndroidFrameworkUtils.h>
+#include <SkBlendMode.h>
#include <SkColorFilter.h>
#include <SkGradientShader.h>
#include <SkHighContrastFilter.h>
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 9a4c550..a7f8f61 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -16,6 +16,7 @@
#pragma once
+#include <SkBlendMode.h>
#include <SkColorFilter.h>
#include <SkImage.h>
#include <SkMatrix.h>
diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in
index 4ec782f..e2127ef 100644
--- a/libs/hwui/DisplayListOps.in
+++ b/libs/hwui/DisplayListOps.in
@@ -52,3 +52,4 @@
X(DrawVectorDrawable)
X(DrawRippleDrawable)
X(DrawWebView)
+X(DrawMesh)
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index 564ee4f..b15b6cb 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -104,6 +104,7 @@
set(FrameInfoIndex::AnimationStart) = vsyncTime;
set(FrameInfoIndex::PerformTraversalsStart) = vsyncTime;
set(FrameInfoIndex::DrawStart) = vsyncTime;
+ set(FrameInfoIndex::FrameStartTime) = vsyncTime;
set(FrameInfoIndex::FrameDeadline) = frameDeadline;
set(FrameInfoIndex::FrameInterval) = frameInterval;
return *this;
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 9053c12..fc3118a 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -20,6 +20,8 @@
#include "utils/Color.h"
#include "utils/MathUtils.h"
+#include <SkBlendMode.h>
+
#include <log/log.h>
namespace android {
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index f5ebfd5..3f21940 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -15,13 +15,16 @@
*/
#include "RecordingCanvas.h"
-#include <hwui/Paint.h>
#include <GrRecordingContext.h>
+#include <SkMesh.h>
+#include <hwui/Paint.h>
#include <experimental/type_traits>
+#include <utility>
#include "SkAndroidFrameworkUtils.h"
+#include "SkBlendMode.h"
#include "SkCanvas.h"
#include "SkCanvasPriv.h"
#include "SkColor.h"
@@ -270,7 +273,6 @@
SkPaint paint;
void draw(SkCanvas* c, const SkMatrix&) const { c->drawDRRect(outer, inner, paint); }
};
-
struct DrawAnnotation final : Op {
static const auto kType = Type::DrawAnnotation;
DrawAnnotation(const SkRect& rect, SkData* value) : rect(rect), value(sk_ref_sp(value)) {}
@@ -452,6 +454,16 @@
c->drawVertices(vertices, mode, paint);
}
};
+struct DrawMesh final : Op {
+ static const auto kType = Type::DrawMesh;
+ DrawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint)
+ : mesh(mesh), blender(std::move(blender)), paint(paint) {}
+
+ SkMesh mesh;
+ sk_sp<SkBlender> blender;
+ SkPaint paint;
+ void draw(SkCanvas* c, const SkMatrix&) const { c->drawMesh(mesh, blender, paint); }
+};
struct DrawAtlas final : Op {
static const auto kType = Type::DrawAtlas;
DrawAtlas(const SkImage* atlas, int count, SkBlendMode mode, const SkSamplingOptions& sampling,
@@ -763,6 +775,10 @@
void DisplayListData::drawVertices(const SkVertices* vert, SkBlendMode mode, const SkPaint& paint) {
this->push<DrawVertices>(0, vert, mode, paint);
}
+void DisplayListData::drawMesh(const SkMesh& mesh, const sk_sp<SkBlender>& blender,
+ const SkPaint& paint) {
+ this->push<DrawMesh>(0, mesh, blender, paint);
+}
void DisplayListData::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[],
const SkColor colors[], int count, SkBlendMode xfermode,
const SkSamplingOptions& sampling, const SkRect* cull,
@@ -1105,6 +1121,10 @@
SkBlendMode mode, const SkPaint& paint) {
fDL->drawVertices(vertices, mode, paint);
}
+void RecordingCanvas::onDrawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender,
+ const SkPaint& paint) {
+ fDL->drawMesh(mesh, blender, paint);
+}
void RecordingCanvas::onDrawAtlas2(const SkImage* atlas, const SkRSXform xforms[],
const SkRect texs[], const SkColor colors[], int count,
SkBlendMode bmode, const SkSamplingOptions& sampling,
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 35bec93..2539694 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -34,6 +34,7 @@
#include <SkRuntimeEffect.h>
#include <vector>
+enum class SkBlendMode;
class SkRRect;
namespace android {
@@ -111,6 +112,8 @@
void drawRRect(const SkRRect&, const SkPaint&);
void drawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
+ void drawMesh(const SkMesh&, const sk_sp<SkBlender>&, const SkPaint&);
+
void drawAnnotation(const SkRect&, const char*, SkData*);
void drawDrawable(SkDrawable*, const SkMatrix*);
void drawPicture(const SkPicture*, const SkMatrix*, const SkPaint*);
@@ -210,6 +213,7 @@
const SkPaint&) override;
void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;
void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;
+ void onDrawMesh(const SkMesh&, sk_sp<SkBlender>, const SkPaint&) override;
void onDrawAtlas2(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int,
SkBlendMode, const SkSamplingOptions&, const SkRect*, const SkPaint*) override;
void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 473afbd..d83d78f 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -570,6 +570,10 @@
applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawVertices(vertices, mode, p); });
}
+void SkiaCanvas::drawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint) {
+ mCanvas->drawMesh(mesh, blender, paint);
+}
+
// ----------------------------------------------------------------------------
// Canvas draw operations: Bitmaps
// ----------------------------------------------------------------------------
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 51007c5..31e3b4c 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -33,6 +33,7 @@
#include <cassert>
#include <optional>
+enum class SkBlendMode;
class SkRRect;
namespace android {
@@ -119,8 +120,8 @@
virtual void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
const Paint& paint) override;
- virtual void drawDoubleRoundRect(const SkRRect& outer, const SkRRect& inner,
- const Paint& paint) override;
+ virtual void drawDoubleRoundRect(const SkRRect& outer, const SkRRect& inner,
+ const Paint& paint) override;
virtual void drawCircle(float x, float y, float radius, const Paint& paint) override;
virtual void drawOval(float left, float top, float right, float bottom,
@@ -129,6 +130,8 @@
float sweepAngle, bool useCenter, const Paint& paint) override;
virtual void drawPath(const SkPath& path, const Paint& paint) override;
virtual void drawVertices(const SkVertices*, SkBlendMode, const Paint& paint) override;
+ virtual void drawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender,
+ const SkPaint& paint) override;
virtual void drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) override;
virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const Paint* paint) override;
diff --git a/libs/hwui/apex/android_paint.cpp b/libs/hwui/apex/android_paint.cpp
index 70bd085..cc79cba 100644
--- a/libs/hwui/apex/android_paint.cpp
+++ b/libs/hwui/apex/android_paint.cpp
@@ -19,6 +19,7 @@
#include "TypeCast.h"
#include <hwui/Paint.h>
+#include <SkBlendMode.h>
using namespace android;
diff --git a/libs/hwui/apex/jni_runtime.cpp b/libs/hwui/apex/jni_runtime.cpp
index 39725a5..e6cfa7b 100644
--- a/libs/hwui/apex/jni_runtime.cpp
+++ b/libs/hwui/apex/jni_runtime.cpp
@@ -76,6 +76,8 @@
extern int register_android_graphics_text_MeasuredText(JNIEnv* env);
extern int register_android_graphics_text_LineBreaker(JNIEnv *env);
extern int register_android_graphics_text_TextShaper(JNIEnv *env);
+extern int register_android_graphics_MeshSpecification(JNIEnv* env);
+extern int register_android_graphics_Mesh(JNIEnv* env);
extern int register_android_util_PathParser(JNIEnv* env);
extern int register_android_view_DisplayListCanvas(JNIEnv* env);
@@ -143,6 +145,8 @@
REG_JNI(register_android_graphics_text_MeasuredText),
REG_JNI(register_android_graphics_text_LineBreaker),
REG_JNI(register_android_graphics_text_TextShaper),
+ REG_JNI(register_android_graphics_MeshSpecification),
+ REG_JNI(register_android_graphics_Mesh),
REG_JNI(register_android_util_PathParser),
REG_JNI(register_android_view_RenderNode),
diff --git a/libs/hwui/hwui/BlurDrawLooper.cpp b/libs/hwui/hwui/BlurDrawLooper.cpp
index d4b0198..8b52551 100644
--- a/libs/hwui/hwui/BlurDrawLooper.cpp
+++ b/libs/hwui/hwui/BlurDrawLooper.cpp
@@ -15,6 +15,7 @@
*/
#include "BlurDrawLooper.h"
+#include <SkBlurTypes.h>
#include <SkColorSpace.h>
#include <SkMaskFilter.h>
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 82d23b5..2a20191 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -30,6 +30,7 @@
#include <SkMatrix.h>
class SkAnimatedImage;
+enum class SkBlendMode;
class SkCanvasState;
class SkRRect;
class SkRuntimeShaderBuilder;
@@ -226,6 +227,7 @@
float sweepAngle, bool useCenter, const Paint& paint) = 0;
virtual void drawPath(const SkPath& path, const Paint& paint) = 0;
virtual void drawVertices(const SkVertices*, SkBlendMode, const Paint& paint) = 0;
+ virtual void drawMesh(const SkMesh& mesh, sk_sp<SkBlender>, const SkPaint& paint) = 0;
// Bitmap-based
virtual void drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) = 0;
diff --git a/libs/hwui/jni/ColorFilter.cpp b/libs/hwui/jni/ColorFilter.cpp
index cef21f9..4bd7ef4 100644
--- a/libs/hwui/jni/ColorFilter.cpp
+++ b/libs/hwui/jni/ColorFilter.cpp
@@ -17,6 +17,7 @@
#include "GraphicsJNI.h"
+#include "SkBlendMode.h"
#include "SkColorFilter.h"
#include "SkColorMatrixFilter.h"
diff --git a/libs/hwui/jni/MaskFilter.cpp b/libs/hwui/jni/MaskFilter.cpp
index 5383032..048ce02 100644
--- a/libs/hwui/jni/MaskFilter.cpp
+++ b/libs/hwui/jni/MaskFilter.cpp
@@ -2,6 +2,7 @@
#include "SkMaskFilter.h"
#include "SkBlurMask.h"
#include "SkBlurMaskFilter.h"
+#include "SkBlurTypes.h"
#include "SkTableMaskFilter.h"
static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) {
diff --git a/libs/hwui/jni/Mesh.cpp b/libs/hwui/jni/Mesh.cpp
index 6dba6c1..109aac3 100644
--- a/libs/hwui/jni/Mesh.cpp
+++ b/libs/hwui/jni/Mesh.cpp
@@ -42,7 +42,7 @@
jint right, jint bottom) {
auto skMeshSpec = sk_ref_sp(reinterpret_cast<SkMeshSpecification*>(meshSpec));
sk_sp<SkMesh::VertexBuffer> skVertexBuffer =
- genVertexBuffer(env, vertexBuffer, skMeshSpec->attributes().size_bytes(), isDirect);
+ genVertexBuffer(env, vertexBuffer, vertexCount * skMeshSpec->stride(), isDirect);
auto skRect = SkRect::MakeLTRB(left, top, right, bottom);
auto mesh = SkMesh::Make(skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount,
vertexOffset, nullptr, skRect);
@@ -55,8 +55,8 @@
jobject indexBuffer, jboolean isIndexDirect, jint indexCount,
jint indexOffset, jint left, jint top, jint right, jint bottom) {
auto skMeshSpec = sk_ref_sp(reinterpret_cast<SkMeshSpecification*>(meshSpec));
- sk_sp<SkMesh::VertexBuffer> skVertexBuffer = genVertexBuffer(
- env, vertexBuffer, skMeshSpec->attributes().size_bytes(), isVertexDirect);
+ sk_sp<SkMesh::VertexBuffer> skVertexBuffer =
+ genVertexBuffer(env, vertexBuffer, vertexCount * skMeshSpec->stride(), isVertexDirect);
sk_sp<SkMesh::IndexBuffer> skIndexBuffer =
genIndexBuffer(env, indexBuffer, indexCount * gIndexByteSize, isIndexDirect);
auto skRect = SkRect::MakeLTRB(left, top, right, bottom);
diff --git a/libs/hwui/jni/MeshSpecification.cpp b/libs/hwui/jni/MeshSpecification.cpp
index 22fa4d3..619a3ed 100644
--- a/libs/hwui/jni/MeshSpecification.cpp
+++ b/libs/hwui/jni/MeshSpecification.cpp
@@ -50,7 +50,6 @@
SkString(attName.c_str())};
attVector.push_back(std::move(temp));
}
-
return attVector;
}
@@ -76,11 +75,15 @@
auto varyings = extractVaryings(env, varyingArray);
auto skVertexShader = ScopedUtfChars(env, vertexShader);
auto skFragmentShader = ScopedUtfChars(env, fragmentShader);
- auto meshSpec = SkMeshSpecification::Make(attributes, vertexStride, varyings,
- SkString(skVertexShader.c_str()),
- SkString(skFragmentShader.c_str()))
- .specification;
- return reinterpret_cast<jlong>(meshSpec.release());
+ auto meshSpecResult = SkMeshSpecification::Make(attributes, vertexStride, varyings,
+ SkString(skVertexShader.c_str()),
+ SkString(skFragmentShader.c_str()));
+
+ if (meshSpecResult.specification.get() == nullptr) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", meshSpecResult.error.c_str());
+ }
+
+ return reinterpret_cast<jlong>(meshSpecResult.specification.release());
}
static jlong MakeWithCS(JNIEnv* env, jobject thiz, jobjectArray attributeArray, jint vertexStride,
@@ -90,13 +93,15 @@
auto varyings = extractVaryings(env, varyingArray);
auto skVertexShader = ScopedUtfChars(env, vertexShader);
auto skFragmentShader = ScopedUtfChars(env, fragmentShader);
- auto meshSpec = SkMeshSpecification::Make(attributes, vertexStride, varyings,
- SkString(skVertexShader.c_str()),
- SkString(skFragmentShader.c_str()),
- GraphicsJNI::getNativeColorSpace(colorSpace))
- .specification;
+ auto meshSpecResult = SkMeshSpecification::Make(
+ attributes, vertexStride, varyings, SkString(skVertexShader.c_str()),
+ SkString(skFragmentShader.c_str()), GraphicsJNI::getNativeColorSpace(colorSpace));
- return reinterpret_cast<jlong>(meshSpec.release());
+ if (meshSpecResult.specification.get() == nullptr) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", meshSpecResult.error.c_str());
+ }
+
+ return reinterpret_cast<jlong>(meshSpecResult.specification.release());
}
static jlong MakeWithAlpha(JNIEnv* env, jobject thiz, jobjectArray attributeArray,
@@ -106,12 +111,16 @@
auto varyings = extractVaryings(env, varyingArray);
auto skVertexShader = ScopedUtfChars(env, vertexShader);
auto skFragmentShader = ScopedUtfChars(env, fragmentShader);
- auto meshSpec = SkMeshSpecification::Make(
- attributes, vertexStride, varyings, SkString(skVertexShader.c_str()),
- SkString(skFragmentShader.c_str()),
- GraphicsJNI::getNativeColorSpace(colorSpace), SkAlphaType(alphaType))
- .specification;
- return reinterpret_cast<jlong>(meshSpec.release());
+ auto meshSpecResult = SkMeshSpecification::Make(
+ attributes, vertexStride, varyings, SkString(skVertexShader.c_str()),
+ SkString(skFragmentShader.c_str()), GraphicsJNI::getNativeColorSpace(colorSpace),
+ SkAlphaType(alphaType));
+
+ if (meshSpecResult.specification.get() == nullptr) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", meshSpecResult.error.c_str());
+ }
+
+ return reinterpret_cast<jlong>(meshSpecResult.specification.release());
}
static void MeshSpecification_safeUnref(SkMeshSpecification* meshSpec) {
@@ -153,4 +162,4 @@
return 0;
}
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/hwui/jni/RenderEffect.cpp b/libs/hwui/jni/RenderEffect.cpp
index 213f35a..f3db170 100644
--- a/libs/hwui/jni/RenderEffect.cpp
+++ b/libs/hwui/jni/RenderEffect.cpp
@@ -15,6 +15,7 @@
*/
#include "Bitmap.h"
#include "GraphicsJNI.h"
+#include "SkBlendMode.h"
#include "SkImageFilter.h"
#include "SkImageFilters.h"
#include "graphics_jni_helpers.h"
diff --git a/libs/hwui/jni/android_graphics_Canvas.cpp b/libs/hwui/jni/android_graphics_Canvas.cpp
index 0513447..8a4d4e1 100644
--- a/libs/hwui/jni/android_graphics_Canvas.cpp
+++ b/libs/hwui/jni/android_graphics_Canvas.cpp
@@ -21,6 +21,7 @@
#else
#define __ANDROID_API_P__ 28
#endif
+#include <Mesh.h>
#include <androidfw/ResourceTypes.h>
#include <hwui/Canvas.h>
#include <hwui/Paint.h>
@@ -30,8 +31,8 @@
#include <nativehelper/ScopedPrimitiveArray.h>
#include <nativehelper/ScopedStringChars.h>
-#include "FontUtils.h"
#include "Bitmap.h"
+#include "FontUtils.h"
#include "SkBitmap.h"
#include "SkBlendMode.h"
#include "SkClipOp.h"
@@ -42,10 +43,10 @@
#include "SkMatrix.h"
#include "SkPath.h"
#include "SkPoint.h"
+#include "SkRRect.h"
#include "SkRect.h"
#include "SkRefCnt.h"
#include "SkRegion.h"
-#include "SkRRect.h"
#include "SkScalar.h"
#include "SkVertices.h"
@@ -443,6 +444,14 @@
blendMode, *paint);
}
+static void drawMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong meshHandle, jint modeHandle,
+ jlong paintHandle) {
+ const SkMesh mesh = reinterpret_cast<MeshWrapper*>(meshHandle)->mesh;
+ SkBlendMode blendMode = static_cast<SkBlendMode>(modeHandle);
+ SkPaint* paint = reinterpret_cast<Paint*>(paintHandle);
+ get_canvas(canvasHandle)->drawMesh(mesh, SkBlender::Mode(blendMode), *paint);
+}
+
static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
jlong chunkHandle, jfloat left, jfloat top, jfloat right, jfloat bottom,
jlong paintHandle, jint dstDensity, jint srcDensity) {
@@ -761,38 +770,38 @@
// If called from Canvas these are regular JNI
// If called from DisplayListCanvas they are @FastNative
static const JNINativeMethod gDrawMethods[] = {
- {"nDrawColor","(JII)V", (void*) CanvasJNI::drawColor},
- {"nDrawColor","(JJJI)V", (void*) CanvasJNI::drawColorLong},
- {"nDrawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
- {"nDrawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
- {"nDrawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
- {"nDrawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
- {"nDrawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
- {"nDrawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
- {"nDrawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
- {"nDrawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
- {"nDrawDoubleRoundRect", "(JFFFFFFFFFFFFJ)V", (void*) CanvasJNI::drawDoubleRoundRectXY},
- {"nDrawDoubleRoundRect", "(JFFFF[FFFFF[FJ)V", (void*) CanvasJNI::drawDoubleRoundRectRadii},
- {"nDrawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
- {"nDrawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
- {"nDrawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
- {"nDrawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
- {"nDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
- {"nDrawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
- {"nDrawBitmapMatrix", "(JJJJ)V", (void*)CanvasJNI::drawBitmapMatrix},
- {"nDrawBitmapMesh", "(JJII[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
- {"nDrawBitmap","(JJFFJIII)V", (void*) CanvasJNI::drawBitmap},
- {"nDrawBitmap","(JJFFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
- {"nDrawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
- {"nDrawGlyphs", "(J[I[FIIIJJ)V", (void*)CanvasJNI::drawGlyphs},
- {"nDrawText","(J[CIIFFIJ)V", (void*) CanvasJNI::drawTextChars},
- {"nDrawText","(JLjava/lang/String;IIFFIJ)V", (void*) CanvasJNI::drawTextString},
- {"nDrawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
- {"nDrawTextRun","(JLjava/lang/String;IIIIFFZJ)V", (void*) CanvasJNI::drawTextRunString},
- {"nDrawTextOnPath","(J[CIIJFFIJ)V", (void*) CanvasJNI::drawTextOnPathChars},
- {"nDrawTextOnPath","(JLjava/lang/String;JFFIJ)V", (void*) CanvasJNI::drawTextOnPathString},
- {"nPunchHole", "(JFFFFFFF)V", (void*) CanvasJNI::punchHole}
-};
+ {"nDrawColor", "(JII)V", (void*)CanvasJNI::drawColor},
+ {"nDrawColor", "(JJJI)V", (void*)CanvasJNI::drawColorLong},
+ {"nDrawPaint", "(JJ)V", (void*)CanvasJNI::drawPaint},
+ {"nDrawPoint", "(JFFJ)V", (void*)CanvasJNI::drawPoint},
+ {"nDrawPoints", "(J[FIIJ)V", (void*)CanvasJNI::drawPoints},
+ {"nDrawLine", "(JFFFFJ)V", (void*)CanvasJNI::drawLine},
+ {"nDrawLines", "(J[FIIJ)V", (void*)CanvasJNI::drawLines},
+ {"nDrawRect", "(JFFFFJ)V", (void*)CanvasJNI::drawRect},
+ {"nDrawRegion", "(JJJ)V", (void*)CanvasJNI::drawRegion},
+ {"nDrawRoundRect", "(JFFFFFFJ)V", (void*)CanvasJNI::drawRoundRect},
+ {"nDrawDoubleRoundRect", "(JFFFFFFFFFFFFJ)V", (void*)CanvasJNI::drawDoubleRoundRectXY},
+ {"nDrawDoubleRoundRect", "(JFFFF[FFFFF[FJ)V", (void*)CanvasJNI::drawDoubleRoundRectRadii},
+ {"nDrawCircle", "(JFFFJ)V", (void*)CanvasJNI::drawCircle},
+ {"nDrawOval", "(JFFFFJ)V", (void*)CanvasJNI::drawOval},
+ {"nDrawArc", "(JFFFFFFZJ)V", (void*)CanvasJNI::drawArc},
+ {"nDrawPath", "(JJJ)V", (void*)CanvasJNI::drawPath},
+ {"nDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
+ {"nDrawMesh", "(JJIJ)V", (void*)CanvasJNI::drawMesh},
+ {"nDrawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
+ {"nDrawBitmapMatrix", "(JJJJ)V", (void*)CanvasJNI::drawBitmapMatrix},
+ {"nDrawBitmapMesh", "(JJII[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
+ {"nDrawBitmap", "(JJFFJIII)V", (void*)CanvasJNI::drawBitmap},
+ {"nDrawBitmap", "(JJFFFFFFFFJII)V", (void*)CanvasJNI::drawBitmapRect},
+ {"nDrawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
+ {"nDrawGlyphs", "(J[I[FIIIJJ)V", (void*)CanvasJNI::drawGlyphs},
+ {"nDrawText", "(J[CIIFFIJ)V", (void*)CanvasJNI::drawTextChars},
+ {"nDrawText", "(JLjava/lang/String;IIFFIJ)V", (void*)CanvasJNI::drawTextString},
+ {"nDrawTextRun", "(J[CIIIIFFZJJ)V", (void*)CanvasJNI::drawTextRunChars},
+ {"nDrawTextRun", "(JLjava/lang/String;IIIIFFZJ)V", (void*)CanvasJNI::drawTextRunString},
+ {"nDrawTextOnPath", "(J[CIIJFFIJ)V", (void*)CanvasJNI::drawTextOnPathChars},
+ {"nDrawTextOnPath", "(JLjava/lang/String;JFFIJ)V", (void*)CanvasJNI::drawTextOnPathString},
+ {"nPunchHole", "(JFFFFFFF)V", (void*)CanvasJNI::punchHole}};
int register_android_graphics_Canvas(JNIEnv* env) {
int ret = 0;
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.h b/libs/hwui/pipeline/skia/RenderNodeDrawable.h
index 6c390c3..c7582e7 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.h
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.h
@@ -18,6 +18,7 @@
#include "SkiaUtils.h"
+#include <SkBlendMode.h>
#include <SkCanvas.h>
#include <SkDrawable.h>
#include <SkMatrix.h>
diff --git a/libs/hwui/pipeline/skia/StretchMask.cpp b/libs/hwui/pipeline/skia/StretchMask.cpp
index 2dbeb3a..b169c92 100644
--- a/libs/hwui/pipeline/skia/StretchMask.cpp
+++ b/libs/hwui/pipeline/skia/StretchMask.cpp
@@ -14,8 +14,10 @@
* limitations under the License.
*/
#include "StretchMask.h"
-#include "SkSurface.h"
+
+#include "SkBlendMode.h"
#include "SkCanvas.h"
+#include "SkSurface.h"
#include "TransformCanvas.h"
#include "SkiaDisplayList.h"
diff --git a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
index 3c7617d..e168a7b 100644
--- a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
@@ -33,6 +33,8 @@
#include "thread/ThreadBase.h"
#include "utils/TimeUtils.h"
+#include <SkBlendMode.h>
+
namespace android {
namespace uirenderer {
namespace skiapipeline {
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index 1d24e71..1c76884 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -98,7 +98,6 @@
auto& cache = skiapipeline::ShaderCache::get();
cache.initShaderDiskCache(identity, size);
contextOptions->fPersistentCache = &cache;
- contextOptions->fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
}
void CacheManager::trimMemory(TrimLevel mode) {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index d09bc47..64839d0 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -71,16 +71,19 @@
} /* namespace */
CanvasContext* CanvasContext::create(RenderThread& thread, bool translucent,
- RenderNode* rootRenderNode, IContextFactory* contextFactory) {
+ RenderNode* rootRenderNode, IContextFactory* contextFactory,
+ int32_t uiThreadId, int32_t renderThreadId) {
auto renderType = Properties::getRenderPipelineType();
switch (renderType) {
case RenderPipelineType::SkiaGL:
return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
- std::make_unique<skiapipeline::SkiaOpenGLPipeline>(thread));
+ std::make_unique<skiapipeline::SkiaOpenGLPipeline>(thread),
+ uiThreadId, renderThreadId);
case RenderPipelineType::SkiaVulkan:
return new CanvasContext(thread, translucent, rootRenderNode, contextFactory,
- std::make_unique<skiapipeline::SkiaVulkanPipeline>(thread));
+ std::make_unique<skiapipeline::SkiaVulkanPipeline>(thread),
+ uiThreadId, renderThreadId);
default:
LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
@@ -110,7 +113,8 @@
CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
IContextFactory* contextFactory,
- std::unique_ptr<IRenderPipeline> renderPipeline)
+ std::unique_ptr<IRenderPipeline> renderPipeline, pid_t uiThreadId,
+ pid_t renderThreadId)
: mRenderThread(thread)
, mGenerationID(0)
, mOpaque(!translucent)
@@ -118,7 +122,8 @@
, mJankTracker(&thread.globalProfileData())
, mProfiler(mJankTracker.frames(), thread.timeLord().frameIntervalNanos())
, mContentDrawBounds(0, 0, 0, 0)
- , mRenderPipeline(std::move(renderPipeline)) {
+ , mRenderPipeline(std::move(renderPipeline))
+ , mHintSessionWrapper(uiThreadId, renderThreadId) {
mRenderThread.cacheManager().registerCanvasContext(this);
rootRenderNode->makeRoot();
mRenderNodes.emplace_back(rootRenderNode);
@@ -472,16 +477,22 @@
mRenderThread.pushBackFrameCallback(this);
}
-std::optional<nsecs_t> CanvasContext::draw() {
+void CanvasContext::draw() {
if (auto grContext = getGrContext()) {
if (grContext->abandoned()) {
LOG_ALWAYS_FATAL("GrContext is abandoned/device lost at start of CanvasContext::draw");
- return std::nullopt;
+ return;
}
}
SkRect dirty;
mDamageAccumulator.finish(&dirty);
+ // reset syncDelayDuration each time we draw
+ nsecs_t syncDelayDuration = mSyncDelayDuration;
+ nsecs_t idleDuration = mIdleDuration;
+ mSyncDelayDuration = 0;
+ mIdleDuration = 0;
+
if (!Properties::isDrawingEnabled() ||
(dirty.isEmpty() && Properties::skipEmptyFrames && !surfaceRequiresRedraw())) {
mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
@@ -498,7 +509,7 @@
std::invoke(func, false /* didProduceBuffer */);
}
mFrameCommitCallbacks.clear();
- return std::nullopt;
+ return;
}
ScopedActiveContext activeContext(this);
@@ -650,10 +661,25 @@
}
}
+ int64_t intendedVsync = mCurrentFrameInfo->get(FrameInfoIndex::IntendedVsync);
+ int64_t frameDeadline = mCurrentFrameInfo->get(FrameInfoIndex::FrameDeadline);
+ int64_t dequeueBufferDuration = mCurrentFrameInfo->get(FrameInfoIndex::DequeueBufferDuration);
+
+ mHintSessionWrapper.updateTargetWorkDuration(frameDeadline - intendedVsync);
+
+ if (didDraw) {
+ int64_t frameStartTime = mCurrentFrameInfo->get(FrameInfoIndex::FrameStartTime);
+ int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime;
+ int64_t actualDuration = frameDuration -
+ (std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
+ dequeueBufferDuration - idleDuration;
+ mHintSessionWrapper.reportActualWorkDuration(actualDuration);
+ }
+
+ mLastDequeueBufferDuration = dequeueBufferDuration;
+
mRenderThread.cacheManager().onFrameCompleted();
- return didDraw ? std::make_optional(
- mCurrentFrameInfo->get(FrameInfoIndex::DequeueBufferDuration))
- : std::nullopt;
+ return;
}
void CanvasContext::reportMetricsWithPresentTime() {
@@ -766,6 +792,8 @@
// Called by choreographer to do an RT-driven animation
void CanvasContext::doFrame() {
if (!mRenderPipeline->isSurfaceReady()) return;
+ mIdleDuration =
+ systemTime(SYSTEM_TIME_MONOTONIC) - mRenderThread.timeLord().computeFrameTimeNanos();
prepareAndDraw(nullptr);
}
@@ -974,6 +1002,14 @@
}
}
+void CanvasContext::sendLoadResetHint() {
+ mHintSessionWrapper.sendLoadResetHint();
+}
+
+void CanvasContext::setSyncDelayDuration(nsecs_t duration) {
+ mSyncDelayDuration = duration;
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index db96cfb..e875c42 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -16,22 +16,6 @@
#pragma once
-#include "DamageAccumulator.h"
-#include "FrameInfo.h"
-#include "FrameInfoVisualizer.h"
-#include "FrameMetricsReporter.h"
-#include "IContextFactory.h"
-#include "IRenderPipeline.h"
-#include "JankTracker.h"
-#include "LayerUpdateQueue.h"
-#include "Lighting.h"
-#include "ReliableSurface.h"
-#include "RenderNode.h"
-#include "renderthread/RenderTask.h"
-#include "renderthread/RenderThread.h"
-#include "utils/RingBuffer.h"
-#include "ColorMode.h"
-
#include <SkBitmap.h>
#include <SkRect.h>
#include <SkSize.h>
@@ -46,6 +30,23 @@
#include <utility>
#include <vector>
+#include "ColorMode.h"
+#include "DamageAccumulator.h"
+#include "FrameInfo.h"
+#include "FrameInfoVisualizer.h"
+#include "FrameMetricsReporter.h"
+#include "HintSessionWrapper.h"
+#include "IContextFactory.h"
+#include "IRenderPipeline.h"
+#include "JankTracker.h"
+#include "LayerUpdateQueue.h"
+#include "Lighting.h"
+#include "ReliableSurface.h"
+#include "RenderNode.h"
+#include "renderthread/RenderTask.h"
+#include "renderthread/RenderThread.h"
+#include "utils/RingBuffer.h"
+
namespace android {
namespace uirenderer {
@@ -66,7 +67,8 @@
class CanvasContext : public IFrameCallback {
public:
static CanvasContext* create(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
- IContextFactory* contextFactory);
+ IContextFactory* contextFactory, pid_t uiThreadId,
+ pid_t renderThreadId);
virtual ~CanvasContext();
/**
@@ -138,7 +140,7 @@
bool makeCurrent();
void prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued, RenderNode* target);
// Returns the DequeueBufferDuration.
- std::optional<nsecs_t> draw();
+ void draw();
void destroy();
// IFrameCallback, Choreographer-driven frame callback entry point
@@ -214,9 +216,14 @@
static CanvasContext* getActiveContext();
+ void sendLoadResetHint();
+
+ void setSyncDelayDuration(nsecs_t duration);
+
private:
CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
- IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
+ IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline,
+ pid_t uiThreadId, pid_t renderThreadId);
friend class RegisterFrameCallbackTask;
// TODO: Replace with something better for layer & other GL object
@@ -330,6 +337,11 @@
std::function<bool(int64_t, int64_t, int64_t)> mASurfaceTransactionCallback;
std::function<void()> mPrepareSurfaceControlForWebviewCallback;
+
+ HintSessionWrapper mHintSessionWrapper;
+ nsecs_t mLastDequeueBufferDuration = 0;
+ nsecs_t mSyncDelayDuration = 0;
+ nsecs_t mIdleDuration = 0;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index cb30614..1cc82fd 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -16,7 +16,6 @@
#include "DrawFrameTask.h"
-#include <dlfcn.h>
#include <gui/TraceUtils.h>
#include <utils/Log.h>
@@ -28,70 +27,11 @@
#include "../RenderNode.h"
#include "CanvasContext.h"
#include "RenderThread.h"
-#include "thread/CommonPool.h"
-#include "utils/TimeUtils.h"
namespace android {
namespace uirenderer {
namespace renderthread {
-namespace {
-
-typedef APerformanceHintManager* (*APH_getManager)();
-typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*, const int32_t*,
- size_t, int64_t);
-typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t);
-typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
-typedef void (*APH_sendHint)(APerformanceHintSession* session, int32_t);
-typedef void (*APH_closeSession)(APerformanceHintSession* session);
-
-bool gAPerformanceHintBindingInitialized = false;
-APH_getManager gAPH_getManagerFn = nullptr;
-APH_createSession gAPH_createSessionFn = nullptr;
-APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr;
-APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
-APH_sendHint gAPH_sendHintFn = nullptr;
-APH_closeSession gAPH_closeSessionFn = nullptr;
-
-void ensureAPerformanceHintBindingInitialized() {
- if (gAPerformanceHintBindingInitialized) return;
-
- void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
- LOG_ALWAYS_FATAL_IF(handle_ == nullptr, "Failed to dlopen libandroid.so!");
-
- gAPH_getManagerFn = (APH_getManager)dlsym(handle_, "APerformanceHint_getManager");
- LOG_ALWAYS_FATAL_IF(gAPH_getManagerFn == nullptr,
- "Failed to find required symbol APerformanceHint_getManager!");
-
- gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession");
- LOG_ALWAYS_FATAL_IF(gAPH_createSessionFn == nullptr,
- "Failed to find required symbol APerformanceHint_createSession!");
-
- gAPH_updateTargetWorkDurationFn = (APH_updateTargetWorkDuration)dlsym(
- handle_, "APerformanceHint_updateTargetWorkDuration");
- LOG_ALWAYS_FATAL_IF(
- gAPH_updateTargetWorkDurationFn == nullptr,
- "Failed to find required symbol APerformanceHint_updateTargetWorkDuration!");
-
- gAPH_reportActualWorkDurationFn = (APH_reportActualWorkDuration)dlsym(
- handle_, "APerformanceHint_reportActualWorkDuration");
- LOG_ALWAYS_FATAL_IF(
- gAPH_reportActualWorkDurationFn == nullptr,
- "Failed to find required symbol APerformanceHint_reportActualWorkDuration!");
-
- gAPH_sendHintFn = (APH_sendHint)dlsym(handle_, "APerformanceHint_sendHint");
- LOG_ALWAYS_FATAL_IF(gAPH_sendHintFn == nullptr,
- "Failed to find required symbol APerformanceHint_sendHint!");
-
- gAPH_closeSessionFn = (APH_closeSession)dlsym(handle_, "APerformanceHint_closeSession");
- LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr,
- "Failed to find required symbol APerformanceHint_closeSession!");
-
- gAPerformanceHintBindingInitialized = true;
-}
-
-} // namespace
-
DrawFrameTask::DrawFrameTask()
: mRenderThread(nullptr)
, mContext(nullptr)
@@ -100,13 +40,11 @@
DrawFrameTask::~DrawFrameTask() {}
-void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode,
- int32_t uiThreadId, int32_t renderThreadId) {
+void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context,
+ RenderNode* targetNode) {
mRenderThread = thread;
mContext = context;
mTargetNode = targetNode;
- mUiThreadId = uiThreadId;
- mRenderThreadId = renderThreadId;
}
void DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) {
@@ -150,11 +88,11 @@
void DrawFrameTask::run() {
const int64_t vsyncId = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameTimelineVsyncId)];
ATRACE_FORMAT("DrawFrames %" PRId64, vsyncId);
- nsecs_t syncDelayDuration = systemTime(SYSTEM_TIME_MONOTONIC) - mSyncQueued;
+
+ mContext->setSyncDelayDuration(systemTime(SYSTEM_TIME_MONOTONIC) - mSyncQueued);
bool canUnblockUiThread;
bool canDrawThisFrame;
- bool didDraw = false;
{
TreeInfo info(TreeInfo::MODE_FULL, *mContext);
info.forceDrawFrame = mForceDrawFrame;
@@ -175,9 +113,6 @@
std::function<void()> frameCompleteCallback = std::move(mFrameCompleteCallback);
mFrameCallback = nullptr;
mFrameCompleteCallback = nullptr;
- int64_t intendedVsync = mFrameInfo[static_cast<int>(FrameInfoIndex::IntendedVsync)];
- int64_t frameDeadline = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameDeadline)];
- int64_t frameStartTime = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameStartTime)];
// From this point on anything in "this" is *UNSAFE TO ACCESS*
if (canUnblockUiThread) {
@@ -188,18 +123,15 @@
if (CC_UNLIKELY(frameCallback)) {
context->enqueueFrameWork([frameCallback, context, syncResult = mSyncResult,
frameNr = context->getFrameNumber()]() {
- auto frameCommitCallback = std::move(frameCallback(syncResult, frameNr));
+ auto frameCommitCallback = frameCallback(syncResult, frameNr);
if (frameCommitCallback) {
context->addFrameCommitListener(std::move(frameCommitCallback));
}
});
}
- nsecs_t dequeueBufferDuration = 0;
if (CC_LIKELY(canDrawThisFrame)) {
- std::optional<nsecs_t> drawResult = context->draw();
- didDraw = drawResult.has_value();
- dequeueBufferDuration = drawResult.value_or(0);
+ context->draw();
} else {
// Do a flush in case syncFrameState performed any texture uploads. Since we skipped
// the draw() call, those uploads (or deletes) will end up sitting in the queue.
@@ -218,41 +150,6 @@
if (!canUnblockUiThread) {
unblockUiThread();
}
-
- if (!mHintSessionWrapper) mHintSessionWrapper.emplace(mUiThreadId, mRenderThreadId);
-
- constexpr int64_t kSanityCheckLowerBound = 100_us;
- constexpr int64_t kSanityCheckUpperBound = 10_s;
- int64_t targetWorkDuration = frameDeadline - intendedVsync;
- targetWorkDuration = targetWorkDuration * Properties::targetCpuTimePercentage / 100;
- if (targetWorkDuration > kSanityCheckLowerBound &&
- targetWorkDuration < kSanityCheckUpperBound &&
- targetWorkDuration != mLastTargetWorkDuration) {
- mLastTargetWorkDuration = targetWorkDuration;
- mHintSessionWrapper->updateTargetWorkDuration(targetWorkDuration);
- }
-
- if (didDraw) {
- int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime;
- int64_t actualDuration = frameDuration -
- (std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
- dequeueBufferDuration;
- if (actualDuration > kSanityCheckLowerBound && actualDuration < kSanityCheckUpperBound) {
- mHintSessionWrapper->reportActualWorkDuration(actualDuration);
- }
- }
-
- mLastDequeueBufferDuration = dequeueBufferDuration;
-}
-
-void DrawFrameTask::sendLoadResetHint() {
- if (!(Properties::useHintManager && Properties::isDrawingEnabled())) return;
- if (!mHintSessionWrapper) mHintSessionWrapper.emplace(mUiThreadId, mRenderThreadId);
- nsecs_t now = systemTime();
- if (now - mLastFrameNotification > kResetHintTimeout) {
- mHintSessionWrapper->sendHint(SessionHint::CPU_LOAD_RESET);
- }
- mLastFrameNotification = now;
}
bool DrawFrameTask::syncFrameState(TreeInfo& info) {
@@ -305,50 +202,6 @@
mSignal.signal();
}
-DrawFrameTask::HintSessionWrapper::HintSessionWrapper(int32_t uiThreadId, int32_t renderThreadId) {
- if (!Properties::useHintManager) return;
- if (uiThreadId < 0 || renderThreadId < 0) return;
-
- ensureAPerformanceHintBindingInitialized();
-
- APerformanceHintManager* manager = gAPH_getManagerFn();
- if (!manager) return;
-
- std::vector<int32_t> tids = CommonPool::getThreadIds();
- tids.push_back(uiThreadId);
- tids.push_back(renderThreadId);
-
- // DrawFrameTask code will always set a target duration before reporting actual durations.
- // So this is just a placeholder value that's never used.
- int64_t dummyTargetDurationNanos = 16666667;
- mHintSession =
- gAPH_createSessionFn(manager, tids.data(), tids.size(), dummyTargetDurationNanos);
-}
-
-DrawFrameTask::HintSessionWrapper::~HintSessionWrapper() {
- if (mHintSession) {
- gAPH_closeSessionFn(mHintSession);
- }
-}
-
-void DrawFrameTask::HintSessionWrapper::updateTargetWorkDuration(long targetDurationNanos) {
- if (mHintSession) {
- gAPH_updateTargetWorkDurationFn(mHintSession, targetDurationNanos);
- }
-}
-
-void DrawFrameTask::HintSessionWrapper::reportActualWorkDuration(long actualDurationNanos) {
- if (mHintSession) {
- gAPH_reportActualWorkDurationFn(mHintSession, actualDurationNanos);
- }
-}
-
-void DrawFrameTask::HintSessionWrapper::sendHint(SessionHint hint) {
- if (mHintSession && Properties::isDrawingEnabled()) {
- gAPH_sendHintFn(mHintSession, static_cast<int>(hint));
- }
-}
-
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 7eae41c..fafab24 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -16,7 +16,6 @@
#ifndef DRAWFRAMETASK_H
#define DRAWFRAMETASK_H
-#include <android/performance_hint.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <utils/StrongPointer.h>
@@ -28,7 +27,6 @@
#include "../Rect.h"
#include "../TreeInfo.h"
#include "RenderTask.h"
-#include "utils/TimeUtils.h"
namespace android {
namespace uirenderer {
@@ -62,8 +60,7 @@
DrawFrameTask();
virtual ~DrawFrameTask();
- void setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode,
- int32_t uiThreadId, int32_t renderThreadId);
+ void setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode);
void setContentDrawBounds(int left, int top, int right, int bottom) {
mContentDrawBounds.set(left, top, right, bottom);
}
@@ -91,22 +88,7 @@
void forceDrawNextFrame() { mForceDrawFrame = true; }
- void sendLoadResetHint();
-
private:
- class HintSessionWrapper {
- public:
- HintSessionWrapper(int32_t uiThreadId, int32_t renderThreadId);
- ~HintSessionWrapper();
-
- void updateTargetWorkDuration(long targetDurationNanos);
- void reportActualWorkDuration(long actualDurationNanos);
- void sendHint(SessionHint hint);
-
- private:
- APerformanceHintSession* mHintSession = nullptr;
- };
-
void postAndWait();
bool syncFrameState(TreeInfo& info);
void unblockUiThread();
@@ -117,8 +99,6 @@
RenderThread* mRenderThread;
CanvasContext* mContext;
RenderNode* mTargetNode = nullptr;
- int32_t mUiThreadId = -1;
- int32_t mRenderThreadId = -1;
Rect mContentDrawBounds;
/*********************************************
@@ -135,13 +115,6 @@
std::function<void(bool)> mFrameCommitCallback;
std::function<void()> mFrameCompleteCallback;
- nsecs_t mLastDequeueBufferDuration = 0;
- nsecs_t mLastTargetWorkDuration = 0;
- std::optional<HintSessionWrapper> mHintSessionWrapper;
-
- nsecs_t mLastFrameNotification = 0;
- nsecs_t kResetHintTimeout = 100_ms;
-
bool mForceDrawFrame = false;
};
diff --git a/libs/hwui/renderthread/HintSessionWrapper.cpp b/libs/hwui/renderthread/HintSessionWrapper.cpp
new file mode 100644
index 0000000..edacef0
--- /dev/null
+++ b/libs/hwui/renderthread/HintSessionWrapper.cpp
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+
+#include "HintSessionWrapper.h"
+
+#include <dlfcn.h>
+#include <utils/Log.h>
+
+#include <vector>
+
+#include "../Properties.h"
+#include "thread/CommonPool.h"
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+namespace {
+
+typedef APerformanceHintManager* (*APH_getManager)();
+typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*, const int32_t*,
+ size_t, int64_t);
+typedef void (*APH_closeSession)(APerformanceHintSession* session);
+typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t);
+typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
+typedef void (*APH_sendHint)(APerformanceHintSession* session, int32_t);
+
+bool gAPerformanceHintBindingInitialized = false;
+APH_getManager gAPH_getManagerFn = nullptr;
+APH_createSession gAPH_createSessionFn = nullptr;
+APH_closeSession gAPH_closeSessionFn = nullptr;
+APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr;
+APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
+APH_sendHint gAPH_sendHintFn = nullptr;
+
+void ensureAPerformanceHintBindingInitialized() {
+ if (gAPerformanceHintBindingInitialized) return;
+
+ void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
+ LOG_ALWAYS_FATAL_IF(handle_ == nullptr, "Failed to dlopen libandroid.so!");
+
+ gAPH_getManagerFn = (APH_getManager)dlsym(handle_, "APerformanceHint_getManager");
+ LOG_ALWAYS_FATAL_IF(gAPH_getManagerFn == nullptr,
+ "Failed to find required symbol APerformanceHint_getManager!");
+
+ gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession");
+ LOG_ALWAYS_FATAL_IF(gAPH_createSessionFn == nullptr,
+ "Failed to find required symbol APerformanceHint_createSession!");
+
+ gAPH_closeSessionFn = (APH_closeSession)dlsym(handle_, "APerformanceHint_closeSession");
+ LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr,
+ "Failed to find required symbol APerformanceHint_closeSession!");
+
+ gAPH_updateTargetWorkDurationFn = (APH_updateTargetWorkDuration)dlsym(
+ handle_, "APerformanceHint_updateTargetWorkDuration");
+ LOG_ALWAYS_FATAL_IF(
+ gAPH_updateTargetWorkDurationFn == nullptr,
+ "Failed to find required symbol APerformanceHint_updateTargetWorkDuration!");
+
+ gAPH_reportActualWorkDurationFn = (APH_reportActualWorkDuration)dlsym(
+ handle_, "APerformanceHint_reportActualWorkDuration");
+ LOG_ALWAYS_FATAL_IF(
+ gAPH_reportActualWorkDurationFn == nullptr,
+ "Failed to find required symbol APerformanceHint_reportActualWorkDuration!");
+
+ gAPH_sendHintFn = (APH_sendHint)dlsym(handle_, "APerformanceHint_sendHint");
+ LOG_ALWAYS_FATAL_IF(gAPH_sendHintFn == nullptr,
+ "Failed to find required symbol APerformanceHint_sendHint!");
+
+ gAPerformanceHintBindingInitialized = true;
+}
+
+} // namespace
+
+HintSessionWrapper::HintSessionWrapper(pid_t uiThreadId, pid_t renderThreadId)
+ : mUiThreadId(uiThreadId), mRenderThreadId(renderThreadId) {}
+
+HintSessionWrapper::~HintSessionWrapper() {
+ if (mHintSession) {
+ gAPH_closeSessionFn(mHintSession);
+ }
+}
+
+bool HintSessionWrapper::useHintSession() {
+ if (!Properties::useHintManager || !Properties::isDrawingEnabled()) return false;
+ if (mHintSession) return true;
+ // If session does not exist, create it;
+ // this defers session creation until we try to actually use it.
+ if (!mSessionValid) return false;
+ return init();
+}
+
+bool HintSessionWrapper::init() {
+ if (mUiThreadId < 0 || mRenderThreadId < 0) return false;
+
+ // Assume that if we return before the end, it broke
+ mSessionValid = false;
+
+ ensureAPerformanceHintBindingInitialized();
+
+ APerformanceHintManager* manager = gAPH_getManagerFn();
+ if (!manager) return false;
+
+ std::vector<pid_t> tids = CommonPool::getThreadIds();
+ tids.push_back(mUiThreadId);
+ tids.push_back(mRenderThreadId);
+
+ // Use a placeholder target value to initialize,
+ // this will always be replaced elsewhere before it gets used
+ int64_t defaultTargetDurationNanos = 16666667;
+ mHintSession =
+ gAPH_createSessionFn(manager, tids.data(), tids.size(), defaultTargetDurationNanos);
+
+ mSessionValid = !!mHintSession;
+ return mSessionValid;
+}
+
+void HintSessionWrapper::updateTargetWorkDuration(long targetWorkDurationNanos) {
+ if (!useHintSession()) return;
+ targetWorkDurationNanos = targetWorkDurationNanos * Properties::targetCpuTimePercentage / 100;
+ if (targetWorkDurationNanos != mLastTargetWorkDuration &&
+ targetWorkDurationNanos > kSanityCheckLowerBound &&
+ targetWorkDurationNanos < kSanityCheckUpperBound) {
+ mLastTargetWorkDuration = targetWorkDurationNanos;
+ gAPH_updateTargetWorkDurationFn(mHintSession, targetWorkDurationNanos);
+ }
+ mLastFrameNotification = systemTime();
+}
+
+void HintSessionWrapper::reportActualWorkDuration(long actualDurationNanos) {
+ if (!useHintSession()) return;
+ if (actualDurationNanos > kSanityCheckLowerBound &&
+ actualDurationNanos < kSanityCheckUpperBound) {
+ gAPH_reportActualWorkDurationFn(mHintSession, actualDurationNanos);
+ }
+}
+
+void HintSessionWrapper::sendLoadResetHint() {
+ if (!useHintSession()) return;
+ nsecs_t now = systemTime();
+ if (now - mLastFrameNotification > kResetHintTimeout) {
+ gAPH_sendHintFn(mHintSession, static_cast<int>(SessionHint::CPU_LOAD_RESET));
+ }
+ mLastFrameNotification = now;
+}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/HintSessionWrapper.h b/libs/hwui/renderthread/HintSessionWrapper.h
new file mode 100644
index 0000000..fcbc101
--- /dev/null
+++ b/libs/hwui/renderthread/HintSessionWrapper.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/performance_hint.h>
+
+#include "utils/TimeUtils.h"
+
+namespace android {
+namespace uirenderer {
+
+namespace renderthread {
+
+class HintSessionWrapper {
+public:
+ HintSessionWrapper(pid_t uiThreadId, pid_t renderThreadId);
+ ~HintSessionWrapper();
+
+ void updateTargetWorkDuration(long targetDurationNanos);
+ void reportActualWorkDuration(long actualDurationNanos);
+ void sendLoadResetHint();
+
+private:
+ bool useHintSession();
+ bool init();
+ APerformanceHintSession* mHintSession = nullptr;
+
+ nsecs_t mLastFrameNotification = 0;
+ nsecs_t mLastTargetWorkDuration = 0;
+
+ pid_t mUiThreadId;
+ pid_t mRenderThreadId;
+
+ bool mSessionValid = true;
+
+ static constexpr nsecs_t kResetHintTimeout = 100_ms;
+ static constexpr int64_t kSanityCheckLowerBound = 100_us;
+ static constexpr int64_t kSanityCheckUpperBound = 10_s;
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 03a2bc9..07f5a78 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -42,11 +42,13 @@
RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode,
IContextFactory* contextFactory)
: mRenderThread(RenderThread::getInstance()), mContext(nullptr) {
- mContext = mRenderThread.queue().runSync([&]() -> CanvasContext* {
- return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory);
+ pid_t uiThreadId = pthread_gettid_np(pthread_self());
+ pid_t renderThreadId = getRenderThreadTid();
+ mContext = mRenderThread.queue().runSync([=, this]() -> CanvasContext* {
+ return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory,
+ uiThreadId, renderThreadId);
});
- mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode,
- pthread_gettid_np(pthread_self()), getRenderThreadTid());
+ mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
}
RenderProxy::~RenderProxy() {
@@ -55,7 +57,7 @@
void RenderProxy::destroyContext() {
if (mContext) {
- mDrawFrameTask.setContext(nullptr, nullptr, nullptr, -1, -1);
+ mDrawFrameTask.setContext(nullptr, nullptr, nullptr);
// This is also a fence as we need to be certain that there are no
// outstanding mDrawFrame tasks posted before it is destroyed
mRenderThread.queue().runSync([this]() { delete mContext; });
@@ -237,7 +239,7 @@
}
void RenderProxy::notifyCallbackPending() {
- mDrawFrameTask.sendLoadResetHint();
+ mRenderThread.queue().post([this]() { mContext->sendLoadResetHint(); });
}
void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
diff --git a/libs/hwui/tests/common/CallCountingCanvas.h b/libs/hwui/tests/common/CallCountingCanvas.h
index d3c41191..dc36a2e 100644
--- a/libs/hwui/tests/common/CallCountingCanvas.h
+++ b/libs/hwui/tests/common/CallCountingCanvas.h
@@ -19,6 +19,8 @@
#include <SkCanvasVirtualEnforcer.h>
#include <SkNoDrawCanvas.h>
+enum class SkBlendMode;
+
namespace android {
namespace uirenderer {
namespace test {
diff --git a/libs/hwui/tests/common/TestListViewSceneBase.cpp b/libs/hwui/tests/common/TestListViewSceneBase.cpp
index 43df4a0..e70d44c 100644
--- a/libs/hwui/tests/common/TestListViewSceneBase.cpp
+++ b/libs/hwui/tests/common/TestListViewSceneBase.cpp
@@ -19,6 +19,8 @@
#include "TestContext.h"
#include "TestUtils.h"
+#include <SkBlendMode.h>
+
#include <utils/Color.h>
namespace android {
diff --git a/libs/hwui/tests/common/scenes/BitmapFillrate.cpp b/libs/hwui/tests/common/scenes/BitmapFillrate.cpp
index 5af7d43..19e87f8 100644
--- a/libs/hwui/tests/common/scenes/BitmapFillrate.cpp
+++ b/libs/hwui/tests/common/scenes/BitmapFillrate.cpp
@@ -19,6 +19,7 @@
#include "utils/Color.h"
#include <SkBitmap.h>
+#include <SkBlendMode.h>
using namespace android;
using namespace android::uirenderer;
diff --git a/libs/hwui/tests/common/scenes/ClippingAnimation.cpp b/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
index 2a016ac..3a1ea8c 100644
--- a/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ClippingAnimation.cpp
@@ -16,6 +16,8 @@
#include "TestSceneBase.h"
+#include <SkBlendMode.h>
+
class ClippingAnimation;
static TestScene::Registrar _RectGrid(TestScene::Info{
diff --git a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
index 4271d2f..484289a 100644
--- a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
@@ -20,6 +20,8 @@
#include <hwui/Paint.h>
#include <minikin/Layout.h>
+#include <SkBlendMode.h>
+
#include <cstdio>
class GlyphStressAnimation;
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
index 0d5ca6d..dfdd0d8 100644
--- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -17,6 +17,7 @@
#include "TestSceneBase.h"
#include "utils/Color.h"
+#include <SkBlendMode.h>
#include <SkColorSpace.h>
#include <SkGradientShader.h>
#include <SkImagePriv.h>
diff --git a/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp b/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
index cac2fb3..2955fb2 100644
--- a/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
@@ -16,6 +16,8 @@
#include "TestSceneBase.h"
+#include <SkBlendMode.h>
+
class HwLayerAnimation;
static TestScene::Registrar _HwLayer(TestScene::Info{
diff --git a/libs/hwui/tests/common/scenes/HwLayerSizeAnimation.cpp b/libs/hwui/tests/common/scenes/HwLayerSizeAnimation.cpp
index 77a59df..8c9a614 100644
--- a/libs/hwui/tests/common/scenes/HwLayerSizeAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/HwLayerSizeAnimation.cpp
@@ -16,6 +16,8 @@
#include "TestSceneBase.h"
+#include <SkBlendMode.h>
+
class HwLayerSizeAnimation;
static TestScene::Registrar _HwLayerSize(TestScene::Info{
diff --git a/libs/hwui/tests/common/scenes/JankyScene.cpp b/libs/hwui/tests/common/scenes/JankyScene.cpp
index f5e6b31..250b986 100644
--- a/libs/hwui/tests/common/scenes/JankyScene.cpp
+++ b/libs/hwui/tests/common/scenes/JankyScene.cpp
@@ -16,6 +16,8 @@
#include "TestSceneBase.h"
+#include <SkBlendMode.h>
+
#include <unistd.h>
class JankyScene;
diff --git a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
index 5eaf185..f669dbc 100644
--- a/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListOfFadedTextAnimation.cpp
@@ -17,6 +17,7 @@
#include "TestSceneBase.h"
#include "tests/common/TestListViewSceneBase.h"
#include "hwui/Paint.h"
+#include <SkBlendMode.h>
#include <SkGradientShader.h>
class ListOfFadedTextAnimation;
diff --git a/libs/hwui/tests/common/scenes/OvalAnimation.cpp b/libs/hwui/tests/common/scenes/OvalAnimation.cpp
index 402c1ec..1a2af83 100644
--- a/libs/hwui/tests/common/scenes/OvalAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/OvalAnimation.cpp
@@ -17,6 +17,8 @@
#include "TestSceneBase.h"
#include "utils/Color.h"
+#include <SkBlendMode.h>
+
class OvalAnimation;
static TestScene::Registrar _Oval(TestScene::Info{"oval", "Draws 1 oval.",
diff --git a/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp b/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
index fb1b000..25cf4d6 100644
--- a/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
@@ -16,6 +16,8 @@
#include "TestSceneBase.h"
+#include <SkBlendMode.h>
+
class PartialDamageAnimation;
static TestScene::Registrar _PartialDamage(TestScene::Info{
diff --git a/libs/hwui/tests/common/scenes/PathClippingAnimation.cpp b/libs/hwui/tests/common/scenes/PathClippingAnimation.cpp
index 1e343c1..969514c 100644
--- a/libs/hwui/tests/common/scenes/PathClippingAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/PathClippingAnimation.cpp
@@ -16,6 +16,8 @@
#include <vector>
+#include <SkBlendMode.h>
+
#include "TestSceneBase.h"
class PathClippingAnimation : public TestScene {
diff --git a/libs/hwui/tests/common/scenes/RectGridAnimation.cpp b/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
index f37bcbc..99e7858 100644
--- a/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
@@ -16,6 +16,8 @@
#include "TestSceneBase.h"
+#include <SkBlendMode.h>
+
class RectGridAnimation;
static TestScene::Registrar _RectGrid(TestScene::Info{
diff --git a/libs/hwui/tests/common/scenes/RoundRectClippingAnimation.cpp b/libs/hwui/tests/common/scenes/RoundRectClippingAnimation.cpp
index e9f353d..2c27969 100644
--- a/libs/hwui/tests/common/scenes/RoundRectClippingAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/RoundRectClippingAnimation.cpp
@@ -16,6 +16,8 @@
#include "TestSceneBase.h"
+#include <SkBlendMode.h>
+
#include <vector>
class RoundRectClippingAnimation : public TestScene {
diff --git a/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp b/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp
index 252f539..ee30c13 100644
--- a/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp
+++ b/libs/hwui/tests/common/scenes/SaveLayer2Animation.cpp
@@ -16,6 +16,7 @@
#include <hwui/Paint.h>
#include <minikin/Layout.h>
+#include <SkBlendMode.h>
#include <string>
#include "TestSceneBase.h"
diff --git a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
index 31a8ae1..d5060c7 100644
--- a/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
@@ -16,6 +16,8 @@
#include "TestSceneBase.h"
+#include <SkBlendMode.h>
+
class SaveLayerAnimation;
static TestScene::Registrar _SaveLayer(TestScene::Info{
diff --git a/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp b/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
index c13e80e..827ddab 100644
--- a/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
+++ b/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
@@ -16,6 +16,8 @@
#include "TestSceneBase.h"
+#include <SkBlendMode.h>
+
class ShadowGrid2Animation;
static TestScene::Registrar _ShadowGrid2(TestScene::Info{
diff --git a/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp b/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
index 772b98e..a4fb10c 100644
--- a/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
@@ -16,6 +16,8 @@
#include "TestSceneBase.h"
+#include <SkBlendMode.h>
+
class ShadowGridAnimation;
static TestScene::Registrar _ShadowGrid(TestScene::Info{
diff --git a/libs/hwui/tests/common/scenes/ShadowShaderAnimation.cpp b/libs/hwui/tests/common/scenes/ShadowShaderAnimation.cpp
index 0019da5..58c0372 100644
--- a/libs/hwui/tests/common/scenes/ShadowShaderAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ShadowShaderAnimation.cpp
@@ -16,6 +16,8 @@
#include "TestSceneBase.h"
+#include <SkBlendMode.h>
+
class ShadowShaderAnimation;
static TestScene::Registrar _ShadowShader(TestScene::Info{
diff --git a/libs/hwui/tests/common/scenes/ShapeAnimation.cpp b/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
index 70a1557d..c0c3dfd 100644
--- a/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ShapeAnimation.cpp
@@ -17,6 +17,8 @@
#include "TestSceneBase.h"
#include "utils/Color.h"
+#include <SkBlendMode.h>
+
#include <cstdio>
class ShapeAnimation;
diff --git a/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
index 2aeb42c..40f2ed0 100644
--- a/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SimpleColorMatrixAnimation.cpp
@@ -16,6 +16,7 @@
#include "TestSceneBase.h"
+#include <SkBlendMode.h>
#include <SkColorFilter.h>
#include <SkColorMatrix.h>
#include <SkGradientShader.h>
diff --git a/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
index 57a260c..a9e7a34 100644
--- a/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/SimpleGradientAnimation.cpp
@@ -16,6 +16,7 @@
#include "TestSceneBase.h"
+#include <SkBlendMode.h>
#include <SkGradientShader.h>
class SimpleGradientAnimation;
diff --git a/libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp b/libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp
index 7d3ca96..bb95490 100644
--- a/libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/StretchyListViewAnimation.cpp
@@ -15,6 +15,7 @@
*/
#include <SkBitmap.h>
+#include <SkBlendMode.h>
#include <SkCanvas.h>
#include <SkColor.h>
#include <SkFont.h>
diff --git a/libs/hwui/tests/common/scenes/TextAnimation.cpp b/libs/hwui/tests/common/scenes/TextAnimation.cpp
index d3090367..78146b8 100644
--- a/libs/hwui/tests/common/scenes/TextAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/TextAnimation.cpp
@@ -17,6 +17,8 @@
#include "TestSceneBase.h"
#include "hwui/Paint.h"
+#include <SkBlendMode.h>
+
class TextAnimation;
static TestScene::Registrar _Text(TestScene::Info{"text", "Draws a bunch of text.",
diff --git a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
index 9cd1075..a55b725 100644
--- a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
@@ -22,6 +22,8 @@
#include "pipeline/skia/SkiaDisplayList.h"
#include "tests/common/TestUtils.h"
+#include <SkBlendMode.h>
+
using namespace android;
using namespace android::uirenderer;
using namespace android::uirenderer::skiapipeline;
diff --git a/libs/hwui/tests/microbench/RenderNodeBench.cpp b/libs/hwui/tests/microbench/RenderNodeBench.cpp
index 6aed251..72946c4 100644
--- a/libs/hwui/tests/microbench/RenderNodeBench.cpp
+++ b/libs/hwui/tests/microbench/RenderNodeBench.cpp
@@ -19,6 +19,8 @@
#include "hwui/Canvas.h"
#include "RenderNode.h"
+#include <SkBlendMode.h>
+
using namespace android;
using namespace android::uirenderer;
diff --git a/libs/hwui/tests/unit/CanvasContextTests.cpp b/libs/hwui/tests/unit/CanvasContextTests.cpp
index 1771c35..88420a5 100644
--- a/libs/hwui/tests/unit/CanvasContextTests.cpp
+++ b/libs/hwui/tests/unit/CanvasContextTests.cpp
@@ -36,7 +36,7 @@
auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
ContextFactory contextFactory;
std::unique_ptr<CanvasContext> canvasContext(
- CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
+ CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory, 0, 0));
ASSERT_FALSE(canvasContext->hasSurface());
diff --git a/libs/hwui/tests/unit/CanvasOpTests.cpp b/libs/hwui/tests/unit/CanvasOpTests.cpp
index d2b1ef9..1f6edf3 100644
--- a/libs/hwui/tests/unit/CanvasOpTests.cpp
+++ b/libs/hwui/tests/unit/CanvasOpTests.cpp
@@ -23,6 +23,7 @@
#include <tests/common/CallCountingCanvas.h>
+#include "SkBlendMode.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColor.h"
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index ec949b8..596bd37 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -17,6 +17,7 @@
#include <VectorDrawable.h>
#include <gtest/gtest.h>
+#include <SkBlendMode.h>
#include <SkClipStack.h>
#include <SkSurface_Base.h>
#include <string.h>
@@ -334,7 +335,7 @@
"A");
ContextFactory contextFactory;
std::unique_ptr<CanvasContext> canvasContext(
- CanvasContext::create(renderThread, false, parent.get(), &contextFactory));
+ CanvasContext::create(renderThread, false, parent.get(), &contextFactory, 0, 0));
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
@@ -398,7 +399,7 @@
"A");
ContextFactory contextFactory;
std::unique_ptr<CanvasContext> canvasContext(
- CanvasContext::create(renderThread, false, parent.get(), &contextFactory));
+ CanvasContext::create(renderThread, false, parent.get(), &contextFactory, 0, 0));
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
@@ -518,7 +519,7 @@
// prepareTree is required to find, which receivers have backward projected nodes
ContextFactory contextFactory;
std::unique_ptr<CanvasContext> canvasContext(
- CanvasContext::create(renderThread, false, parent.get(), &contextFactory));
+ CanvasContext::create(renderThread, false, parent.get(), &contextFactory, 0, 0));
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
@@ -618,7 +619,7 @@
// prepareTree is required to find, which receivers have backward projected nodes
ContextFactory contextFactory;
std::unique_ptr<CanvasContext> canvasContext(
- CanvasContext::create(renderThread, false, parent.get(), &contextFactory));
+ CanvasContext::create(renderThread, false, parent.get(), &contextFactory, 0, 0));
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
@@ -634,7 +635,7 @@
static int drawNode(RenderThread& renderThread, const sp<RenderNode>& renderNode) {
ContextFactory contextFactory;
std::unique_ptr<CanvasContext> canvasContext(
- CanvasContext::create(renderThread, false, renderNode.get(), &contextFactory));
+ CanvasContext::create(renderThread, false, renderNode.get(), &contextFactory, 0, 0));
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index 61bd646..80796f4 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -274,7 +274,7 @@
auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
ContextFactory contextFactory;
std::unique_ptr<CanvasContext> canvasContext(
- CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
+ CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory, 0, 0));
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
@@ -310,7 +310,7 @@
});
ContextFactory contextFactory;
std::unique_ptr<CanvasContext> canvasContext(
- CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
+ CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory, 0, 0));
canvasContext->setSurface(nullptr);
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
index 50d9f56..87c5216 100644
--- a/libs/hwui/tests/unit/SkiaCanvasTests.cpp
+++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
@@ -17,10 +17,19 @@
#include "tests/common/TestUtils.h"
#include <hwui/Paint.h>
+#include <SkAlphaType.h>
+#include <SkBitmap.h>
+#include <SkBlendMode.h>
+#include <SkCanvas.h>
#include <SkCanvasStateUtils.h>
+#include <SkColor.h>
#include <SkColorSpace.h>
+#include <SkColorType.h>
+#include <SkImageInfo.h>
#include <SkPicture.h>
#include <SkPictureRecorder.h>
+#include <SkRefCnt.h>
+#include <SkSurface.h>
#include <gtest/gtest.h>
using namespace android;
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index 3d5aca4..f825d7c 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -142,7 +142,7 @@
auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
ContextFactory contextFactory;
std::unique_ptr<CanvasContext> canvasContext(
- CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
+ CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory, 0, 0));
TreeInfo info(TreeInfo::MODE_FULL, *canvasContext.get());
DamageAccumulator damageAccumulator;
info.damageAccumulator = &damageAccumulator;
@@ -201,7 +201,7 @@
auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
ContextFactory contextFactory;
std::unique_ptr<CanvasContext> canvasContext(
- CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
+ CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory, 0, 0));
// Set up a Surface so that we can position the VectorDrawable offscreen.
test::TestContext testContext;
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
index 7419f8f..4d0595e 100644
--- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -17,6 +17,7 @@
#include <VectorDrawable.h>
#include <gtest/gtest.h>
+#include <SkBlendMode.h>
#include <SkClipStack.h>
#include <SkSurface_Base.h>
#include <string.h>
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index 94bcb11..f44f9d0 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -19,6 +19,7 @@
#include <GLES2/gl2.h>
#include <utils/Blur.h>
+#include <SkBlendMode.h>
#include <SkColorFilter.h>
#include <SkPaint.h>
#include <SkShader.h>
diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp
index 0e7b7ff..a835167 100644
--- a/libs/input/MouseCursorController.cpp
+++ b/libs/input/MouseCursorController.cpp
@@ -199,8 +199,7 @@
width = viewport.deviceWidth;
height = viewport.deviceHeight;
- if (viewport.orientation == DISPLAY_ORIENTATION_90 ||
- viewport.orientation == DISPLAY_ORIENTATION_270) {
+ if (viewport.orientation == ui::ROTATION_90 || viewport.orientation == ui::ROTATION_270) {
std::swap(width, height);
}
}
@@ -244,38 +243,42 @@
// Undo the previous rotation.
switch (oldViewport.orientation) {
- case DISPLAY_ORIENTATION_90:
+ case ui::ROTATION_90:
temp = x;
x = oldViewport.deviceHeight - y;
y = temp;
break;
- case DISPLAY_ORIENTATION_180:
+ case ui::ROTATION_180:
x = oldViewport.deviceWidth - x;
y = oldViewport.deviceHeight - y;
break;
- case DISPLAY_ORIENTATION_270:
+ case ui::ROTATION_270:
temp = x;
x = y;
y = oldViewport.deviceWidth - temp;
break;
+ case ui::ROTATION_0:
+ break;
}
// Perform the new rotation.
switch (viewport.orientation) {
- case DISPLAY_ORIENTATION_90:
+ case ui::ROTATION_90:
temp = x;
x = y;
y = viewport.deviceHeight - temp;
break;
- case DISPLAY_ORIENTATION_180:
+ case ui::ROTATION_180:
x = viewport.deviceWidth - x;
y = viewport.deviceHeight - y;
break;
- case DISPLAY_ORIENTATION_270:
+ case ui::ROTATION_270:
temp = x;
x = viewport.deviceWidth - y;
y = temp;
break;
+ case ui::ROTATION_0:
+ break;
}
// Apply offsets to convert from the pixel center to the pixel top-left corner position
diff --git a/media/java/android/media/RouteListingPreference.java b/media/java/android/media/RouteListingPreference.java
index 26b190b..62f233e 100644
--- a/media/java/android/media/RouteListingPreference.java
+++ b/media/java/android/media/RouteListingPreference.java
@@ -16,6 +16,7 @@
package android.media;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
@@ -23,6 +24,8 @@
import com.android.internal.util.Preconditions;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -111,6 +114,45 @@
/** Holds preference information for a specific route in a media routing listing. */
public static final class Item implements Parcelable {
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(
+ flag = true,
+ prefix = {"FLAG_"},
+ value = {FLAG_ONGOING_SESSION, FLAG_SUGGESTED_ROUTE})
+ public @interface Flags {}
+
+ /**
+ * The corresponding route is already hosting a session with the app that owns this listing
+ * preference.
+ */
+ public static final int FLAG_ONGOING_SESSION = 1;
+
+ /**
+ * The corresponding route is specially likely to be selected by the user.
+ *
+ * <p>A UI reflecting this preference may reserve a specific space for suggested routes,
+ * making it more accessible to the user. If the number of suggested routes exceeds the
+ * number supported by the UI, the routes listed first in {@link
+ * RouteListingPreference#getItems()} will take priority.
+ */
+ public static final int FLAG_SUGGESTED_ROUTE = 1 << 1;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(
+ prefix = {"DISABLE_REASON_"},
+ value = {DISABLE_REASON_NONE, DISABLE_REASON_SUBSCRIPTION_REQUIRED})
+ public @interface DisableReason {}
+
+ /** The corresponding route is available for routing. */
+ public static final int DISABLE_REASON_NONE = 0;
+ /**
+ * The corresponding route requires a special subscription in order to be available for
+ * routing.
+ */
+ public static final int DISABLE_REASON_SUBSCRIPTION_REQUIRED = 1;
+
@NonNull
public static final Creator<Item> CREATOR =
new Creator<>() {
@@ -126,21 +168,29 @@
};
@NonNull private final String mRouteId;
+ @Flags private final int mFlags;
+ @DisableReason private final int mDisableReason;
/**
* Creates an instance with the given value.
*
* @param routeId See {@link #getRouteId()}. Must not be empty.
+ * @param flags See {@link #getFlags()}.
+ * @param disableReason See {@link #getDisableReason()}.
*/
- public Item(@NonNull String routeId) {
+ public Item(@NonNull String routeId, @Flags int flags, @DisableReason int disableReason) {
Preconditions.checkArgument(!TextUtils.isEmpty(routeId));
mRouteId = routeId;
+ mFlags = flags;
+ mDisableReason = disableReason;
}
private Item(Parcel in) {
String routeId = in.readString();
Preconditions.checkArgument(!TextUtils.isEmpty(routeId));
mRouteId = routeId;
+ mFlags = in.readInt();
+ mDisableReason = in.readInt();
}
/** Returns the id of the route that corresponds to this route listing preference item. */
@@ -149,6 +199,29 @@
return mRouteId;
}
+ /**
+ * Returns the flags associated to the route that corresponds to this item.
+ *
+ * @see #FLAG_ONGOING_SESSION
+ * @see #FLAG_SUGGESTED_ROUTE
+ */
+ @Flags
+ public int getFlags() {
+ return mFlags;
+ }
+
+ /**
+ * Returns the reason for the corresponding route to be disabled, or {@link
+ * #DISABLE_REASON_NONE} if the route is not disabled.
+ *
+ * @see #DISABLE_REASON_NONE
+ * @see #DISABLE_REASON_SUBSCRIPTION_REQUIRED
+ */
+ @DisableReason
+ public int getDisableReason() {
+ return mDisableReason;
+ }
+
// Item Parcelable implementation.
@Override
@@ -159,6 +232,8 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mRouteId);
+ dest.writeInt(mFlags);
+ dest.writeInt(mDisableReason);
}
// Equals and hashCode.
@@ -172,12 +247,14 @@
return false;
}
Item item = (Item) other;
- return mRouteId.equals(item.mRouteId);
+ return mRouteId.equals(item.mRouteId)
+ && mFlags == item.mFlags
+ && mDisableReason == item.mDisableReason;
}
@Override
public int hashCode() {
- return Objects.hash(mRouteId);
+ return Objects.hash(mRouteId, mFlags, mDisableReason);
}
}
}
diff --git a/packages/CompanionDeviceManager/res/values-af/strings.xml b/packages/CompanionDeviceManager/res/values-af/strings.xml
index 97cae3a..3d8369a 100644
--- a/packages/CompanionDeviceManager/res/values-af/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-af/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang tot jou <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"horlosie"</string>
<string name="chooser_title" msgid="2262294130493605839">"Kies \'n <xliff:g id="PROFILE_NAME">%1$s</xliff:g> om deur <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> bestuur te word"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Hierdie app is nodig om jou <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te bestuur. <xliff:g id="APP_NAME">%2$s</xliff:g> sal toegelaat word om interaksie met jou kennisgewings te hê, en sal toegang hê tot jou Foon-, SMS-, Kontakte-, Kalender-, Oproeprekords- en Toestelle in die Omtrek-toestemming."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Hierdie app is nodig om jou <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te bestuur. <xliff:g id="APP_NAME">%2$s</xliff:g> sal toegelaat word om interaksie met die volgende toestemmings te hê:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Gee <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang tot hierdie inligting op jou foon"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Oorkruistoestel-dienste"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek tans namens jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toestemming om programme tussen jou toestelle te stroom"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dit kan mikrofoon-, kamera- en liggingtoegang insluit, asook ander sensitiewe toestemmings op <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Jy kan hierdie toestemmings enige tyd verander in jou Instellings op <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Program-ikoon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Meer Inligting-knoppie"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Foon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontakte"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Toestelle in die omtrek"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foto\'s en media"</string>
<string name="permission_notification" msgid="693762568127741203">"Kennisgewings"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Het toegang tot jou foonnommer en netwerkinligting. Word vereis vir die maak van oproepe en VoIP, stemboodskapdiens, oproepherleiding en die wysiging van oproeprekords"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Kan jou kontaklys lees, skep, of wysig, en het toegang tot die lys van al die rekeninge wat op jou toestel gebruik word"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kan alle kennisgewings lees, insluitend inligting soos kontakte, boodskappe en foto\'s"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stroom jou foon se apps"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml
index ef685e6..94c9325 100644
--- a/packages/CompanionDeviceManager/res/values-as/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-as/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক আপোনাৰ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> এক্সেছ কৰিবলৈ দিয়ক"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ঘড়ী"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>এ পৰিচালনা কৰিব লগা এটা <xliff:g id="PROFILE_NAME">%1$s</xliff:g> বাছনি কৰক"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"আপোনাৰ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এপ্টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক আপোনাৰ জাননী ব্যৱহাৰ কৰিবলৈ আৰু আপোনাৰ ফ’ন, এছএমএছ, সম্পৰ্ক ,কেলেণ্ডাৰ, কল লগ আৰু নিকটৱৰ্তী ডিভাইচৰ অনুমতি এক্সেছ কৰিবলৈ দিয়া হ’ব।"</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"আপোনাৰ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> পৰিচালনা কৰিবলৈ এপ্টোৰ আৱশ্যক। <xliff:g id="APP_NAME">%2$s</xliff:g>ক এই অনুমতিসমূহৰ সৈতে ভাব-বিনিময় কৰিবলৈ দিয়া হ’ব:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ক আপোনাৰ ফ’নৰ পৰা এই তথ্যখিনি এক্সেছ কৰাৰ অনুমতি দিয়ক"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"ক্ৰছ-ডিভাইচ সেৱাসমূহ"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ হৈ আপোনাৰ ডিভাইচসমূহৰ মাজত এপ্ ষ্ট্ৰীম কৰাৰ বাবে অনুৰোধ জনাইছে"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>ইয়াত <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>ত মাইক্ৰ’ফ’ন, কেমেৰা আৰু অৱস্থানৰ এক্সেছ আৰু অন্য সংবেদশীল অনুমতিসমূহ প্ৰদান কৰাটো অন্তৰ্ভুক্ত হ’ব পাৰে।</p> <p>আপুনি যিকোনো সময়তে <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>ত থকা আপোনাৰ ছেটিঙত এই অনুমতিসমূহ সলনি কৰিব পাৰে।</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"এপৰ চিহ্ন"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"অধিক তথ্যৰ বুটাম"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"ফ’ন"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"এছএমএছ"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"সম্পৰ্ক"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"কেলেণ্ডাৰ"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"নিকটৱৰ্তী ডিভাইচ"</string>
<string name="permission_storage" msgid="6831099350839392343">"ফট’ আৰু মিডিয়া"</string>
<string name="permission_notification" msgid="693762568127741203">"জাননী"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"এপ্"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"কল আৰু VoIP, ভইচমেইল, কল ৰিডাইৰেক্ট আৰু কলৰ লগ সম্পাদনা কৰিবলৈ আৱশ্যক হোৱা আপোনাৰ ফ’ন নম্বৰ আৰু নেটৱৰ্কৰ তথ্য এক্সেছ কৰিব পাৰে"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"আমাৰ সম্পৰ্কসূচী পঢ়িব, সৃষ্টি কৰিব অথবা সম্পাদনা কৰিব পাৰে আৰু লগতে আপোনাৰ ডিভাইচত ব্যৱহাৰ কৰা আটাইবোৰ একাউণ্টৰ সূচীখন এক্সেছ কৰিব পাৰে"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"সম্পৰ্কসূচী, বাৰ্তা আৰু ফট’ৰ দৰে তথ্যকে ধৰি আটাইবোৰ জাননী পঢ়িব পাৰে"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"আপোনাৰ ফ’নৰ এপ্ ষ্ট্ৰীম কৰক"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml
index b303e0f..625275dc 100644
--- a/packages/CompanionDeviceManager/res/values-az/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-az/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinin <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> cihazınıza girişinə icazə verin"</string>
<string name="profile_name_watch" msgid="576290739483672360">"izləyin"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> tərəfindən idarə ediləcək <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızı idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> bildirişlərinizə, Telefon, SMS, Kontaktlar, Təqvim, Zəng qeydləri və Yaxınlıqdakı cihaz icazələrinə giriş əldə edəcək."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Tətbiq <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızı idarə etmək üçün lazımdır. <xliff:g id="APP_NAME">%2$s</xliff:g> bu icazələrlə qarşılıqlı əlaqəyə icazə veriləcək:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqinə telefonunuzdan bu məlumata giriş icazəsi verin"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlararası xidmətlər"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> adından cihazlarınız arasında tətbiqləri yayımlamaq üçün icazə istəyir"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Buraya <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> cihazındakı Mikrofon, Kamera və Məkana girişi və digər həssas icazələr daxil ola bilər.</p> <p>Bu icazələri istənilən vaxt <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> cihazında ayarlarınızda dəyişə bilərsiniz.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Tətbiq İkonası"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Ətraflı Məlumat Düyməsi"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontakt"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Təqvim"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Yaxınlıqdakı cihazlar"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foto və media"</string>
<string name="permission_notification" msgid="693762568127741203">"Bildirişlər"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Tətbiqlər"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Telefon nömrənizə və şəbəkə məlumatınıza giriş edə bilər. Zəng etmək və VoIP, səsli poçt, zəng yönləndirməsi və zəng qeydlərini redaktə etmək üçün tələb olunur"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Kontakt siyahımızı oxuya, yarada və ya redaktə edə, həmçinin cihazınızda istifadə edilən bütün hesabların siyahısına giriş edə bilər"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Bütün bildirişləri, o cümlədən kontaktlar, mesajlar və fotolar kimi məlumatları oxuya bilər"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefonunuzun tətbiqlərini yayımlayın"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
index a064672..4b12d60 100644
--- a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pristupa uređaju <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"sat"</string>
<string name="chooser_title" msgid="2262294130493605839">"Odaberite profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS, kontakte, kalendar, evidencije poziva i uređaje u blizini."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> će dobiti dozvolu za interakciju sa ovim dozvolama:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pristupa ovim informacijama sa telefona"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluge na više uređaja"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> zahteva dozvolu u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za strimovanje aplikacija između uređaja"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>To može da obuhvata pristup mikrofonu, kameri i lokaciji, kao i drugim osetljivim dozvolama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>U svakom trenutku možete da promenite te dozvole u Podešavanjima na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikacije"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Dugme za više informacija"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontakti"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalendar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Uređaji u blizini"</string>
<string name="permission_storage" msgid="6831099350839392343">"Slike i mediji"</string>
<string name="permission_notification" msgid="693762568127741203">"Obaveštenja"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Može da pristupa vašem broju telefona i informacijama o mreži. Neophodno za upućivanje poziva i VoIP, govornu poštu, preusmeravanje poziva i izmene evidencije poziva"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Može da čita, kreira ili menja listu kontakata, kao i da pristupa listi svih naloga koji se koriste na vašem uređaju"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Može da čita sva obaveštenja, uključujući informacije poput kontakata, poruka i slika"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Strimujte aplikacije na telefonu"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml
index a42b974..a11f9c1 100644
--- a/packages/CompanionDeviceManager/res/values-be/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-be/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> доступ да вашай прылады <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"гадзіннік"</string>
<string name="chooser_title" msgid="2262294130493605839">"Выберыце прыладу (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), якой будзе кіраваць праграма <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа ўзаемадзейнічаць з вашымі апавяшчэннямі і атрымае доступ да тэлефона, SMS, кантактаў, календара, журналаў выклікаў і прылад паблізу."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Гэта праграма неабходная для кіравання прыладай \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> зможа выкарыстоўваць наступныя дазволы:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> мець доступ да гэтай інфармацыі з вашага тэлефона"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Сэрвісы для некалькіх прылад"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запытвае дазвол ад імя вашай прылады \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" на трансляцыю праграм паміж вашымі прыладамі"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Дазволы могуць уключаць доступ да мікрафона, камеры і даных пра месцазнаходжанне, а таксама да іншай канфідэнцыяльнай інфармацыі на прыладзе <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Вы можаце ў любы час змяніць гэтыя дазволы ў Наладах на прыладзе <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Значок праграмы"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Кнопка \"Даведацца больш\""</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Тэлефон"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Кантакты"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Каляндар"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Прылады паблізу"</string>
<string name="permission_storage" msgid="6831099350839392343">"Фота і медыяфайлы"</string>
<string name="permission_notification" msgid="693762568127741203">"Апавяшчэнні"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Праграмы"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Доступ да вашага нумара тэлефона і інфармацыі пра сетку. Гэты дазвол патрабуецца, каб рабіць звычайныя і VoIP-выклікі, адпраўляць галасавыя паведамленні, перанакіроўваць выклікі і рэдагаваць журналы выклікаў"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Магчымасць чытаць, ствараць і рэдагаваць спіс кантактаў, а таксама атрымліваць доступ да спіса ўсіх уліковых запісаў на вашай прыладзе"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Можа счытваць усе апавяшчэнні, уключаючы паведамленні, фота і інфармацыю пра кантакты"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Трансляцыя змесціва праграм з вашага тэлефона"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml
index a4bd854..e75f392 100644
--- a/packages/CompanionDeviceManager/res/values-bg/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Разрешаване на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да осъществява достъп до устройството ви <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"часовник"</string>
<string name="chooser_title" msgid="2262294130493605839">"Изберете устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), което да се управлява от <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Това приложение е необходимо за управление на устройството ви (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи разрешение да взаимодейства с известията ви и да осъществява достъп до разрешенията за телефона, SMS съобщенията, контактите, календара, списъците с обажданията и разрешенията за устройства в близост."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Това приложение е необходимо за управление на устройството ви (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> ще получи разрешение да взаимодейства със следните разрешения:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Разрешете на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да осъществява достъп до тази информация от телефона ви"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуги за различни устройства"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ иска разрешение от името на <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> да предава поточно приложения между устройствата ви"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Това може да включва достъп до микрофона, камерата и местоположението, както и други разрешения за достъп до поверителна информация на <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Можете да промените тези разрешения по всяко време от настройките на <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Икона на приложението"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Бутон за още информация"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Телефон"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Контакти"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Календар"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Устройства в близост"</string>
<string name="permission_storage" msgid="6831099350839392343">"Снимки и мултимедия"</string>
<string name="permission_notification" msgid="693762568127741203">"Известия"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Приложения"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Може да осъществява достъп до номера и мрежата на телефона ви. Изисква се за провеждането на обаждания и разговори през VoIP, гласовата поща, пренасочването на обаждания и редактирането на списъците с обажданията"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Може да чете, създава и редактира записи в списъка с контактите ви, както и да осъществява достъп до списъка с всички профили, използвани на устройството ви"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Може да чете всички известия, включително различна информация, като например контакти, съобщения и снимки"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Поточно предаване на приложенията на телефона ви"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml
index 2f36c5a..8930a81 100644
--- a/packages/CompanionDeviceManager/res/values-bn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"আপনার <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> অ্যাক্সেস করার জন্য <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-কে অনুমতি দিন"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ঘড়ি"</string>
<string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> বেছে নিন যেটি <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ম্যানেজ করবে"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করার জন্য অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g>-কে আপনার বিজ্ঞপ্তির সাথে ইন্টার্যাক্ট করার এবং ফোন, এসএমএস, পরিচিতি, ক্যালেন্ডার, কল লগ ও আশেপাশের ডিভাইস অ্যাক্সেস করার অনুমতি দেওয়া হবে।"</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"আপনার <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ম্যানেজ করার জন্য অ্যাপটি প্রয়োজন। <xliff:g id="APP_NAME">%2$s</xliff:g> অ্যাপকে এইসব অনুমতির সাথে ইন্টার্যাক্ট করার জন্য অনুমোদন দেওয়া হবে:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"আপনার ফোন থেকে <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> অ্যাপকে এই তথ্য অ্যাক্সেস করার অনুমতি দিন"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"ক্রস-ডিভাইস পরিষেবা"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"আপনার ডিভাইসগুলির মধ্যে অ্যাপ স্ট্রিম করার জন্য <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এর হয়ে অনুমতি চাইছে"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>এটি <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p&gt-এ হয়ত মাইক্রোফোন, ক্যামেরা এবং লোকেশনের অ্যাক্সেস ও অন্যান্য সংবেদনশীল অনুমতি অন্তর্ভুক্ত করতে পারে;আপনি যেকোনও সময় <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>-এর \'সেটিংস\'-এ গিয়ে এইসব অনুমতি পরিবর্তন করতে পারবেন"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"অ্যাপের আইকন"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"আরও তথ্য সংক্রান্ত বোতাম"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"ফোন"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"এসএমএস"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"পরিচিতি"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"ক্যালেন্ডার"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"আশেপাশের ডিভাইস"</string>
<string name="permission_storage" msgid="6831099350839392343">"ফটো ও মিডিয়া"</string>
<string name="permission_notification" msgid="693762568127741203">"বিজ্ঞপ্তি"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"অ্যাপ"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"আপনার ফোন নম্বর ও নেটওয়ার্ক সংক্রান্ত তথ্য অ্যাক্সেস করতে পারবে। কল করার জন্য এবং VoIP, ভয়েসমেল, কল রিডাইরেক্ট ও কল লগ এডিট করার জন্য যা প্রয়োজন"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"আমাদের পরিচিতি তালিকা দেখতে, তৈরি বা এডিট করতে পারবে, পাশাপাশি আপনার ডিভাইসে ব্যবহার করা হয় এমন সবকটি অ্যাকাউন্টের তালিকা অ্যাক্সেস করতে পারবে"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"সব বিজ্ঞপ্তি পড়তে পারবে, যার মধ্যে পরিচিতি, মেসেজ ও ফটোর মতো তথ্য অন্তর্ভুক্ত"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"আপনার ফোনের অ্যাপ স্ট্রিম করুন"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml
index 78f6e2c..2a45533 100644
--- a/packages/CompanionDeviceManager/res/values-bs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Dozvolite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da pristupa uređaju <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"sat"</string>
<string name="chooser_title" msgid="2262294130493605839">"Odaberite uređaj <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će se dozvoliti da ostvaruje interakciju s vašim obavještenjima i da pristupa odobrenjima za telefon, SMS-ove, kontakte, kalendar, zapisnike poziva i uređaje u blizini."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikacija je potrebna za upravljanje uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> će biti dozvoljena interakcija s ovim odobrenjima:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Dozvolite da aplikacija <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pristupa ovim informacijama s telefona"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluga na više uređaja"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> u ime uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> zahtijeva odobrenje da prenosi aplikacije između vaših uređaja"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ovo može uključivati pristup mikrofonu, kameri i lokaciji i druga osjetljiva odobrenja na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Uvijek možete promijeniti ova odobrenja u Postavkama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikacije"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Dugme Više informacija"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontakti"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalendar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Uređaji u blizini"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string>
<string name="permission_notification" msgid="693762568127741203">"Obavještenja"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Može pristupiti vašem broju telefona i informacijama o mreži. Potrebno je za upućivanje poziva i VoIP, govornu poštu, preusmjeravanje poziva te uređivanje zapisnika poziva"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Može čitati, kreirati ili uređivati našu listu kontakata te pristupiti listi svih računa koji se koriste na vašem uređaju"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Može čitati sva obavještenja, uključujući informacije kao što su kontakti, poruke i fotografije"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Prenosite aplikacije s telefona"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml
index 840c89c..8995cdd 100644
--- a/packages/CompanionDeviceManager/res/values-ca/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> accedeixi a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"rellotge"</string>
<string name="chooser_title" msgid="2262294130493605839">"Tria un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> perquè el gestioni <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"L\'aplicació és necessària per gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per interaccionar amb les teves notificacions i accedir al telèfon, als SMS, als contactes, al calendari, als registres de trucades i als dispositius propers."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"L\'aplicació és necessària per gestionar <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> tindrà permís per interaccionar amb aquests permisos:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Permet que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> accedeixi a aquesta informació del telèfon"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Serveis multidispositiu"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del teu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> per reproduir en continu aplicacions entre els dispositius"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Això pot incloure accés al micròfon, a la càmera i a la ubicació, i altres permisos sensibles a <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Pots canviar aquests permisos en qualsevol moment a <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>, a Configuració.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icona de l\'aplicació"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Botó Més informació"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telèfon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contactes"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendari"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositius propers"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos i contingut multimèdia"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificacions"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Aplicacions"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Pot accedir al teu número de telèfon i a la informació de la xarxa. Es requereix per fer trucades i VoIP, enviar missatges de veu, redirigir trucades i editar els registres de trucades."</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Pot llegir, crear o editar la nostra llista de contactes i també accedir a la llista de tots els comptes que s\'utilitzen al teu dispositiu"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Pot llegir totes les notificacions, inclosa informació com ara els contactes, els missatges i les fotos"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Reprodueix en continu aplicacions del telèfon"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml
index 0ce29cf..fdf93d8 100644
--- a/packages/CompanionDeviceManager/res/values-cs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Povolit aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> přístup k vašemu zařízení <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"hodinky"</string>
<string name="chooser_title" msgid="2262294130493605839">"Vyberte zařízení <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, které chcete spravovat pomocí aplikace <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Aplikace je nutná ke správě zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikace <xliff:g id="APP_NAME">%2$s</xliff:g> bude moci interagovat s vašimi oznámeními a získá přístup k telefonu, SMS, kontaktům, kalendáři, seznamům hovorů a zařízením v okolí."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikace je nutná ke správě zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikace <xliff:g id="APP_NAME">%2$s</xliff:g> bude moci interagovat s těmito oprávněními:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Povolte aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> přístup k těmto informacím z vašeho telefonu"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pro více zařízení"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> oprávnění ke streamování aplikací mezi zařízeními"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Může být zahrnut přístup k mikrofonu, fotoaparátu a poloze a další citlivá oprávnění na zařízení <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Tato oprávnění můžete v Nastavení na zařízení <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> kdykoliv změnit.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikace"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Tlačítko Další informace"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontakty"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalendář"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Zařízení v okolí"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotky a média"</string>
<string name="permission_notification" msgid="693762568127741203">"Oznámení"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikace"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Má přístup k vašemu telefonnímu číslu a informacím o síti. Vyžadováno pro volání a VoIP, hlasové zprávy, přesměrování hovorů a úpravy seznamů hovorů."</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Může načítat, vytvářet a upravovat váš seznam kontaktů a má přístup k seznamu všech účtů používaných v zařízení"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Může číst veškerá oznámení včetně informací, jako jsou kontakty, zprávy a fotky"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streamujte aplikace v telefonu"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml
index 32f958f..51fcc62 100644
--- a/packages/CompanionDeviceManager/res/values-da/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-da/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Tillad, at <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> får adgang til dit <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ur"</string>
<string name="chooser_title" msgid="2262294130493605839">"Vælg den enhed (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), som skal administreres af <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tilladelse til at interagere med dine notifikationer og får adgang til dine tilladelser for Opkald, Sms, Kalender, Opkaldshistorik og Enheder i nærheden."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Du skal bruge denne app for at administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får mulighed for at interagere med følgende tilladelser:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Giv <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> adgang til disse oplysninger fra din telefon"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester, som kan tilsluttes en anden enhed"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til at streame apps mellem dine enheder"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dette kan omfatte mikrofon-, kamera- og lokationsadgang samt andre tilladelser til at tilgå følsomme oplysninger på <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Du kan til enhver tid ændre disse tilladelser under Indstillinger på <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Appikon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Knappen Flere oplysninger"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"Sms"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontakter"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Enheder i nærheden"</string>
<string name="permission_storage" msgid="6831099350839392343">"Billeder og medier"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifikationer"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Har adgang til oplysninger om dit telefonnummer og netværk. Påkrævet for at foretage opkald og VoIP, talebeskeder, omdirigering og redigering af opkaldshistorikken"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Kan læse, oprette eller redigere din liste over kontakter samt tilgå lister for alle de konti, der bruges på din enhed"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kan læse alle notifikationer, herunder oplysninger som f.eks. kontakter, beskeder og billeder"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream din telefons apps"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml
index 42c6fde..8747256 100644
--- a/packages/CompanionDeviceManager/res/values-de/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-de/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> erlauben, auf dein Gerät (<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>) zuzugreifen"</string>
<string name="profile_name_watch" msgid="576290739483672360">"Smartwatch"</string>
<string name="chooser_title" msgid="2262294130493605839">"Gerät „<xliff:g id="PROFILE_NAME">%1$s</xliff:g>“ auswählen, das von <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> verwaltet werden soll"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Die App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf mit deinen Benachrichtigungen interagieren und auf die Berechtigungen „Telefon“, „SMS“, „Kontakte“, „Kalender“, „Anrufliste“ und „Geräte in der Nähe“ zugreifen."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Die App wird zur Verwaltung deines Geräts (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) benötigt. <xliff:g id="APP_NAME">%2$s</xliff:g> darf mit diesen Berechtigungen interagieren:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> Zugriff auf diese Informationen von deinem Smartphone gewähren"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Geräteübergreifende Dienste"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> um die Berechtigung zum Streamen von Apps zwischen deinen Geräten"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dazu können Berechtigungen für Mikrofon, Kamera und Standortzugriff sowie andere vertrauliche Berechtigungen auf <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> gehören.</p><p>Sie lassen sich jederzeit in den Einstellungen auf <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> ändern.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App-Symbol"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Weitere-Infos-Schaltfläche"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontakte"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Geräte in der Nähe"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos und Medien"</string>
<string name="permission_notification" msgid="693762568127741203">"Benachrichtigungen"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Darf auf deine Telefonnummer und Netzwerkinformationen zugreifen. Erforderlich für normale und VoIP-Anrufe, Mailbox, Anrufweiterleitung und das Bearbeiten von Anruflisten"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Darf deine Kontaktliste lesen, erstellen oder bearbeiten sowie auf die Kontaktliste aller auf diesem Gerät verwendeten Konten zugreifen"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kann alle Benachrichtigungen lesen, einschließlich Informationen wie Kontakten, Nachrichten und Fotos"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Smartphone-Apps streamen"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml
index 28ab7a3..ccd5611 100644
--- a/packages/CompanionDeviceManager/res/values-el/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-el/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Επιτρέψτε στην εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> να έχει πρόσβαση στη συσκευή <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ρολόι"</string>
<string name="chooser_title" msgid="2262294130493605839">"Επιλέξτε ένα προφίλ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> για διαχείριση από την εφαρμογή <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Η εφαρμογή είναι απαραίτητη για τη διαχείριση της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Η εφαρμογή <xliff:g id="APP_NAME">%2$s</xliff:g> θα επιτρέπεται να αλληλεπιδρά με τις ειδοποιήσεις και να έχει πρόσβαση στις άδειες Τηλέφωνο, SMS, Επαφές, Ημερολόγιο, Αρχεία καταγραφής κλήσεων και Συσκευές σε κοντινή απόσταση."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Η εφαρμογή είναι απαραίτητη για τη διαχείριση της συσκευής <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Η εφαρμογή <xliff:g id="APP_NAME">%2$s</xliff:g> θα επιτρέπεται να αλληλεπιδρά με τις εξής άδειες:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Να επιτρέπεται στο <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> η πρόσβαση σε αυτές τις πληροφορίες από το τηλέφωνό σας."</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Υπηρεσίες πολλών συσκευών"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> ζητά εκ μέρους της συσκευής σας <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> άδεια για ροή εφαρμογών μεταξύ των συσκευών σας"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Αυτές μπορεί να περιλαμβάνουν πρόσβαση σε μικρόφωνο, κάμερα και τοποθεσία και άλλες άδειες πρόσβασης σε ευαίσθητες πληροφορίες στη συσκευή <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Μπορείτε να αλλάξετε αυτές τις άδειες ανά πάσα στιγμή στις Ρυθμίσεις σας στη συσκευή <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Εικονίδιο εφαρμογής"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Κουμπί περισσότερων πληροφορ."</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Τηλέφωνο"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Επαφές"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Ημερολόγιο"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Συσκευές σε κοντινή απόσταση"</string>
<string name="permission_storage" msgid="6831099350839392343">"Φωτογραφίες και μέσα"</string>
<string name="permission_notification" msgid="693762568127741203">"Ειδοποιήσεις"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Εφαρμογές"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Δυνατότητα πρόσβασης στον αριθμό τηλεφώνου σας και στις πληροφορίες δικτύου. Απαιτείται για την πραγματοποίηση κλήσεων και για υπηρεσίες VoIP, μηνύματα αυτόματου τηλεφωνητή, ανακατεύθυνση κλήσεων και επεξεργασία αρχείων καταγραφής κλήσεων"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Δυνατότητα ανάγνωσης, δημιουργίας ή επεξεργασίας της λίστας επαφών σας, καθώς και πρόσβασης στη λίστα επαφών όλων των λογαριασμών που χρησιμοποιούνται στη συσκευή σας"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Μπορεί να διαβάσει όλες τις ειδοποιήσεις, συμπεριλαμβανομένων πληροφοριών όπως επαφές, μηνύματα και φωτογραφίες"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Μεταδώστε σε ροή τις εφαρμογές του τηλεφώνου σας"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
index 89aebbd..1d7623f 100644
--- a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access your <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, calendar, call logs and Nearby devices permissions."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include microphone, camera and location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions at any time in your settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App icon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"More information button"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Phone"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Nearby devices"</string>
<string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Can access your phone number and network info. Required for making calls and VoIP, voicemail, call redirect and editing call logs"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Can read, create or edit our contact list, as well as access the list of all accounts used on your device"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages and photos"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream your phone’s apps"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
index d6f95ad..61ae537 100644
--- a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access your <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include Microphone, Camera, and Location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions any time in your Settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App Icon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"More Information Button"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Phone"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Nearby devices"</string>
<string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Can access your phone number and network info. Required for making calls and VoIP, voicemail, call redirect, and editing call logs"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Can read, create, or edit our contact list, as well as access the list of all accounts used on your device"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages, and photos"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream your phone’s apps"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
index 89aebbd..1d7623f 100644
--- a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access your <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, calendar, call logs and Nearby devices permissions."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include microphone, camera and location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions at any time in your settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App icon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"More information button"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Phone"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Nearby devices"</string>
<string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Can access your phone number and network info. Required for making calls and VoIP, voicemail, call redirect and editing call logs"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Can read, create or edit our contact list, as well as access the list of all accounts used on your device"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages and photos"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream your phone’s apps"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
index 89aebbd..1d7623f 100644
--- a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access your <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your phone, SMS, contacts, calendar, call logs and Nearby devices permissions."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include microphone, camera and location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions at any time in your settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App icon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"More information button"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Phone"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Nearby devices"</string>
<string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Can access your phone number and network info. Required for making calls and VoIP, voicemail, call redirect and editing call logs"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Can read, create or edit our contact list, as well as access the list of all accounts used on your device"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages and photos"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream your phone’s apps"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
index 54c4931..d40ac6a 100644
--- a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access your <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with your notifications and access your Phone, SMS, Contacts, Calendar, Call logs and Nearby devices permissions."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"The app is needed to manage your <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> will be allowed to interact with these permissions:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Allow <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to access this information from your phone"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> to stream apps between your devices"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include Microphone, Camera, and Location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions any time in your Settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App Icon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"More Information Button"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Phone"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Nearby devices"</string>
<string name="permission_storage" msgid="6831099350839392343">"Photos and media"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Can access your phone number and network info. Required for making calls and VoIP, voicemail, call redirect, and editing call logs"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Can read, create, or edit our contact list, as well as access the list of all accounts used on your device"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Can read all notifications, including information like contacts, messages, and photos"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream your phone’s apps"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
index 31e9b66..ef7e59d 100644
--- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a tu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"reloj"</string>
<string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para que la app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> lo administre"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Esta app es necesaria para administrar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con tus notificaciones y acceder a los permisos de Teléfono, SMS, Contactos, Calendario, Llamadas y Dispositivos cercanos."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Esta app es necesaria para administrar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con estos permisos:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Permite que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información de tu teléfono"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita tu permiso en nombre de <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para transmitir apps entre dispositivos"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Esto puede incluir el acceso al micrófono, la cámara y la ubicación, así como otros permisos sensibles del dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Puedes cambiar estos permisos en cualquier momento en la Configuración del dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ícono de la app"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Botón Más información"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Teléfono"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contactos"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendario"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos cercanos"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos y contenido multimedia"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificaciones"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Puede acceder a tu número de teléfono y a la información de la red (es obligatorio para realizar llamadas VoIP, enviar mensajes de voz, redireccionar llamadas y editar registros de llamadas)"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Puede leer, crear o editar la lista de contactos, además de acceder a la lista de contactos para todas las cuentas que se usan en tu dispositivo"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Puede leer todas las notificaciones, incluso con información como contactos, mensajes y fotos"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Transmitir las apps de tu teléfono"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml
index bcfff13..82ff28a 100644
--- a/packages/CompanionDeviceManager/res/values-es/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a tu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"reloj"</string>
<string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para gestionarlo con <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Se necesita la aplicación para gestionar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> podrá interactuar con tus notificaciones y acceder a tus permisos de teléfono, SMS, contactos, calendario, registros de llamadas y dispositivos cercanos."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Se necesita la aplicación para gestionar tu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Se permitirá que <xliff:g id="APP_NAME">%2$s</xliff:g> interaccione con los siguientes permisos:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información de tu teléfono"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicios multidispositivo"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para emitir aplicaciones en otros dispositivos tuyos"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Esto puede incluir acceso al micrófono, la cámara y la ubicación, así como otros permisos sensibles de <p><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Puedes cambiar estos permisos cuando quieras en los ajustes de <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icono de la aplicación"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Botón Más información"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Teléfono"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contactos"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendario"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos cercanos"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos y elementos multimedia"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificaciones"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Aplicaciones"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Puede acceder a tu número de teléfono e información de red. Es necesario para hacer llamadas y VoIP, enviar mensajes de voz, redirigir llamadas y editar registros de llamadas"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Puede leer, crear o editar tu lista de contactos, así como acceder a la lista de contactos de todas las cuentas que se usan en tu dispositivo"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Puede leer todas las notificaciones, incluida información como contactos, mensajes y fotos"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Muestra en streaming las aplicaciones de tu teléfono"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml
index b267ce5..ab42dda 100644
--- a/packages/CompanionDeviceManager/res/values-et/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-et/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Lubage rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> teie seadmele <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> juurde pääseda"</string>
<string name="profile_name_watch" msgid="576290739483672360">"käekell"</string>
<string name="chooser_title" msgid="2262294130493605839">"Valige seade <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, mida haldab rakendus <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Seda rakendust on vaja teie seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse kasutada teie märguandeid ning pääseda juurde teie telefoni, SMS-ide, kontaktide, kalendri, kõnelogide ja läheduses olevate seadmete lubadele."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Seda rakendust on vaja teie seadme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> haldamiseks. Rakendusel <xliff:g id="APP_NAME">%2$s</xliff:g> lubatakse kasutada järgmisi lube."</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Lubage rakendusel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pääseda teie telefonis juurde sellele teabele"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Seadmeülesed teenused"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nimel luba teie seadmete vahel rakendusi voogesitada"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>See võib hõlmata mikrofoni, kaamerat ja juurdepääsu asukohale ning muid tundlikke lube seadmes <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Võite neid lube seadme <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> seadetes igal ajal muuta.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Rakenduse ikoon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Nupp Lisateave"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontaktid"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Läheduses olevad seadmed"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotod ja meedia"</string>
<string name="permission_notification" msgid="693762568127741203">"Märguanded"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Rakendused"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Pääseb juurde teie telefoninumbrile ja võrguteabele. Nõutav helistamiseks, VoIP-i ja kõneposti kasutamiseks, kõnede ümbersuunamiseks ning kõnelogide muutmiseks."</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Saab lugeda, luua või muuta kontaktiloendit ja pääseda juurde kõigi teie seadmes kasutatavate kontode loendile"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kõikide märguannete, sealhulgas teabe, nagu kontaktid, sõnumid ja fotod, lugemine"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefoni rakenduste voogesitamine"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index b6421b3..b00cb5b 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> اجازه دهید به <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> دسترسی داشته باشد"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ساعت"</string>
<string name="chooser_title" msgid="2262294130493605839">"انتخاب <xliff:g id="PROFILE_NAME">%1$s</xliff:g> برای مدیریت کردن با <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> شما لازم است. <xliff:g id="APP_NAME">%2$s</xliff:g> میتواند با اعلانهای شما تعامل داشته باشد و به اجازههای «تلفن»، «پیامک»، «مخاطبین»، «تقویم»، «گزارشهای تماس» و «دستگاههای اطراف» دسترسی خواهد داشت."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"این برنامه برای مدیریت <xliff:g id="DEVICE_NAME">%1$s</xliff:g> شما لازم است. <xliff:g id="APP_NAME">%2$s</xliff:g> مجاز است با این اجازهها تعامل داشته باشد:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"اجازه دادن به <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> برای دسترسی به اطلاعات تلفن"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"سرویسهای بیندستگاهی"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> اجازه میخواهد ازطرف <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> برنامهها را بین دستگاههای شما جاریسازی کند"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>این اجازهها میتواند شامل دسترسی به «میکروفون»، «دوربین»، و «مکان»، و دیگر اجازههای حساس در <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> شود.</p> <p>هروقت بخواهید میتوانید این اجازهها را در «تنظیمات» در <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> تغییر دهید.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"نماد برنامه"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"دکمه اطلاعات بیشتر"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"تلفن"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"پیامک"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"مخاطبین"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"تقویم"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"دستگاههای اطراف"</string>
<string name="permission_storage" msgid="6831099350839392343">"عکسها و رسانهها"</string>
<string name="permission_notification" msgid="693762568127741203">"اعلانها"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"برنامهها"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"میتواند به شماره تلفن و اطلاعات شبکهتان دسترسی داشته باشد. برای برقراری تماسهای تلفنی و VoIP، استفاده از پست صوتی، هدایت تماس، و ویرایش گزارشهای تماس لازم است"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"میتواند فهرست مخاطبین ما را بخواند و ایجاد یا ویرایش کند و همچنین میتواند به فهرست همه حسابهای مورداستفاده در دستگاهتان دسترسی داشته باشد"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"میتواند همه اعلانها، ازجمله اطلاعاتی مثل مخاطبین، پیامها، و عکسها را بخواند"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"جاریسازی برنامههای تلفن"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml
index d71ad89..d4136c7 100644
--- a/packages/CompanionDeviceManager/res/values-fi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fi/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Salli, että <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> saa pääsyn laitteeseesi: <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"kello"</string>
<string name="chooser_title" msgid="2262294130493605839">"Valitse <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, jota <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> hallinnoi"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Laitteen (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) ylläpitoon tarvitaan tätä sovellusta. <xliff:g id="APP_NAME">%2$s</xliff:g> saa luvan hallinnoida ilmoituksiasi sekä pääsyn puhelimeen, tekstiviesteihin, yhteystietoihin, kalenteriin, puhelulokeihin ja lähellä olevat laitteet ‑lupiin."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Laitteen (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) ylläpitoon tarvitaan tätä sovellusta. <xliff:g id="APP_NAME">%2$s</xliff:g> saa käyttää näitä lupia:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Salli, että <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> saa pääsyn näihin puhelimesi tietoihin"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Laitteidenväliset palvelut"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteesi (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) puolesta lupaa striimata sovelluksia laitteidesi välillä"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Tähän voi kuulua pääsy mikrofoniin, kameraan ja sijaintiin sekä muita arkaluontoisia lupia laitteella <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Voit muuttaa lupia asetuksista milloin tahansa laitteella <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Sovelluskuvake"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Lisätietopainike"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Puhelin"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"Tekstiviesti"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Yhteystiedot"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalenteri"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Lähellä olevat laitteet"</string>
<string name="permission_storage" msgid="6831099350839392343">"Kuvat ja media"</string>
<string name="permission_notification" msgid="693762568127741203">"Ilmoitukset"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Sovellukset"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Voi nähdä puhelinnumerosi ja verkon tiedot. Tätä tarvitaan puheluiden soittamiseen, VoIP:n, puhelinvastaajan ja puheluiden uudelleenohjauksen käyttämiseen sekä puhelulokien muokkaamiseen."</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Voi luoda yhteystietolistan tai lukea tai muokata sitä sekä avata listan kaikilla tileillä, joita käytetään laitteellasi."</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Voi lukea kaikkia ilmoituksia, esim. kontakteihin, viesteihin ja kuviin liittyviä tietoja"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Striimaa puhelimen sovelluksia"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
index 95f512a..7c17039 100644
--- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à votre <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"montre"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choisissez un(e) <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"L\'application est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder aux autorisations suivantes : téléphone, messages texte, contacts, agenda, journaux d\'appels et appareils à proximité."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"L\'application est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec ces autorisations :"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Autorisez <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à ces informations à partir de votre téléphone"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Services multiappareils"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour diffuser des applications entre vos appareils"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Cela peut comprendre l\'accès au microphone, à l\'appareil photo et à la position, ainsi que d\'autres autorisations sensibles sur <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Vous pouvez modifier ces autorisations en tout temps dans vos paramètres sur <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icône de l\'application"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Bouton En savoir plus"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Téléphone"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"Messages texte"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Agenda"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Appareils à proximité"</string>
<string name="permission_storage" msgid="6831099350839392343">"Photos et fichiers multimédias"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Applications"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Peut accéder à votre numéro de téléphone et à vos renseignements de réseau. Ceci est nécessaire pour passer des appels téléphoniques et des appels voix sur IP, laisser un message vocal, rediriger les appels et modifier les journaux d\'appels"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Peut lire, créer ou modifier notre liste de contacts et accéder à la liste de tous les comptes utilisés sur votre appareil"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Peut lire toutes les notifications, y compris les renseignements tels que les contacts, les messages et les photos"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Diffusez les applications de votre téléphone"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml
index aa4da5b..fde2322 100644
--- a/packages/CompanionDeviceManager/res/values-fr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à votre <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"montre"</string>
<string name="chooser_title" msgid="2262294130493605839">"Sélectionnez le/la <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Cette appli est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> aura l\'autorisation d\'interagir avec vos notifications et d\'accéder au téléphone, aux SMS, aux contacts, à l\'agenda, aux journaux d\'appels et aux appareils à proximité."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Cette appli est nécessaire pour gérer votre <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> pourra interagir avec ces autorisations :"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Autoriser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à accéder à ces informations depuis votre téléphone"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Services inter-appareils"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pour caster des applis d\'un appareil à l\'autre"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Il peut s\'agir de l\'accès au micro, à l\'appareil photo et à la position, et d\'autres autorisations sensibles sur l\'appareil <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Vous pouvez modifier ces autorisations à tout moment dans les paramètres de l\'appareil <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icône d\'application"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Bouton Plus d\'informations"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Téléphone"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Agenda"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Appareils à proximité"</string>
<string name="permission_storage" msgid="6831099350839392343">"Photos et contenus multimédias"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Applis"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Peut accéder à votre numéro de téléphone et aux informations réseau. Nécessaire pour passer des appels et pour VoIP, la messagerie vocale, la redirection d\'appels et la modification des journaux d\'appels."</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Peut lire, créer ou modifier votre liste de contacts, et accéder à la liste de tous les comptes utilisés sur votre appareil"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Peut lire toutes les notifications, y compris des informations comme les contacts, messages et photos"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Diffuser en streaming les applis de votre téléphone"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml
index 2a7af18..214c3f5 100644
--- a/packages/CompanionDeviceManager/res/values-gl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Permitir que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda ao teu dispositivo (<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>)"</string>
<string name="profile_name_watch" msgid="576290739483672360">"reloxo"</string>
<string name="chooser_title" msgid="2262294130493605839">"Escolle un perfil (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) para que o xestione a aplicación <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"A aplicación é necesaria para xestionar o teu dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá interactuar coas túas notificacións e acceder aos permisos do teu teléfono, das SMS, dos contactos, do calendario, dos rexistros de chamadas e dos dispositivos próximos."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"A aplicación é necesaria para xestionar o teu dispositivo (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>). <xliff:g id="APP_NAME">%2$s</xliff:g> poderá interactuar con estes permisos:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Permitir que a aplicación <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> acceda a esta información desde o teu teléfono"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Servizos multidispositivo"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome do teu dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) para emitir contido de aplicacións entre os teus aparellos"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Con esta acción podes conceder acceso ao micrófono, á cámara e á localización, así como outros permisos de acceso á información confidencial de <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Podes cambiar estes permisos en calquera momento na configuración de <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icona de aplicación"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Botón de máis información"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Teléfono"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contactos"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendario"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos próximos"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos e contido multimedia"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificacións"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Aplicacións"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Pode acceder ao teu número de teléfono e á información de rede do dispositivo. Necesítase para facer chamadas, usar VoIP, acceder ao correo de voz, redirixir chamadas e modificar os rexistros de chamadas"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Pode ler, crear ou editar a túa lista de contactos, así como acceder á lista de todas as contas usadas no teu dispositivo"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificacións (que poden incluír información como contactos, mensaxes e fotos)"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Emite as aplicacións do teu teléfono"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml
index a9895eb..437ab99 100644
--- a/packages/CompanionDeviceManager/res/values-hr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Dopustite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da pristupa vašem uređaju <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"satom"</string>
<string name="chooser_title" msgid="2262294130493605839">"Odaberite profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Aplikacija je potrebna za upravljanje vašim uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će stupati u interakciju s vašim obavijestima i pristupati dopuštenjima za telefon, SMS-ove, kontakte, kalendar, zapisnike poziva i uređaje u blizini."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikacija je potrebna za upravljanje vašim uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME">%2$s</xliff:g> moći će stupati u interakciju s ovim dopuštenjima:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Omogućite aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da pristupa informacijama s vašeg telefona"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Usluge na različitim uređajima"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime vašeg uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> za emitiranje aplikacija između vaših uređaja"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>To može uključivati pristup mikrofonu, kameri i lokaciji i druga dopuštenja za osjetljive podatke na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Ta dopuštenja uvijek možete promijeniti u postavkama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikacije"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Gumb Više informacija"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontakti"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalendar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Uređaji u blizini"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string>
<string name="permission_notification" msgid="693762568127741203">"Obavijesti"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Može pristupati vašem broju telefona i podacima o mreži. Potrebno je za uspostavu poziva i VoIP, govornu poštu, preusmjeravanje poziva i uređivanje zapisnika poziva"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Može čitati, izrađivati ili uređivati vaš popis kontakata te pristupati popisu kontakata svih računa korištenih na vašem uređaju"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Može čitati sve obavijesti, uključujući informacije kao što su kontakti, poruke i fotografije"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streaming aplikacija vašeg telefona"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml
index 83f681aa..de7aac1 100644
--- a/packages/CompanionDeviceManager/res/values-hu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"A(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> hozzáférésének engedélyezése a(z) <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> eszközhöz"</string>
<string name="profile_name_watch" msgid="576290739483672360">"óra"</string>
<string name="chooser_title" msgid="2262294130493605839">"A(z) <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> alkalmazással kezelni kívánt <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiválasztása"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Szükség van az alkalmazásra a következő kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> műveleteket végezhet majd az értesítésekkel, és hozzáférhet a telefonra, az SMS-ekre, a névjegyekre, a naptárra, a hívásnaplókra és a közeli eszközökre vonatkozó engedélyekhez."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Szükség van az alkalmazásra a következő kezeléséhez: <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A(z) <xliff:g id="APP_NAME">%2$s</xliff:g> műveleteket végezhet majd ezekkel az engedélyekkel:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Engedélyezi a(z) „<xliff:g id="APP_NAME">%1$s</xliff:g>” alkalmazás számára az információhoz való hozzáférést a telefonról"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Többeszközös szolgáltatások"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nevében az alkalmazások eszközök közötti streameléséhez"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ide tartozhatnak a mikrofonhoz, a kamerához és a helyhez való hozzáférések, valamint a(z) <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> eszközön érvényes egyéb, bizalmas adatokra vonatkozó hozzáférési engedélyek is.</p> <p>Ezeket az engedélyeket bármikor módosíthatja a(z) <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> eszköz beállításai között.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Alkalmazás ikonja"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"További információ gomb"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Címtár"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Naptár"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Közeli eszközök"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotók és médiatartalmak"</string>
<string name="permission_notification" msgid="693762568127741203">"Értesítések"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Alkalmazások"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Hozzáférhet telefonszámához és hálózati adataihoz. Hívások és VoIP indításához, hívásátirányításhoz és hívásnaplók szerkesztéséhez szükséges."</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Olvashatja, létrehozhatja és szerkesztheti a névjegylistánkat, valamint hozzáférhet az eszközén használt összes fiók listájához"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Elolvashat minden értesítést, ideértve az olyan információkat, mint a névjegyek, az üzenetek és a fotók"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"A telefon alkalmazásainak streamelése"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml
index d0b739d..acbb453c1 100644
--- a/packages/CompanionDeviceManager/res/values-hy/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Թույլատրեք <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածին կառավարել ձեր <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> սարքը"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ժամացույց"</string>
<string name="chooser_title" msgid="2262294130493605839">"Ընտրեք <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ը, որը պետք է կառավարվի <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> հավելվածի կողմից"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Այս հավելվածն անհրաժեշտ է ձեր <xliff:g id="DEVICE_NAME">%1$s</xliff:g> պրոֆիլը կառավարելու համար։ <xliff:g id="APP_NAME">%2$s</xliff:g> հավելվածը կկարողանա փոխազդել ձեր ծանուցումների հետ և կստանա «Հեռախոս», «SMS», «Կոնտակտներ», «Օրացույց», «Կանչերի ցուցակ» և «Մոտակա սարքեր» թույլտվությունները։"</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Այս հավելվածն անհրաժեշտ է ձեր <xliff:g id="DEVICE_NAME">%1$s</xliff:g> պրոֆիլը կառավարելու համար։ <xliff:g id="APP_NAME">%2$s</xliff:g> հավելվածին կթույլատրվի օգտվել այս թույլտվություններից․"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Թույլատրեք <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածին օգտագործել այս տեղեկությունները ձեր հեռախոսից"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Միջսարքային ծառայություններ"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր սարքերի միջև հավելվածներ հեռարձակելու համար"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Դրանք կարող են ներառել խոսափողի, տեսախցիկի և տեղադրության տվյալների օգտագործման թույլտվությունները, ինչպես նաև կոնֆիդենցիալ տեղեկությունների օգտագործման այլ թույլտվություններ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> սարքում։</p> <p>Այդ թույլտվությունները ցանկացած ժամանակ կարելի է փոխել <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> սարքի ձեր կարգավորումներում։</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Հավելվածի պատկերակ"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"«Այլ տեղեկություններ» կոճակ"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Հեռախոս"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Կոնտակտներ"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Օրացույց"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Մոտակա սարքեր"</string>
<string name="permission_storage" msgid="6831099350839392343">"Լուսանկարներ և մուլտիմեդիա"</string>
<string name="permission_notification" msgid="693762568127741203">"Ծանուցումներ"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Հավելվածներ"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Կարող է օգտագործել ձեր հեռախոսահամարը և ցանցի մասին տեղեկությունները։ Պահանջվում է սովորական և VoIP զանգեր կատարելու, ձայնային փոստի, զանգերի վերահասցեավորման և զանգերի մատյանները փոփոխելու համար"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Կարող է կարդալ, ստեղծել և փոփոխել կոնտակտների ցանկը, ինչպես նաև բացել ձեր սարքի բոլոր հաշիվների ցանկը"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Կարող է կարդալ բոլոր ծանուցումները, ներառյալ տեղեկությունները, օրինակ՝ կոնտակտները, հաղորդագրությունները և լուսանկարները"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Հեռարձակել հեռախոսի հավելվածները"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml
index ef35e49..9c1c2e0 100644
--- a/packages/CompanionDeviceManager/res/values-in/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-in/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> mengakses <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"smartwatch"</string>
<string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk dikelola oleh <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Aplikasi diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan berinteraksi dengan notifikasi dan mengakses izin Telepon, SMS, Kontak, Kalender, Log panggilan, dan Perangkat di sekitar."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikasi diperlukan untuk mengelola <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> akan diizinkan berinteraksi dengan izin ini:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Izinkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk mengakses informasi ini dari ponsel Anda"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Layanan lintas perangkat"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> untuk menstreaming aplikasi di antara perangkat Anda"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ini termasuk akses Mikrofon, Kamera, dan Lokasi, serta izin sensitif lainnya di <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Anda dapat mengubah izin ini kapan saja di Setelan pada <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikon Aplikasi"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Tombol Informasi Lainnya"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telepon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontak"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Perangkat di sekitar"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foto dan media"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifikasi"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikasi"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Dapat mengakses nomor telepon dan info jaringan. Diperlukan untuk melakukan panggilan dan VoIP, pesan suara, pengalihan panggilan, dan pengeditan log panggilan"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Dapat membaca, membuat, atau mengedit daftar kontak, serta mengakses daftar kontak untuk semua akun yang digunakan di perangkat"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Dapat membaca semua notifikasi, termasuk informasi seperti kontak, pesan, dan foto"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streaming aplikasi ponsel"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml
index 9ca64a5..3f8c1c3 100644
--- a/packages/CompanionDeviceManager/res/values-is/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-is/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Veita <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aðgang að <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"úr"</string>
<string name="chooser_title" msgid="2262294130493605839">"Velja <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sem <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> á að stjórna"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Forritið er nauðsynlegt til að hafa umsjón með <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær aðgang að tilkynningum og heimildum síma, SMS, tengiliða, dagatals, símtalaskráa og nálægra tækja."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Forritið er nauðsynlegt til að hafa umsjón með <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> fær aðgang að eftirfarandi heimildum:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Veita <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aðgang að þessum upplýsingum úr símanum þínum"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Þjónustur á milli tækja"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> sendir beiðni um heimild til straumspilunar forrita á milli tækjanna þinna fyrir hönd <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Þetta kann að fela í sér aðgang að hljóðnema, myndavél og staðsetningu og aðrar heimildir fyrir viðkvæmu efni í <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Hægt er að breyta þessum heimildum hvenær sem er í stillingunum í <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Tákn forrits"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Hnappur fyrir upplýsingar"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Sími"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Tengiliðir"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Dagatal"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Nálæg tæki"</string>
<string name="permission_storage" msgid="6831099350839392343">"Myndir og efni"</string>
<string name="permission_notification" msgid="693762568127741203">"Tilkynningar"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Forrit"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Fær aðgang að símanúmeri og netkerfisupplýsingum. Nauðsynlegt til að hringja símtöl og netsímtöl, fyrir talhólf, framsendingu símtala og breytingar símtalaskráa"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Getur lesið, búið til eða breytt tengiliðalista og fær auk þess aðgang að tengiliðalista allra reikninga sem eru notaðir í tækinu"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Getur lesið allar tilkynningar, þar á meðal upplýsingar á borð við tengiliði, skilaboð og myndir"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streymdu forritum símans"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml
index 67ed6b8..1d53be9 100644
--- a/packages/CompanionDeviceManager/res/values-it/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-it/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Consenti all\'app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di accedere <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"orologio"</string>
<string name="chooser_title" msgid="2262294130493605839">"Scegli un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> da gestire con <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Questa app è necessaria per gestire <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> potrà interagire con le tue notifiche e accedere alle autorizzazioni Telefono, SMS, Contatti, Calendario, Registri chiamate e Dispositivi nelle vicinanze."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Questa app è necessaria per gestire <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> potrà interagire con le seguenti autorizzazioni:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Consenti a <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> di accedere a queste informazioni dal tuo telefono"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Servizi cross-device"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede per conto del tuo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> l\'autorizzazione a trasmettere app in streaming tra i dispositivi"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Potrebbero essere incluse le autorizzazioni di accesso al microfono, alla fotocamera e alla posizione, nonché altre autorizzazioni sensibili su <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Puoi cambiare queste autorizzazioni in qualsiasi momento nelle Impostazioni su <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icona dell\'app"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Pulsante Altre informazioni"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefono"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contatti"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendario"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivi nelle vicinanze"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foto e contenuti multimediali"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifiche"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"App"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Può accedere al tuo numero di telefono e alle informazioni della rete. Necessaria per chiamate e VoIP, segreteria, deviazione delle chiamate e modifica dei registri chiamate"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Può leggere, creare o modificare l\'elenco contatti, nonché accedere all\'elenco contatti di tutti gli account usati sul dispositivo"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Puoi leggere tutte le notifiche, incluse le informazioni come contatti, messaggi e foto"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Trasmetti in streaming le app del tuo telefono"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
index 8689fea..a169c78 100644
--- a/packages/CompanionDeviceManager/res/values-iw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"אישור לאפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong&g; לגשת אל <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"שעון"</string>
<string name="chooser_title" msgid="2262294130493605839">"בחירת <xliff:g id="PROFILE_NAME">%1$s</xliff:g> לניהול באמצעות <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"האפליקציה הזו נחוצה כדי לנהל את <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g> תוכל לבצע פעולות בהתראות ותקבל הרשאות גישה לטלפון, ל-SMS לאנשי הקשר, ליומן, ליומני השיחות ולמכשירים בקרבת מקום."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"האפליקציה הזו נחוצה כדי לנהל את <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME">%2$s</xliff:g> תוכל לקיים אינטראקציה עם ההרשאות הבאות:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"מתן אישור לאפליקציה <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> לגשת למידע הזה מהטלפון שלך"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"שירותים למספר מכשירים"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה עבור מכשיר <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> כדי לשדר אפליקציות בין המכשירים שלך"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>ההרשאות עשויות לכלול גישה למיקרופון, למצלמה ולמיקום, וכן גישה למידע רגיש אחר ב-</strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p&gt; <p>אפשר לשנות את ההרשאות האלה בכל שלב בהגדרות של <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"סמל האפליקציה"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"לחצן מידע נוסף"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"טלפון"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"אנשי קשר"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"יומן"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"מכשירים בקרבת מקום"</string>
<string name="permission_storage" msgid="6831099350839392343">"תמונות ומדיה"</string>
<string name="permission_notification" msgid="693762568127741203">"התראות"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"אפליקציות"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"אפשרות לגשת למספר הטלפון ופרטי הרשת שלך. הדבר נדרש לצורך ביצוע שיחות ו-VoIP, להודעה קולית, להפניית שיחות ולעריכת יומני שיחות"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"אפשרות לקרוא, ליצור או לערוך את רשימת אנשי הקשר שלנו, וגם לגשת לרשימה של כל החשבונות שבהם נעשה שימוש במכשיר שלך"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"גישת קריאה לכל ההתראות, כולל מידע כמו אנשי קשר, הודעות ותמונות."</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"שידור אפליקציות מהטלפון"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml
index f6321b5..686e2dd 100644
--- a/packages/CompanionDeviceManager/res/values-ja/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> へのアクセスを許可"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ウォッチ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> の管理対象となる<xliff:g id="PROFILE_NAME">%1$s</xliff:g>の選択"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"このアプリは<xliff:g id="DEVICE_NAME">%1$s</xliff:g>の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> は、通知の使用と、電話、SMS、連絡先、カレンダー、通話履歴、付近のデバイスの権限へのアクセスが可能となります。"</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"このアプリは<xliff:g id="DEVICE_NAME">%1$s</xliff:g>の管理に必要です。<xliff:g id="APP_NAME">%2$s</xliff:g> は、次の権限の使用が可能となります。"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"スマートフォンのこの情報へのアクセスを <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> に許可"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"クロスデバイス サービス"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> に代わってデバイス間でアプリをストリーミングする権限をリクエストしています"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>これには、<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> のマイク、カメラ、位置情報へのアクセスや、その他の機密情報に関わる権限が含まれる可能性があります。</p> <p>これらの権限は <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> の [設定] でいつでも変更できます。</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"アプリのアイコン"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"詳細情報ボタン"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"電話"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"連絡先"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"カレンダー"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"付近のデバイス"</string>
<string name="permission_storage" msgid="6831099350839392343">"写真とメディア"</string>
<string name="permission_notification" msgid="693762568127741203">"通知"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"アプリ"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"電話番号とネットワーク情報にアクセスできます。電話と VoIP の発信、ボイスメールの送信、通話のリダイレクト、通話履歴の編集に必要です"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"連絡先リストの読み取り、作成、編集を行えるほか、デバイスで使用するすべてのアカウントのリストにアクセスできます"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"連絡先、メッセージ、写真に関する情報を含め、すべての通知を読み取ることができます"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"スマートフォンのアプリをストリーミングします"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml
index e31ff8a..b0ef1c3 100644
--- a/packages/CompanionDeviceManager/res/values-ka/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ka/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"დაუშვით <strong><xliff:g id="APP_NAME">%1$s</xliff:g>-ის</strong>, წვდომა თქვენს <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g>-ზე</strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"საათი"</string>
<string name="chooser_title" msgid="2262294130493605839">"აირჩიეთ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, რომელიც უნდა მართოს <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>-მა"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"ეს აპი საჭიროა, რომ მართოთ თქვენი <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> შეძლებს თქვენს შეტყობინებებთან ინტერაქციას და თქვენი ტელეფონის, SMS-ების, კონტაქტებისა, კალენდრის, ზარების ჟურნალისა და ახლომახლო მოწყობილობების ნებართვებზე წვდომას."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"ეს აპი საჭიროა, რომ მართოთ თქვენი <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> შეძლებს ინტერაქციას შემდეგი ნებართვებით:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"ნება დართეთ, რომ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> აპს ჰქონდეს ამ ინფორმაციაზე წვდომა თქვენი ტელეფონიდან"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"მოწყობილობათშორისი სერვისები"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს უფლებას თქვენი <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ის სახელით, რომ მოწყობილობებს შორის აპების სტრიმინგი შეძლოს"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>აღნიშნული შეიძლება მოიცავდეს მიკროფონზე, კამერასა და მდებარეობაზე წვდომას თუ სხვა ნებართვას სენსიტიურ ინფორმაციაზე <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>-ში.</p> <p>ამ ნებართვების შეცვლა ნებისმიერ დროს შეგიძლიათ თქვენი პარამეტრებიდან <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>-ში.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"აპის ხატულა"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"დამატებითი ინფორმაციის ღილაკი"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Phone"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"კონტაქტები"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"კალენდარი"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"ახლომახლო მოწყობილობები"</string>
<string name="permission_storage" msgid="6831099350839392343">"ფოტოები და მედია"</string>
<string name="permission_notification" msgid="693762568127741203">"შეტყობინებები"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"აპები"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"შეუძლია თქვენი ტელეფონის ნომერსა და ქსელის ინფორმაციაზე წვდომა. საჭიროა ზარების განსახორციელებლად და VoIP-ისთვის, ხმოვანი ფოსტისთვის, ზარის გადამისამართებისა და ზარების ჟურნალების რედაქტირებისთვის"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"შეუძლია ჩვენი კონტაქტების სიის წაკითხვა, შექმნა ან რედაქტირება, ასევე, თქვენს მოწყობილობაზე გამოყენებული ყველა ანგარიშის კონტაქტების სიაზე წვდომა"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"შეუძლია წაიკითხოს ყველა შეტყობინება, მათ შორის ისეთი ინფორმაცია, როგორიცაა კონტაქტები, ტექსტური შეტყობინებები და ფოტოები"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"თქვენი ტელეფონის აპების სტრიმინგი"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml
index f82a1d5..18ab580 100644
--- a/packages/CompanionDeviceManager/res/values-kk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> құрылғысын пайдалануға рұқсат беру"</string>
<string name="profile_name_watch" msgid="576290739483672360">"сағат"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> арқылы басқарылатын <xliff:g id="PROFILE_NAME">%1$s</xliff:g> құрылғысын таңдаңыз"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына хабарландыруларға қатысты әрекет жасау, телефон, SMS, контактілер, күнтізбе, қоңырау журналдары қолданбаларын және маңайдағы құрылғыларды пайдалану рұқсаттары беріледі."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Қолданба <xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысын басқару үшін қажет. <xliff:g id="APP_NAME">%2$s</xliff:g> қолданбасына осы рұқсаттар беріледі:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына телефоныңыздағы осы ақпаратты пайдалануға рұқсат беріңіз."</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Аралық құрылғы қызметтері"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> атынан құрылғылар арасында қолданбалар трансляциялау үшін рұқсат сұрайды."</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Оларға микрофонды, камераны және геодеректі пайдалану рұқсаттары, сондай-ақ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> құрылғысына берілетін басқа да құпия ақпарат рұқсаттары кіруі мүмкін.</p> <p>Бұл рұқсаттарды кез келген уақытта <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> құрылғысындағы параметрлерден өзгерте аласыз.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Қолданба белгішесі"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"\"Қосымша ақпарат\" түймесі"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Телефон"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Контактілер"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Күнтізбе"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Маңайдағы құрылғылар"</string>
<string name="permission_storage" msgid="6831099350839392343">"Фотосуреттер мен медиафайлдар"</string>
<string name="permission_notification" msgid="693762568127741203">"Хабарландырулар"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Қолданбалар"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Телефон нөміріңізге және желі ақпаратына қол жеткізе алады. Қоңырау шалу, VoIP, дауыстық хабар жіберу, қоңырау бағытын ауыстыру және қоңырау журналдарын өзгерту үшін қажет."</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Контактілер тізімін оқуға, жасауға немесе өзгертуге, сондай-ақ құрылғыңызда қолданылатын барлық аккаунт тізімін пайдалануға рұқсат беріледі."</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Барлық хабарландыруды, соның ішінде контактілер, хабарлар және фотосуреттер сияқты ақпаратты оқи алады."</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Телефон қолданбаларын трансляциялайды."</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml
index 07a195a..c90b3a2 100644
--- a/packages/CompanionDeviceManager/res/values-km/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-km/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ចូលប្រើប្រាស់ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> របស់អ្នក"</string>
<string name="profile_name_watch" msgid="576290739483672360">"នាឡិកា"</string>
<string name="chooser_title" msgid="2262294130493605839">"ជ្រើសរើស <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ដើម្បីឱ្យស្ថិតក្រោមការគ្រប់គ្រងរបស់ <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យធ្វើអន្តរកម្មជាមួយការជូនដំណឹងរបស់អ្នក និងចូលប្រើការអនុញ្ញាតទូរសព្ទ, SMS, ទំនាក់ទំនង, ប្រតិទិន, កំណត់ហេតុហៅទូរសព្ទ និងឧបករណ៍នៅជិតរបស់អ្នក។"</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"ត្រូវការកម្មវិធីនេះ ដើម្បីគ្រប់គ្រង <xliff:g id="DEVICE_NAME">%1$s</xliff:g> របស់អ្នក។ <xliff:g id="APP_NAME">%2$s</xliff:g> នឹងត្រូវបានអនុញ្ញាតឱ្យធ្វើអន្តរកម្មជាមួយការអនុញ្ញាតទាំងនេះ៖"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"អនុញ្ញាតឱ្យ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ចូលប្រើព័ត៌មាននេះពីទូរសព្ទរបស់អ្នក"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"សេវាកម្មឆ្លងកាត់ឧបករណ៍"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> របស់អ្នក ដើម្បីបញ្ចាំងកម្មវិធីរវាងឧបករណ៍របស់អ្នក"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>សកម្មភាពនេះអាចរួមបញ្ចូលការចូលប្រើទីតាំង កាមេរ៉ា និងមីក្រូហ្វូន និងការអនុញ្ញាតដែលមានលក្ខណៈរសើបផ្សេងទៀតនៅលើ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>។</p> <p>អ្នកអាចប្ដូរការអនុញ្ញាតទាំងនេះបានគ្រប់ពេលវេលានៅក្នុងការកំណត់នៅលើ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>។</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"រូបកម្មវិធី"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"ប៊ូតុងព័ត៌មានបន្ថែម"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"ទូរសព្ទ"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"ប្រតិទិន"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"ឧបករណ៍នៅជិត"</string>
<string name="permission_storage" msgid="6831099350839392343">"រូបថត និងមេឌៀ"</string>
<string name="permission_notification" msgid="693762568127741203">"ការជូនដំណឹង"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"កម្មវិធី"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"អាចចូលមើលលេខទូរសព្ទ និងព័ត៌មានបណ្ដាញរបស់អ្នក។ ត្រូវបានតម្រូវសម្រាប់ការហៅទូរសព្ទនិង VoIP, សារជាសំឡេង, ការបញ្ជូនបន្តការហៅទូរសព្ទ និងការកែកំណត់ហេតុហៅទូរសព្ទ"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"អាចអាន បង្កើត ឬកែបញ្ជីទំនាក់ទំនងរបស់យើង ក៏ដូចជាចូលប្រើបញ្ជីគណនីទាំងអស់ដែលត្រូវបានប្រើនៅលើឧបករណ៍របស់អ្នក"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"អាចអានការជូនដំណឹងទាំងអស់ រួមទាំងព័ត៌មានដូចជាទំនាក់ទំនង សារ និងរូបថត"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"ផ្សាយកម្មវិធីរបស់ទូរសព្ទអ្នក"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml
index b453f3b0..f60f7bc 100644
--- a/packages/CompanionDeviceManager/res/values-kn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"ನಿಮ್ಮ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ಅನ್ನು ಪ್ರವೇಶಿಸಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಿ"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ವೀಕ್ಷಿಸಿ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ಮೂಲಕ ನಿರ್ವಹಿಸಬೇಕಾದ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು ಆ್ಯಪ್ನ ಅಗತ್ಯವಿದೆ. ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಮತ್ತು ನಿಮ್ಮ ಫೋನ್, SMS, ಸಂಪರ್ಕಗಳು, Calendar, ಕರೆಯ ಲಾಗ್ಗಳು ಹಾಗೂ ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳ ಅನುಮತಿಗಳನ್ನು ಪ್ರವೇಶಿಸಲು <xliff:g id="APP_NAME">%2$s</xliff:g> ಗೆ ಅನುಮತಿಸಲಾಗುತ್ತದೆ."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"ನಿಮ್ಮ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು ಆ್ಯಪ್ನ ಅಗತ್ಯವಿದೆ. <xliff:g id="APP_NAME">%2$s</xliff:g> ಗೆ ಈ ಅನುಮತಿಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಅನುಮತಿಸಲಾಗುವುದು:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"ನಿಮ್ಮ ಫೋನ್ ಮೂಲಕ ಈ ಮಾಹಿತಿಯನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಗೆ ಅನುಮತಿಸಿ"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"ಕ್ರಾಸ್-ಡಿವೈಸ್ ಸೇವೆಗಳು"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆ್ಯಪ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನ ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸಿಕೊಳ್ಳುತ್ತಿದೆ"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>ಇದು <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> ನಲ್ಲಿನ ಮೈಕ್ರೊಫೋನ್, ಕ್ಯಾಮರಾ ಮತ್ತು ಸ್ಥಳ ಆ್ಯಕ್ಸೆಸ್ ಹಾಗೂ ಇತರ ಸೂಕ್ಷ್ಮ ಅನುಮತಿಗಳನ್ನು ಹೊಂದಿರಬಹುದು<p></p> <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> ನಲ್ಲಿನ ನಿಮ್ಮ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ನೀವು ಈ ಅನುಮತಿಗಳನ್ನು ಯಾವಾಗ ಬೇಕಾದರೂ ಬದಲಾಯಿಸಬಹುದು.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ಆ್ಯಪ್ ಐಕಾನ್"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"ಹೆಚ್ಚಿನ ಮಾಹಿತಿಯ ಬಟನ್"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"ಫೋನ್"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"ಸಂಪರ್ಕಗಳು"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳು"</string>
<string name="permission_storage" msgid="6831099350839392343">"ಫೋಟೋಗಳು ಮತ್ತು ಮಾಧ್ಯಮ"</string>
<string name="permission_notification" msgid="693762568127741203">"ಅಧಿಸೂಚನೆಗಳು"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"ಆ್ಯಪ್ಗಳು"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"ನಿಮ್ಮ ಫೋನ್ ಸಂಖ್ಯೆ ಮತ್ತು ನೆಟ್ವರ್ಕ್ ಮಾಹಿತಿಯನ್ನು ಪ್ರವೇಶಿಸಬಹುದು. ಕರೆಗಳನ್ನು ಮಾಡಲು ಮತ್ತು VoIP, ಧ್ವನಿಮೇಲ್, ಕರೆ ಮರುನಿರ್ದೇಶನ ಮತ್ತು ಕರೆಯ ಲಾಗ್ಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಲು ಅಗತ್ಯವಿದೆ"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"ನಮ್ಮ ಸಂಪರ್ಕ ಪಟ್ಟಿಯನ್ನು ಓದಬಹುದು, ರಚಿಸಬಹುದು ಅಥವಾ ಎಡಿಟ್ ಮಾಡಬಹುದು, ಹಾಗೆಯೇ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಬಳಸಲಾದ ಎಲ್ಲಾ ಖಾತೆಗಳ ಪಟ್ಟಿಯನ್ನು ಪ್ರವೇಶಿಸಬಹುದು"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"ಸಂಪರ್ಕಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ಫೋಟೋಗಳಂತಹ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಂತೆ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ಓದಬಹುದು"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"ನಿಮ್ಮ ಫೋನ್ನ ಆ್ಯಪ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಿ"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index 361d3b2..3442ab2 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 내 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> 기기에 액세스하도록 허용"</string>
<string name="profile_name_watch" msgid="576290739483672360">"시계"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>에서 관리할 <xliff:g id="PROFILE_NAME">%1$s</xliff:g>을(를) 선택"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 알림과 상호작용하고 내 전화, SMS, 연락처, Calendar, 통화 기록, 근처 기기에 대한 권한을 갖게 됩니다."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 기기를 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 다음 권한과 상호작용할 수 있습니다."</string>
<string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>이 휴대전화의 이 정보에 액세스하도록 허용합니다."</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"교차 기기 서비스"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 대신 기기 간에 앱을 스트리밍할 수 있는 권한을 요청하고 있습니다."</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>여기에는 <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>에서 허용했던 마이크, 카메라, 위치 정보 액세스 권한 및 기타 민감한 권한이 포함될 수 있습니다.</p> <p>언제든지 <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>의 설정에서 이러한 권한을 변경할 수 있습니다.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"앱 아이콘"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"추가 정보 버튼"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"전화"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"연락처"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"캘린더"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"근처 기기"</string>
<string name="permission_storage" msgid="6831099350839392343">"사진 및 미디어"</string>
<string name="permission_notification" msgid="693762568127741203">"알림"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"앱"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"전화번호 및 네트워크 정보에 액세스할 수 있습니다. 전화 걸기 및 VoIP, 음성사서함, 통화 리디렉션, 통화 기록 수정 시 필요합니다."</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"연락처 목록을 읽고, 만들고, 수정할 수 있으며 기기에서 사용되는 모든 계정의 목록에도 액세스할 수 있습니다."</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"연락처, 메시지, 사진 등의 정보를 포함한 모든 알림을 읽을 수 있습니다."</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"휴대전화의 앱을 스트리밍합니다."</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index 57b2747..36a72ff 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> түзмөгүңүзгө кирүүгө уруксат бериңиз"</string>
<string name="profile_name_watch" msgid="576290739483672360">"саат"</string>
<string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> тарабынан башкарылсын"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Бул колдонмо <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүздү тескөө үчүн керек. <xliff:g id="APP_NAME">%2$s</xliff:g> билдирмелериңизди көрүп, телефонуңуз, SMS билдирүүлөр, байланыштар, жылнаама, чалуулар тизмеси жана жакын жердеги түзмөктөргө болгон уруксаттарды пайдалана алат."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Бул колдонмо <xliff:g id="DEVICE_NAME">%1$s</xliff:g> түзмөгүңүздү тескөө үчүн керек. <xliff:g id="APP_NAME">%2$s</xliff:g> төмөнкү уруксаттарды пайдалана алат:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосуна телефонуңуздагы ушул маалыматты көрүүгө уруксат бериңиз"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Түзмөктөр аралык кызматтар"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрүңүздүн ортосунда колдонмолорду өткөрүүгө уруксат сурап жатат"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Бул уруксаттарга микрофонго, камерага жана жайгашкан жерге кирүү мүмкүнчүлүгү жана <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> түзмөгүндөгү башка купуя маалыматты көрүүгө уруксаттар кириши мүмкүн.</p> <p>Бул уруксаттарды каалаган убакта <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> түзмөгүндөгү Жөндөөлөрдөн өзгөртө аласыз.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Колдонмонун сүрөтчөсү"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Дагы маалымат баскычы"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Телефон"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Байланыштар"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Жылнаама"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Жакын жердеги түзмөктөр"</string>
<string name="permission_storage" msgid="6831099350839392343">"Сүрөттөр жана медиафайлдар"</string>
<string name="permission_notification" msgid="693762568127741203">"Билдирмелер"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Колдонмолор"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Телефонуңуздун номерин жана тармак тууралуу маалыматты көрө алат. Чалуу жана VoIP, үн почтасы, чалууларды багыттоо жана чалуулар тизмесин түзөтүү үчүн талап кылынат"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Байланыштар тизмесин окуп, түзүп же түзөтүп жана түзмөгүңүздөгү бардык аккаунттардагы тизмелерге кире алат"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Бардык билдирмелерди, анын ичинде байланыштар, билдирүүлөр жана сүрөттөр сыяктуу маалыматты окуй алат"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Телефондогу колдонмолорду алып ойнотуу"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml
index 9ec7136..9283eb7 100644
--- a/packages/CompanionDeviceManager/res/values-lo/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lo/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"ອະນຸຍາດ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ໃຫ້ເຂົ້າເຖິງ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ຂອງທ່ານໄດ້"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ໂມງ"</string>
<string name="chooser_title" msgid="2262294130493605839">"ເລືອກ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ເພື່ອໃຫ້ຖືກຈັດການໂດຍ <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"ຕ້ອງໃຊ້ແອັບດັ່ງກ່າວເພື່ອຈັດການ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ຂອງທ່ານ. <xliff:g id="APP_NAME">%2$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ໂຕ້ຕອບກັບການແຈ້ງເຕືອນຂອງທ່ານ ແລະ ເຂົ້າເຖິງການອະນຸຍາດໂທລະສັບ, SMS, ລາຍຊື່ຜູ້ຕິດຕໍ່, ປະຕິທິນ, ບັນທຶກການໂທ ແລະ ອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງຂອງທ່ານ."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"ຕ້ອງໃຊ້ແອັບດັ່ງກ່າວເພື່ອຈັດການ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ຂອງທ່ານ. <xliff:g id="APP_NAME">%2$s</xliff:g> ຈະໄດ້ຮັບອະນຸຍາດໃຫ້ໂຕ້ຕອບກັບການອະນຸຍາດເຫຼົ່ານີ້:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"ອະນຸຍາດ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ໃຫ້ເຂົ້າເຖິງຂໍ້ມູນນີ້ຈາກໂທລະສັບຂອງທ່ານໄດ້"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"ບໍລິການຂ້າມອຸປະກອນ"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມຂອງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ເພື່ອສະຕຣີມແອັບລະຫວ່າງອຸປະກອນຂອງທ່ານ"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>ນີ້ອາດຮວມສິດເຂົ້າເຖິງໄມໂຄຣໂຟນ, ກ້ອງຖ່າຍຮູບ ແລະ ສະຖານທີ່, ຮວມທັງການອະນຸຍາດທີ່ລະອຽດອ່ອນອື່ນໆຢູ່ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>ທ່ານສາມາດປ່ຽນການອະນຸຍາດເຫຼົ່ານີ້ຕອນໃດກໍໄດ້ໃນການຕັ້ງຄ່າຂອງທ່ານຢູ່ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ໄອຄອນແອັບ"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"ປຸ່ມຂໍ້ມູນເພີ່ມເຕີມ"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"ໂທລະສັບ"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"ລາຍຊື່ຜູ້ຕິດຕໍ່"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"ປະຕິທິນ"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"ອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງ"</string>
<string name="permission_storage" msgid="6831099350839392343">"ຮູບພາບ ແລະ ມີເດຍ"</string>
<string name="permission_notification" msgid="693762568127741203">"ການແຈ້ງເຕືອນ"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"ແອັບ"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"ສາມາດເຂົ້າເຖິງເບີໂທລະສັບ ແລະ ຂໍ້ມູນເຄືອຂ່າຍຂອງທ່ານ. ເຊິ່ງຈຳເປັນສຳລັບການໂທ ແລະ VoIP, ຂໍ້ຄວາມສຽງ, ການປ່ຽນເສັ້ນທາງການໂທ ແລະ ການແກ້ໄຂບັນທຶກການໂທ"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"ສາມາດອ່ານ, ສ້າງ ຫຼື ແກ້ໄຂລາຍຊື່ຜູ້ຕິດຕໍ່ຂອງພວກເຮົາ, ຮວມທັງເຂົ້າເຖິງລາຍຊື່ຂອງບັນຊີທັງໝົດທີ່ໃຊ້ຢູ່ໃນອຸປະກອນຂອງທ່ານ"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"ສາມາດອ່ານການແຈ້ງເຕືອນທັງໝົດ, ຮວມທັງຂໍ້ມູນ ເຊັ່ນ: ລາຍຊື່ຜູ້ຕິດຕໍ່, ຂໍ້ຄວາມ ແລະ ຮູບພາບ"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"ສະຕຣີມແອັບຂອງໂທລະສັບທ່ານ"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml
index 6640595..3483cf3 100644
--- a/packages/CompanionDeviceManager/res/values-lt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lt/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Leisti <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pasiekti jūsų <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"laikrodį"</string>
<string name="chooser_title" msgid="2262294130493605839">"Jūsų <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, kurį valdys <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> (pasirinkite)"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Programa reikalinga norint tvarkyti jūsų <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. „<xliff:g id="APP_NAME">%2$s</xliff:g>“ bus leidžiama sąveikauti su pranešimų funkcija ir pasiekti Telefono, SMS, Kontaktų, Kalendoriaus, Skambučių žurnalų ir Įrenginių netoliese leidimus."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Programa reikalinga norint tvarkyti jūsų <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. „<xliff:g id="APP_NAME">%2$s</xliff:g>“ bus leidžiama sąveikauti su toliau nurodytais leidimais."</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Leisti <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pasiekti šią informaciją iš jūsų telefono"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Pasl. keliuose įrenginiuose"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo jūsų „<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>“ vardu, kad galėtų srautu perduoti programas iš vieno įrenginio į kitą"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Gali būti įtraukti prieigos prie mikrofono, kameros ir vietovės leidimai ir kiti leidimai pasiekti neskelbtiną informaciją <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> įrenginyje.</p> <p>Šiuos leidimus galite bet kada pakeisti „Nustatymų“ skiltyje <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> įrenginyje.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Programos piktograma"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Mygtukas „Daugiau informacijos“"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefonas"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontaktai"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalendorius"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Įrenginiai netoliese"</string>
<string name="permission_storage" msgid="6831099350839392343">"Nuotraukos ir medija"</string>
<string name="permission_notification" msgid="693762568127741203">"Pranešimai"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Programos"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Galima pasiekti telefono numerio ir tinklo informaciją. Reikalinga norint skambinti ir naudoti „VoIP“, balso paštą, skambučių peradresavimo funkciją bei redaguoti skambučių žurnalus"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Galima skaityti, kurti ar redaguoti kontaktų sąrašą bei pasiekti visų įrenginyje naudojamų paskyrų sąrašą"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Galima skaityti visus pranešimus, įskaitant tokią informaciją kaip kontaktai, pranešimai ir nuotraukos"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefono programų perdavimas srautu"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml
index ae24636..039cc4d 100644
--- a/packages/CompanionDeviceManager/res/values-lv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Atļauja lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> piekļūt jūsu ierīcei <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"pulkstenis"</string>
<string name="chooser_title" msgid="2262294130493605839">"Profila (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) izvēle, ko pārvaldīt lietotnē <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Šī lietotne ir nepieciešama jūsu ierīces (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) pārvaldībai. Lietotnei <xliff:g id="APP_NAME">%2$s</xliff:g> tiks atļauts mijiedarboties ar jūsu paziņojumiem un piekļūt šādām atļaujām: Tālrunis, Īsziņas, Kontaktpersonas, Kalendārs, Zvanu žurnāli un Tuvumā esošas ierīces."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Šī lietotne ir nepieciešama jūsu ierīces (<xliff:g id="DEVICE_NAME">%1$s</xliff:g>) pārvaldībai. Lietotnei <xliff:g id="APP_NAME">%2$s</xliff:g> tiks atļauts mijiedarboties ar šīm atļaujām:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Atļaut lietotnei <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> piekļūt šai informācijai no jūsu tālruņa"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Vairāku ierīču pakalpojumi"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju straumēt lietotnes starp jūsu ierīcēm šīs ierīces vārdā: <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Tās var būt mikrofona, kameras, atrašanās vietas piekļuves atļaujas un citas sensitīvas atļaujas ierīcē <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Atļaujas jebkurā brīdī varat mainīt ierīces <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p> iestatījumos."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Lietotnes ikona"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Plašākas informācijas poga"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Tālrunis"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"Īsziņas"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontaktpersonas"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalendārs"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Tuvumā esošas ierīces"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotoattēli un multivides faili"</string>
<string name="permission_notification" msgid="693762568127741203">"Paziņojumi"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Lietotnes"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Var piekļūt jūsu tālruņa numuram un tīkla informācijai. Nepieciešama, lai veiktu zvanus un VoIP zvanus, izmantotu balss pastu, pāradresētu zvanus un rediģētu zvanu žurnālus."</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Var lasīt, izveidot vai rediģēt jūsu kontaktpersonu sarakstu, kā arī piekļūt visu jūsu ierīcē izmantoto kontu kontaktpersonu sarakstiem"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Var lasīt visus paziņojumus, tostarp tādu informāciju kā kontaktpersonas, ziņojumi un fotoattēli."</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Straumēt jūsu tālruņa lietotnes"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml
index cdecb20..938932d 100644
--- a/packages/CompanionDeviceManager/res/values-mk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Дозволете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да пристапува до вашиот <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"часовник"</string>
<string name="chooser_title" msgid="2262294130493605839">"Изберете <xliff:g id="PROFILE_NAME">%1$s</xliff:g> со којшто ќе управува <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Апликацијата е потребна за управување со вашиот <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да остварува интеракција со известувањата и да пристапува до дозволите за „Телефон“, SMS, „Контакти“, „Календар“, „Евиденција на повици“ и „Уреди во близина“."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Апликацијата е потребна за управување со вашиот <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ќе може да остварува интеракција со следниве дозволи:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Овозможете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да пристапува до овие податоци на телефонот"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Повеќенаменски услуги"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на вашиот <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за да стримува апликации помеѓу вашите уреди"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ова може да вклучува пристап до микрофон, камера и локација и други чувствителни дозволи на <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Може да ги промените дозволиве во секое време во вашите „Поставки“ на <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Икона на апликацијата"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Копче за повеќе информации"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Телефон"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Контакти"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Календар"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Уреди во близина"</string>
<string name="permission_storage" msgid="6831099350839392343">"Аудиовизуелни содржини"</string>
<string name="permission_notification" msgid="693762568127741203">"Известувања"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Апликации"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Може да пристапува до вашиот телефонски број и податоците за мрежата. Потребно за упатување повици и VoIP, говорна пошта, пренасочување повици и изменување евиденција на повици"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Може да го чита, создава или изменува вашиот список со контакти, како и да пристапува до списоците со контакти на сите сметки што се користат на уредот"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"може да ги чита сите известувања, вклучително и податоци како контакти, пораки и фотографии"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Стримувајте ги апликациите на телефонот"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml
index 8361bd8..511e9eb 100644
--- a/packages/CompanionDeviceManager/res/values-mn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-д таны <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д хандахыг зөвшөөрнө үү"</string>
<string name="profile_name_watch" msgid="576290739483672360">"цаг"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>-н удирдах<xliff:g id="PROFILE_NAME">%1$s</xliff:g>-г сонгоно уу"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Энэ апп таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д таны мэдэгдэлтэй харилцан үйлдэл хийж, Утас, SMS, Харилцагчид, Календарь, Дуудлагын жагсаалт болон Ойролцоох төхөөрөмжүүдийн зөвшөөрөлд хандахыг зөвшөөрнө."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Энэ апп таны <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г удирдахад шаардлагатай. <xliff:g id="APP_NAME">%2$s</xliff:g>-д эдгээр зөвшөөрөлтэй харилцан үйлдэл хийхийг зөвшөөрнө:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-д таны утаснаас энэ мэдээлэлд хандахыг зөвшөөрнө үү"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Төхөөрөмж хоорондын үйлчилгээ"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Таны төхөөрөмжүүд хооронд апп дамжуулахын тулд <xliff:g id="APP_NAME">%1$s</xliff:g> таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н өмнөөс зөвшөөрөл хүсэж байна"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Үүнд Микрофон, Камер болон Байршлын хандалт болон <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> дээрх бусад эмзэг зөвшөөрөл багтаж болно.</p> <p>Та эдгээр зөвшөөрлийг <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> дээрх Тохиргоо хэсэгтээ хүссэн үедээ өөрчлөх боломжтой.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Aппын дүрс тэмдэг"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Дэлгэрэнгүй мэдээллийн товчлуур"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Утас"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Харилцагчид"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Календарь"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Ойролцоох төхөөрөмжүүд"</string>
<string name="permission_storage" msgid="6831099350839392343">"Зураг болон медиа"</string>
<string name="permission_notification" msgid="693762568127741203">"Мэдэгдэл"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Аппууд"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Таны утасны дугаар болон сүлжээний мэдээлэлд хандах боломжтой. Дуудлага хийх, VoIP, дуут шуудан, дуудлагыг дахин чиглүүлэх болон дуудлагын жагсаалтыг засахад шаардлагатай"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Манай харилцагчийн жагсаалтыг унших, үүсгэх эсвэл засахаас гадна таны төхөөрөмж дээр ашигласан бүх бүртгэлийн жагсаалтад хандах боломжтой"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Харилцагчид, мессеж болон зураг зэрэг мэдээллийг оруулаад бүх мэдэгдлийг унших боломжтой"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Утасныхаа аппуудыг дамжуулаарай"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml
index 65be367..37a8349 100644
--- a/packages/CompanionDeviceManager/res/values-mr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"तुमचे <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> अॅक्सेस करण्यासाठी <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला अनुमती द्या"</string>
<string name="profile_name_watch" msgid="576290739483672360">"वॉच"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> द्वारे व्यवस्थापित करण्यासाठी <xliff:g id="PROFILE_NAME">%1$s</xliff:g> निवडा"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"तुमचे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला तुमच्या सूचनांशी संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क कॅलेंडर, कॉल लॉग व जवळपासच्या डिव्हाइसच्या परवानग्या अॅक्सेस करण्याची अनुमती मिळेल."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"तुमचे <xliff:g id="DEVICE_NAME">%1$s</xliff:g> व्यवस्थापित करण्यासाठी हे ॲप आवश्यक आहे. <xliff:g id="APP_NAME">%2$s</xliff:g> ला पुढील परवानग्यांशी संवाद साधण्याची अनुमती मिळेल:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ला ही माहिती तुमच्या फोनवरून अॅक्सेस करण्यासाठी अनुमती द्या"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"क्रॉस-डिव्हाइस सेवा"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"तुमच्या डिव्हाइसदरम्यान ॲप्स स्ट्रीम करण्यासाठी <xliff:g id="APP_NAME">%1$s</xliff:g> हे तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>यामध्ये <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g><strong> वरील मायक्रोफोन, कॅमेरा आणि स्थान अॅक्सेस व इतर संवेदनशील परवानग्यांचा समावेश असू शकतो </strong>.</p> <p>तुम्ही <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> वर तुमच्या सेटिंग्ज मध्ये या परवानग्या कधीही बदलू शकता</strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"अॅप आयकन"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"अधिक माहिती बटण"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"फोन"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"एसएमएस"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"जवळपासची डिव्हाइस"</string>
<string name="permission_storage" msgid="6831099350839392343">"फोटो आणि मीडिया"</string>
<string name="permission_notification" msgid="693762568127741203">"सूचना"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"ॲप्स"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"तुमचा फोन नंबर आणि नेटवर्कची माहिती अॅक्सेस करू शकते. कॉल करणे व VoIP, व्हॉइसमेल, कॉल रीडिरेक्ट करणे आणि कॉल लॉग संपादित करणे यांसाठी आवश्यक"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"आमची संपर्क सूची रीड, तयार आणि संपादित करू शकते, तसेच तुमच्या डिव्हाइसवर वापरल्या जाणाऱ्या खात्यांची सूची अॅक्सेस करू शकते"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"संपर्क, मेसेज आणि फोटो यांसारख्या माहितीचा समावेश असलेल्या सर्व सूचना वाचू शकते"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"तुमच्या फोनवरील ॲप्स स्ट्रीम करा"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml
index a2a8e2a..ac9acbc 100644
--- a/packages/CompanionDeviceManager/res/values-ms/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ms/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Benarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> mengakses <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> anda"</string>
<string name="profile_name_watch" msgid="576290739483672360">"jam tangan"</string>
<string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk diurus oleh <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Apl ini diperlukan untuk mengurus <xliff:g id="DEVICE_NAME">%1$s</xliff:g> anda. <xliff:g id="APP_NAME">%2$s</xliff:g> akan dibenarkan berinteraksi dengan pemberitahuan anda dan mengakses kebenaran Telefon, SMS, Kenalan, Kalendar, Log panggilan serta Peranti berdekatan anda."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Apl ini diperlukan untuk mengurus <xliff:g id="DEVICE_NAME">%1$s</xliff:g> anda. <xliff:g id="APP_NAME">%2$s</xliff:g> akan dibenarkan berinteraksi dengan kebenaran ini:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Benarkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> mengakses maklumat ini daripada telefon anda"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Perkhidmatan silang peranti"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang meminta kebenaran bagi pihak <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda untuk menstrim apl antara peranti anda"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ini mungkin termasuk akses Mikrofon, Kamera dan Lokasi serta kebenaran sensitif lain pada <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Anda boleh menukar kebenaran ini pada bila-bila masa dalam Tetapan anda pada <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikon Apl"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Butang Maklumat Lagi"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kenalan"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalendar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Peranti berdekatan"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foto dan media"</string>
<string name="permission_notification" msgid="693762568127741203">"Pemberitahuan"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Apl"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Boleh mengakses nombor telefon dan maklumat rangkaian anda. Diperlukan untuk membuat panggilan dan VoIP, mel suara, ubah hala panggilan dan mengedit log panggilan"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Boleh membaca, membuat atau mengedit senarai kenalan kami, serta mengakses senarai semua akaun yang digunakan pada peranti anda"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Boleh membaca semua pemberitahuan, termasuk maklumat seperti kenalan, mesej dan foto"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Strim apl telefon anda"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml
index 82a0282..01f4d32 100644
--- a/packages/CompanionDeviceManager/res/values-nb/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Tillat at <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> bruker <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"klokke"</string>
<string name="chooser_title" msgid="2262294130493605839">"Velg <xliff:g id="PROFILE_NAME">%1$s</xliff:g> som skal administreres av <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å samhandle med varslene dine og har tilgang til tillatelsene for telefon, SMS, kontakter, kalender, samtalelogger og enheter i nærheten."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Appen kreves for å administrere <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillatelse til å samhandle med disse tillatelsene:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Gi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tilgang til denne informasjonen fra telefonen din"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjenester på flere enheter"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse til å strømme apper mellom enhetene dine, på vegne av <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dette kan inkludere tilgang til mikrofon, kamera og posisjon samt andre sensitive tillatelser på <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Du kan når som helst endre disse tillatelsene i innstillingene på <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Appikon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Mer informasjon-knapp"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontakter"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Enheter i nærheten"</string>
<string name="permission_storage" msgid="6831099350839392343">"Bilder og medier"</string>
<string name="permission_notification" msgid="693762568127741203">"Varsler"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Apper"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Kan se telefonnummeret ditt og nettverksinformasjon. Dette kreves for samtaler og VoIP, talepost, viderekobling av anrop og endring av samtalelogger"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Kan lese, opprette eller endre kontaktlisten din og se listen over alle kontoene som brukes på enheten"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kan lese alle varsler, inkludert informasjon som kontakter, meldinger og bilder"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Strøm appene på telefonen"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml
index ed8890b..28366f6 100644
--- a/packages/CompanionDeviceManager/res/values-nl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nl/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang geven tot je <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"horloge"</string>
<string name="chooser_title" msgid="2262294130493605839">"Een <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiezen om te beheren met <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"De app is vereist om je <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te beheren. <xliff:g id="APP_NAME">%2$s</xliff:g> kan interactie hebben met je meldingen en toegang krijgen tot rechten voor Telefoon, Sms, Contacten, Agenda, Gesprekslijsten en Apparaten in de buurt."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"De app is vereist om je <xliff:g id="DEVICE_NAME">%1$s</xliff:g> te beheren. <xliff:g id="APP_NAME">%2$s</xliff:g> heeft toestemming om interactie te hebben met de volgende rechten:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> toegang geven tot deze informatie op je telefoon"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device-services"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens jouw <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> toestemming om apps te streamen tussen je apparaten"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dit kan toegang tot de microfoon, camera en je locatie en andere gevoelige rechten op je <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> omvatten.</p> <p>Je kunt deze rechten op elk moment wijzigen in je Instellingen op de <xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App-icoon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Knop Meer informatie"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefoon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"Sms"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contacten"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Agenda"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Apparaten in de buurt"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foto\'s en media"</string>
<string name="permission_notification" msgid="693762568127741203">"Meldingen"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Heeft toegang tot je telefoonnummer en netwerkgegevens. Vereist voor bellen en VoIP, voicemail, gesprek omleiden en gesprekslijsten bewerken."</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Kan je contactenlijst lezen, maken of bewerken, en heeft toegang tot de contactenlijst voor alle accounts die op je apparaat worden gebruikt."</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kan alle meldingen lezen, waaronder informatie zoals contacten, berichten en foto\'s"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream de apps van je telefoon"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml
index 225074c..5f7f52e 100644
--- a/packages/CompanionDeviceManager/res/values-or/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-or/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"ଆପଣଙ୍କ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>କୁ ଆକ୍ସେସ କରିବା ପାଇଁ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ୱାଚ୍"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ଦ୍ୱାରା ପରିଚାଳିତ ହେବା ପାଇଁ ଏକ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>କୁ ବାଛନ୍ତୁ"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"ଆପଣଙ୍କ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଆପ ଆବଶ୍ୟକ। ଆପଣଙ୍କ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ଏବଂ ଆପଣଙ୍କର ଫୋନ, SMS, କଣ୍ଟାକ୍ଟ, କେଲେଣ୍ଡର, କଲ ଲଗ ଓ ଆଖପାଖର ଡିଭାଇସ ଅନୁମତିଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ।"</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"ଆପଣଙ୍କ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ ଆପ ଆବଶ୍ୟକ। ଏହି ଅନୁମତିଗୁଡ଼ିକ ସହ ଇଣ୍ଟରାକ୍ଟ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%2$s</xliff:g>କୁ ଅନୁମତି ଦିଆଯିବ:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"ଆପଣଙ୍କ ଫୋନରୁ ଏହି ସୂଚନାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"କ୍ରସ-ଡିଭାଇସ ସେବାଗୁଡ଼ିକ"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"ଆପଣଙ୍କ ଡିଭାଇସଗୁଡ଼ିକ ମଧ୍ୟରେ ଆପ୍ସକୁ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କର <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>ଏହା <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>ରେ ମାଇକ୍ରୋଫୋନ, କ୍ୟାମେରା ଏବଂ ଲୋକେସନ ଆକ୍ସେସ ଓ ଅନ୍ୟ ସମ୍ବେଦନଶୀଳ ଅନୁମତିଗୁଡ଼ିକୁ ଅନ୍ତର୍ଭୁକ୍ତ କରିପାରେ।</p> <p>ଆପଣ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>ରେ ଯେ କୌଣସି ସମୟରେ ଆପଣଙ୍କ ସେଟିଂସରେ ଏହି ଅନୁମତିଗୁଡ଼ିକୁ ପରିବର୍ତ୍ତନ କରିପାରିବେ।</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ଆପ ଆଇକନ"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"ଅଧିକ ସୂଚନା ବଟନ"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"ଫୋନ"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"କଣ୍ଟାକ୍ଟଗୁଡ଼ିକ"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"କେଲେଣ୍ଡର"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକ"</string>
<string name="permission_storage" msgid="6831099350839392343">"ଫଟୋ ଏବଂ ମିଡିଆ"</string>
<string name="permission_notification" msgid="693762568127741203">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"ଆପ୍ସ"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"ଆପଣଙ୍କ ଫୋନ ନମ୍ବର ଏବଂ ନେଟୱାର୍କ ସୂଚନା ଆକ୍ସେସ କରିପାରିବେ।କଲ କରିବା ଓ VoIP, ଭଏସମେଲ, କଲ ଡାଇରେକ୍ଟ ଏବଂ କଲ ଲଗକୁ ଏଡିଟ କରିବା ପାଇଁ ଆବଶ୍ୟକ"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"ଆପଣଙ୍କ କଣ୍ଟାକ୍ଟ ତାଲିକା ପଢ଼ିପାରିବେ, ତିଆରି କିମ୍ବା ଏଡିଟ କରିପାରିବେ ତଥା ଆପଣଙ୍କ ଡିଭାଇସରେ ବ୍ୟବହାର କରାଯାଇଥିବା ସମସ୍ତ ଆକାଉଣ୍ଟର ତାଲିକାକୁ ଆକ୍ସେସ କରିପାରିବେ"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"ଯୋଗାଯୋଗ, ମେସେଜ ଏବଂ ଫଟୋଗୁଡ଼ିକ ପରି ସୂଚନା ସମେତ ସମସ୍ତ ବିଜ୍ଞପ୍ତିକୁ ପଢ଼ିପାରିବ"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"ଆପଣଙ୍କ ଫୋନର ଆପ୍ସକୁ ଷ୍ଟ୍ରିମ କରନ୍ତୁ"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml
index 00fbc3c..4d9b8d3 100644
--- a/packages/CompanionDeviceManager/res/values-pa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡੇ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ਸਮਾਰਟ-ਵਾਚ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤੇ ਜਾਣ ਲਈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ਚੁਣੋ"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"ਇਹ ਐਪ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਤੁਹਾਡੀਆਂ ਸੂਚਨਾਵਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ, SMS, ਸੰਪਰਕਾਂ, ਕੈਲੰਡਰ, ਕਾਲ ਲੌਗਾਂ ਅਤੇ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਸੰਬੰਧੀ ਇਜਾਜ਼ਤਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ।"</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"ਇਹ ਐਪ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ। <xliff:g id="APP_NAME">%2$s</xliff:g> ਨੂੰ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਨਾਲ ਅੰਤਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਹੋਵੇਗੀ:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੋਂ ਇਸ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"ਕ੍ਰਾਸ-ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸਾਂ ਵਿਚਕਾਰ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>ਇਸ ਵਿੱਚ ਮਾਈਕ੍ਰੋਫ਼ੋਨ, ਕੈਮਰਾ, ਟਿਕਾਣਾ ਪਹੁੰਚ ਅਤੇ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> \'ਤੇ ਮੌਜੂਦ ਹੋਰ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਸੰਬੰਧੀ ਇਜਾਜ਼ਤਾਂ ਸ਼ਾਮਲ ਹੋ ਸਕਦੀਆਂ ਹਨ।</p> <p>ਤੁਸੀਂ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> \'ਤੇ ਮੌਜੂਦ ਆਪਣੀਆਂ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ ਕਦੇ ਵੀ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ਐਪ ਪ੍ਰਤੀਕ"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"ਹੋਰ ਜਾਣਕਾਰੀ ਬਟਨ"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"ਫ਼ੋਨ"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"ਸੰਪਰਕ"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"ਕੈਲੰਡਰ"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸ"</string>
<string name="permission_storage" msgid="6831099350839392343">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ"</string>
<string name="permission_notification" msgid="693762568127741203">"ਸੂਚਨਾਵਾਂ"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"ਐਪਾਂ"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"ਤੁਹਾਡੇ ਫ਼ੋਨ ਨੰਬਰ ਅਤੇ ਨੈੱਟਵਰਕ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ। ਇਹ ਕਾਲਾਂ ਅਤੇ VoIP, ਵੌਇਸਮੇਲ, ਕਾਲ ਨੂੰ ਰੀਡਾਇਰੈਕਟ ਕਰਨ ਅਤੇ ਕਾਲ ਲੌਗਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰਨ ਲਈ ਲੋੜੀਂਦੀ ਹੈ"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"ਤੁਹਾਡੀ ਸੰਪਰਕ ਸੂਚੀ ਨੂੰ ਪੜ੍ਹ, ਬਣਾ ਸਕਦੀ ਹੈ ਜਾਂ ਉਸਦਾ ਸੰਪਾਦਨ ਕਰ ਸਕਦੀ ਹੈ ਅਤੇ ਇਸ ਤੋਂ ਇਲਾਵਾ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਵਰਤੇ ਗਏ ਸਾਰੇ ਖਾਤਿਆਂ ਦੀ ਸੂਚੀ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"ਤੁਸੀਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਪੜ੍ਹ ਸਕਦੇ ਹੋ, ਜਿਨ੍ਹਾਂ ਵਿੱਚ ਸੰਪਰਕਾਂ, ਸੁਨੇਹਿਆਂ ਅਤੇ ਫ਼ੋਟੋਆਂ ਵਰਗੀ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੁੰਦੀ ਹੈ"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"ਆਪਣੇ ਫ਼ੋਨ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰੋ"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml
index f312507..2c7a038 100644
--- a/packages/CompanionDeviceManager/res/values-pl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Zezwól na dostęp aplikacji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> do urządzenia <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"zegarek"</string>
<string name="chooser_title" msgid="2262294130493605839">"Wybierz profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, którym ma zarządzać aplikacja <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Aplikacja jest niezbędna do zarządzania profilem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła korzystać z powiadomień oraz uprawnień dotyczących telefonu, SMS-ów, kontaktów, kalendarza, rejestrów połączeń i Urządzeń w pobliżu."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikacja jest niezbędna do zarządzania profilem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła korzystać z tych powiadomień:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Zezwól urządzeniu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na dostęp do tych informacji na Twoim telefonie"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Usługi na innym urządzeniu"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> o uprawnienia dotyczące strumieniowego odtwarzania treści z aplikacji na innym urządzeniu"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Mogą one obejmować dane dostęp do Mikrofonu, Aparatu i lokalizacji oraz inne uprawnienia newralgiczne na urządzeniu <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Możesz w dowolnym momencie zmienić uprawnienia na urządzeniu <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikacji"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Przycisk – więcej informacji"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS-y"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontakty"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalendarz"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Urządzenia w pobliżu"</string>
<string name="permission_storage" msgid="6831099350839392343">"Zdjęcia i multimedia"</string>
<string name="permission_notification" msgid="693762568127741203">"Powiadomienia"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacje"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Może korzystać z numeru telefonu i informacji o sieci. Wymagane przy nawiązywaniu połączeń, korzystaniu z VoIP oraz poczty głosowej, przekierowywaniu połączeń oraz edytowaniu rejestrów połączeń"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Może odczytywać, tworzyć i edytować listę kontaktów, jak również korzystać z listy wszystkich kont używanych na urządzeniu"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Może odczytywać wszystkie powiadomienia, w tym informacje takie jak kontakty, wiadomości i zdjęcia"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Odtwarzaj strumieniowo aplikacje z telefonu"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
index a11f7ff..5f3eeeb 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aceda ao seu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"relógio"</string>
<string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerido pela app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"A app é necessária para gerir o seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A app <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com as suas notificações e aceder às autorizações do Telemóvel, SMS, Contactos, Calendário, Registos de chamadas e Dispositivos próximos."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"A app é necessária para gerir o seu <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. A app <xliff:g id="APP_NAME">%2$s</xliff:g> vai poder interagir com estas autorizações:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Permita que a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aceda a estas informações do seu telemóvel"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Serviços entre dispositivos"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do seu dispositivo <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para fazer stream de apps entre os seus dispositivos"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Isto pode incluir o acesso ao microfone, câmara e localização, bem como a outras autorizações confidenciais no dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Pode alterar estas autorizações em qualquer altura nas Definições do dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ícone da app"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Botão Mais informações"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telemóvel"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Contactos"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendário"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos próximos"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos e multimédia"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificações"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Pode aceder ao seu número de telefone e informações da rede. É precisa para fazer chamadas e VoIP (voice over Internet Protocol), o correio de voz, redirecionar a chamada e editar registos de chamadas"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Pode ler, criar ou editar a nossa lista de contactos e aceder à lista de todas as contas usadas no seu dispositivo"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificações, incluindo informações como contactos, mensagens e fotos"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Faça stream das apps do telemóvel"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml
index 7c33ab3..35c0888 100644
--- a/packages/CompanionDeviceManager/res/values-ro/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Permite ca <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să acceseze dispozitivul <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ceas"</string>
<string name="chooser_title" msgid="2262294130493605839">"Alege un profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> pe care să îl gestioneze <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Aplicația este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să interacționeze cu notificările tale și să îți acceseze permisiunile pentru Telefon, SMS, Agendă, Calendar, Jurnale de apeluri și Dispozitive din apropiere."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplicația este necesară pentru a gestiona <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> va putea să interacționeze cu următoarele permisiuni:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Permite ca <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> să acceseze aceste informații de pe telefon"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Servicii pe mai multe dispozitive"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> de a reda în stream aplicații între dispozitivele tale"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Aici pot fi incluse accesul la microfon, la camera foto, la locație și alte permisiuni de accesare a informațiilor sensibile de pe <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Poți modifica oricând aceste permisiuni din Setările de pe <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Pictograma aplicației"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Butonul Mai multe informații"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Agendă"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Dispozitive din apropiere"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotografii și media"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificări"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Aplicații"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Poate să acceseze numărul tău de telefon și informațiile despre rețea. Permisiunea este necesară pentru inițierea apelurilor și VoIP, mesaje vocale, redirecționarea apelurilor și editarea jurnalelor de apeluri"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Poate să citească, să creeze sau să editeze agenda, precum și să acceseze lista tuturor conturilor folosite pe dispozitiv"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Poate să citească toate notificările, inclusiv informații cum ar fi agenda, mesajele și fotografiile"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Să redea în stream aplicațiile telefonului"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml
index d82fa76..612601a 100644
--- a/packages/CompanionDeviceManager/res/values-ru/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Разрешите приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> доступ к устройству <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"часы"</string>
<string name="chooser_title" msgid="2262294130493605839">"Выберите устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), которым будет управлять приложение <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Это приложение необходимо для управления устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Приложение \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" получит доступ к уведомлениям, а также следующие разрешения: телефон, SMS, контакты, календарь, список вызовов и устройства поблизости."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Это приложение необходимо для управления устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". Приложение \"<xliff:g id="APP_NAME">%2$s</xliff:g>\" получит следующие разрешения:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Разрешите приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> получать эту информацию с вашего телефона"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Сервисы стриминга приложений"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запрашивает разрешение от имени вашего устройства <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, чтобы транслировать приложения между вашими устройствами."</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Сюда может входить доступ к микрофону, камере и данным о местоположении, а также другие разрешения на доступ к конфиденциальной информации на устройстве <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Вы можете в любое время изменить разрешения в настройках устройства <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Значок приложения"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Кнопка информации"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Телефон"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Контакты"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Календарь"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Устройства поблизости"</string>
<string name="permission_storage" msgid="6831099350839392343">"Фотографии и медиафайлы"</string>
<string name="permission_notification" msgid="693762568127741203">"Уведомления"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Приложения"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Доступ к номеру телефона и информации о сети. Это разрешение необходимо, чтобы совершать обычные и VoIP-звонки, отправлять голосовые сообщения, перенаправлять вызовы и редактировать списки вызовов."</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Возможность читать, создавать и редактировать список контактов, а также получать доступ к списку всех аккаунтов на вашем устройстве."</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Чтение всех уведомлений, в том числе сведений о контактах, сообщениях и фотографиях."</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Трансляция приложений с телефона."</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml
index f58f042..0743dba 100644
--- a/packages/CompanionDeviceManager/res/values-si/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-si/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට ඔබගේ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> කළමනාකරණය කිරීමට ඉඩ දෙන්න"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ඔරලෝසුව"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> මගින් කළමනාකරණය කරනු ලැබීමට <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ක් තෝරන්න"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"ඔබේ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනා කිරීමට මෙම යෙදුම අවශ්යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> ඔබේ දැනුම්දීම් සමග අන්තර්ක්රියා කිරීමට සහ ඔබේ දුරකථනය, කෙටිපණිවුඩය, සම්බන්ධතා, දිනදර්ශනය, ඇමතුම් ලොග සහ අවට උපාංග අවසර වෙත ප්රවේශ වීමට ඉඩ දෙයි."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"ඔබේ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> කළමනා කිරීමට මෙම යෙදුම අවශ්යයි. <xliff:g id="APP_NAME">%2$s</xliff:g> හට මෙම අවසර සමග අන්තර්ක්රියා කිරීමට අවසර දෙනු ලැබේ:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> හට ඔබගේ දුරකථනයෙන් මෙම තොරතුරුවලට ප්රවේශ වීමට ඉඩ දෙන්න"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"හරස්-උපාංග සේවා"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබගේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> වෙනුවෙන් ඔබගේ උපාංග අතර යෙදුම් ප්රවාහ කිරීමට අවසරය ඉල්ලමින් සිටියි"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>මෙයට මයික්රෆෝනය, කැමරාව සහ ස්ථාන ප්රවේශය සහ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> හි අනෙකුත් සංවේදී අවසර ඇතුළත් විය හැකිය.</p> <p>ඔබට ඔබගේ සැකසීම් තුළ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> හිදී ඕනෑම වේලාවක මෙම අවසර වෙනස් කළ හැකිය.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"යෙදුම් නිරූපකය"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"වැඩිදුර තොරතුරු බොත්තම"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"දුරකථනය"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"කෙටිපණිවුඩය"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"සම්බන්ධතා"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"දිනදර්ශනය"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"අවට උපාංග"</string>
<string name="permission_storage" msgid="6831099350839392343">"ඡායාරූප සහ මාධ්ය"</string>
<string name="permission_notification" msgid="693762568127741203">"දැනුම්දීම්"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"යෙදුම්"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"ඔබේ දුරකථන අංකයට සහ ජාල තොරතුරු වෙත ප්රවේශ විය හැක. ඇමතුම් සහ VoIP, හඬ තැපැල්, ඇමතුම් ප්රතියෝමුව, සහ ඇමතුම් සටහන් සංස්කරණය සඳහා අවශ්යයි."</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"අපගේ සම්බන්ධතා ලැයිස්තුව කියවීමට, සෑදීමට, හෝ සංස්කරණ කිරීමට මෙන් ම ඔබේ උපාංගය මත භාවිත කරනු ලබන සියලුම ගිණුම් ලැයිස්තු වෙත ප්රවේශ වීමට හැකිය"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"සම්බන්ධතා, පණිවිඩ සහ ඡායාරූප වැනි තොරතුරු ඇතුළුව සියලු දැනුම්දීම් කියවිය හැකිය"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"ඔබේ දුරකථනයේ යෙදුම් ප්රවාහ කරන්න"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml
index 492a235..933c289 100644
--- a/packages/CompanionDeviceManager/res/values-sk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prístup k zariadeniu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"hodinky"</string>
<string name="chooser_title" msgid="2262294130493605839">"Vyberte profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ktorý bude spravovať aplikácia <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Aplikácia sa vyžaduje na správu zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude môcť interagovať s vašimi upozorneniami a získa prístup k povoleniam telefónu, SMS, kontaktov, kalendára, zoznamu hovorov a zariadení v okolí."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikácia sa vyžaduje na správu zariadenia <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> bude môcť interagovať s týmito povoleniami:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Povoľte aplikácii <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> prístup k týmto informáciám z vášho telefónu"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Služby pre viacero zariadení"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje povolenie na streamovanie aplikácií medzi vašimi zariadeniami v mene tohto zariadenia (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>)"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Môžu zahŕňať prístup k mikrofónu, kamere a polohe a ďalšie citlivé povolenia v zariadení <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Tieto povolenia môžete kedykoľvek zmeniť v Nastaveniach v zariadení <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikácie"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Tlačidlo Ďalšie informácie"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefón"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontakty"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalendár"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Zariadenia v okolí"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotky a médiá"</string>
<string name="permission_notification" msgid="693762568127741203">"Upozornenia"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikácie"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Má prístup k vášmu telefónnemu číslu a informáciám o sieti. Vyžaduje sa na volanie a VoIP, fungovanie hlasovej schránky, presmerovanie hovorov a upravovanie zoznamu hovorov"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Môže čítať, vytvárať alebo upravovať náš zoznam kontaktov, ako aj získavať prístup k zoznamu všetkých účtov používaných vo vašom zariadení"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Môže čítať všetky upozornenia vrátane informácií, ako sú kontakty, správy a fotky"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streamovať aplikácie telefónu"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml
index 09ebcdf..676da68 100644
--- a/packages/CompanionDeviceManager/res/values-sl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Aplikaciji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dovolite dostop do naprave <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ura"</string>
<string name="chooser_title" msgid="2262294130493605839">"Izbira naprave <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ki jo bo upravljala aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bosta omogočeni interakcija z obvestili in uporaba dovoljenj Telefon, SMS, Stiki, Koledar, Dnevniki klicev in Naprave v bližini."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Ta aplikacija je potrebna za upravljanje naprave »<xliff:g id="DEVICE_NAME">%1$s</xliff:g>«. Aplikaciji <xliff:g id="APP_NAME">%2$s</xliff:g> bo omogočena interakcija s temi dovoljenji:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Dovolite, da <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dostopa do teh podatkov v vašem telefonu"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Storitve za zunanje naprave"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>« zahteva dovoljenje za pretočno predvajanje aplikacij v vaših napravah."</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>To lahko vključuje dostop do mikrofona, fotoaparata in lokacije ter druga občutljiva dovoljenja v napravi <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Ta dovoljenja lahko kadar koli spremenite v nastavitvah v napravi <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikacije"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Gumb za več informacij"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Stiki"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Koledar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Naprave v bližini"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotografije in predstavnost"</string>
<string name="permission_notification" msgid="693762568127741203">"Obvestila"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Lahko dostopa do telefonske številke in podatkov o omrežju. Obvezno za opravljanje klicev, uporabo storitve VoIP in glasovne pošte, preusmerjanje klicev in urejanje dnevnikov klicev."</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Lahko bere, ustvarja ali ureja seznam stikov in dostopa do seznama stikov vseh računov, uporabljenih v napravi."</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Lahko bere vsa obvestila, vključno s podatki, kot so stiki, sporočila in fotografije."</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Pretočno predvajanje aplikacij telefona"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml
index 3879cb3..7bd86ce 100644
--- a/packages/CompanionDeviceManager/res/values-sq/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të ketë qasje te <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"ora inteligjente"</string>
<string name="chooser_title" msgid="2262294130493605839">"Zgjidh një profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> që do të menaxhohet nga <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Aplikacioni nevojitet për të menaxhuar profilin tënd të \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> do të lejohet të ndërveprojë me njoftimet e tua dhe të ketë qasje te lejet e \"Telefonit\", \"SMS-ve\", \"Kontakteve\", \"Kalendarit\", \"Evidencave të telefonatave\" dhe të \"Pajisjeve në afërsi\"."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Aplikacioni nevojitet për të menaxhuar profilin tënd të \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\". <xliff:g id="APP_NAME">%2$s</xliff:g> do të lejohet të ndërveprojë me këto leje:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Lejo që <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> të ketë qasje në këtë informacion nga telefoni yt"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Shërbimet mes pajisjeve"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> për të transmetuar aplikacione ndërmjet pajisjeve të tua"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Kjo mund të përfshijë qasjen te \"Mikrofoni\", \"Kamera\", \"Vendndodhja\" dhe leje të tjera për informacione delikate në <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p&gtTi mund t\'i ndryshosh këto leje në çdo kohë te \"Cilësimet\" në <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona e aplikacionit"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Butoni \"Më shumë informacione\""</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefoni"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontaktet"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalendari"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Pajisjet në afërsi"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotografitë dhe media"</string>
<string name="permission_notification" msgid="693762568127741203">"Njoftimet"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacionet"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Mund të qaset te informacionet e numrit të telefonit dhe të rrjetit. Kërkohet për të bërë telefonata dhe VoIP, postë zanore, ridrejtim të telefonatës dhe modifikim të evidencave të telefonatave"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Mund të lexojë, të krijojë ose të modifikojë listën tënde të kontakteve si dhe të qaset në listën e të gjitha llogarive të përdorura në pajisjen tënde"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Mund të lexojë të gjitha njoftimet, duke përfshirë informacione si kontaktet, mesazhet dhe fotografitë"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Transmeto aplikacionet e telefonit tënd"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml
index 6ad111f..73cf13d 100644
--- a/packages/CompanionDeviceManager/res/values-sr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Дозволите да <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> приступа уређају <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"сат"</string>
<string name="chooser_title" msgid="2262294130493605839">"Одаберите профил <xliff:g id="PROFILE_NAME">%1$s</xliff:g> којим ће управљати апликација <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за интеракцију са обавештењима и приступ дозволама за телефон, SMS, контакте, календар, евиденције позива и уређаје у близини."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Апликација је потребна за управљање уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> ће добити дозволу за интеракцију са овим дозволама:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Дозволите да <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> приступа овим информацијама са телефона"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Услуге на више уређаја"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> захтева дозволу у име уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> за стримовање апликација између уређаја"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>То може да обухвата приступ микрофону, камери и локацији, као и другим осетљивим дозволама на уређају <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>У сваком тренутку можете да промените те дозволе у Подешавањима на уређају <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Икона апликације"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Дугме за више информација"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Телефон"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Контакти"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Календар"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Уређаји у близини"</string>
<string name="permission_storage" msgid="6831099350839392343">"Слике и медији"</string>
<string name="permission_notification" msgid="693762568127741203">"Обавештења"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Апликације"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Може да приступа вашем броју телефона и информацијама о мрежи. Неопходно за упућивање позива и VoIP, говорну пошту, преусмеравање позива и измене евиденције позива"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Може да чита, креира или мења листу контаката, као и да приступа листи свих налога који се користе на вашем уређају"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Може да чита сва обавештења, укључујући информације попут контаката, порука и слика"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Стримујте апликације на телефону"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml
index cd5d8de..ceb7e40 100644
--- a/packages/CompanionDeviceManager/res/values-sv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Tillåt att <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> får åtkomst till din <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"klocka"</string>
<string name="chooser_title" msgid="2262294130493605839">"Välj en <xliff:g id="PROFILE_NAME">%1$s</xliff:g> för hantering av <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att interagera med dina aviseringar och får åtkomst till behörigheterna Telefon, Sms, Kontakter, Kalender, Samtalsloggar och Enheter i närheten."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Appen behövs för att hantera <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. <xliff:g id="APP_NAME">%2$s</xliff:g> får tillåtelse att interagera med följande behörigheter:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Ge <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> åtkomstbehörighet till denna information på telefonen"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Tjänster för flera enheter"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet att låta <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> streama appar mellan enheter"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Det kan gälla behörighet till mikrofon, kamera och plats och åtkomstbehörighet till andra känsliga uppgifter på <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Du kan när som helst ändra behörigheterna i inställningarna på <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.lt;/p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Appikon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Knappen Mer information"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"Sms"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontakter"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Enheter i närheten"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foton och media"</string>
<string name="permission_notification" msgid="693762568127741203">"Aviseringar"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Appar"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Kan få åtkomst till ditt telefonnummer och din nätverksinformation. Krävs för att ringa samtal och VoIP-samtal, röstbrevlådan, omdirigering av samtal och redigering av samtalsloggar"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Kan läsa, skapa eller redigera din kontaktlista samt få åtkomst till kontaktlistan för alla konton som används på enheten"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kan läsa alla aviseringar, inklusive information som kontakter, meddelanden och foton"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Streama telefonens appar"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml
index b44b59c..3a09d68 100644
--- a/packages/CompanionDeviceManager/res/values-te/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-te/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"మీ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ను యాక్సెస్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను అనుమతించండి"</string>
<string name="profile_name_watch" msgid="576290739483672360">"వాచ్"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ద్వారా మేనేజ్ చేయబడటానికి ఒక <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ను ఎంచుకోండి"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"మీ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. మీ నోటిఫికేషన్లతో ఇంటరాక్ట్ అవ్వడానికి, అలాగే మీ ఫోన్, SMS, కాంటాక్ట్లు, క్యాలెండర్, కాల్ లాగ్లు, సమీపంలోని పరికరాల అనుమతులను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"మీ <xliff:g id="DEVICE_NAME">%1$s</xliff:g>ను మేనేజ్ చేయడానికి ఈ యాప్ అవసరం. ఈ అనుమతులతో ఇంటరాక్ట్ అవ్వడానికి <xliff:g id="APP_NAME">%2$s</xliff:g> అనుమతించబడుతుంది:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"మీ ఫోన్ నుండి ఈ సమాచారాన్ని యాక్సెస్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> యాప్ను అనుమతించండి"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Cross-device services"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"మీ పరికరాల మధ్య యాప్లను స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p><strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>లో మైక్రోఫోన్, కెమెరా, లొకేషన్ యాక్సెస్, ఇంకా ఇతర గోప్యమైన సమాచార యాక్సెస్ అనుమతులు ఇందులో ఉండవచ్చు.</p> <p>మీరు <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>లో మీ సెట్టింగ్లలో ఎప్పుడైనా ఈ అనుమతులను మార్చవచ్చు.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"యాప్ చిహ్నం"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"మరింత సమాచారం బటన్"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"ఫోన్"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"కాంటాక్ట్లు"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"క్యాలెండర్"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"సమీపంలోని పరికరాలు"</string>
<string name="permission_storage" msgid="6831099350839392343">"ఫోటోలు, మీడియా"</string>
<string name="permission_notification" msgid="693762568127741203">"నోటిఫికేషన్లు"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"యాప్లు"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"మీ ఫోన్ నంబర్, ఇంకా నెట్వర్క్ సమాచారాన్ని యాక్సెస్ చేయగలదు. కాల్స్ చేయడానికి, VoIP కాల్స్ చేయడానికి, వాయిస్ మెయిల్కు, కాల్ మళ్లింపునకు, ఇంకా కాల్ లాగ్లను ఎడిట్ చేయడానికి ఇది అవసరం"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"మీ కాంటాక్ట్ లిస్ట్ను చదవడం, క్రియేట్ చేయడం, లేదా ఎడిట్ చేయడంతో పాటు మీ పరికరంలో ఉపయోగించబడే ఖాతాలన్నింటి లిస్ట్ను యాక్సెస్ కూడా చేయగలదు"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"కాంటాక్ట్లు, మెసేజ్లు, ఫోటోల వంటి సమాచారంతో సహా అన్ని నోటిఫికేషన్లను చదవగలదు"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"మీ ఫోన్లోని యాప్లను స్ట్రీమ్ చేయండి"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml
index 237d129..522c29f 100644
--- a/packages/CompanionDeviceManager/res/values-th/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-th/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> เข้าถึง <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ของคุณ"</string>
<string name="profile_name_watch" msgid="576290739483672360">"นาฬิกา"</string>
<string name="chooser_title" msgid="2262294130493605839">"เลือก<xliff:g id="PROFILE_NAME">%1$s</xliff:g>ที่จะให้มีการจัดการโดย <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"ต้องใช้แอปนี้ในการจัดการ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> <xliff:g id="APP_NAME">%2$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับการแจ้งเตือนและได้รับสิทธิ์เข้าถึงโทรศัพท์, SMS, รายชื่อติดต่อ, ปฏิทิน, บันทึกการโทร และอุปกรณ์ที่อยู่ใกล้เคียง"</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"ต้องใช้แอปนี้ในการจัดการ<xliff:g id="DEVICE_NAME">%1$s</xliff:g> <xliff:g id="APP_NAME">%2$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับสิทธิ์เหล่านี้"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"อนุญาตให้ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> เข้าถึงข้อมูลนี้จากโทรศัพท์ของคุณ"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"บริการหลายอุปกรณ์"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> เพื่อสตรีมแอประหว่างอุปกรณ์ต่างๆ ของคุณ"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>โดยอาจรวมถึงสิทธิ์เข้าถึงไมโครโฟน กล้อง และตำแหน่ง ตลอดจนสิทธิ์ที่มีความละเอียดอ่อนอื่นๆ ใน <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>คุณเปลี่ยนแปลงสิทธิ์เหล่านี้ได้ทุกเมื่อในการตั้งค่าใน <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ไอคอนแอป"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"ปุ่มข้อมูลเพิ่มเติม"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"โทรศัพท์"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"รายชื่อติดต่อ"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"ปฏิทิน"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"อุปกรณ์ที่อยู่ใกล้เคียง"</string>
<string name="permission_storage" msgid="6831099350839392343">"รูปภาพและสื่อ"</string>
<string name="permission_notification" msgid="693762568127741203">"การแจ้งเตือน"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"แอป"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"สามารถเข้าถึงหมายเลขโทรศัพท์และข้อมูลเครือข่ายของคุณ จำเป็นสำหรับการโทรและ VoIP, ข้อความเสียง, การเปลี่ยนเส้นทางการโทร และการแก้ไขบันทึกการโทร"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"สามารถอ่าน สร้าง หรือแก้ไขข้อมูลรายชื่อติดต่อของเรา รวมทั้งเข้าถึงข้อมูลรายชื่อติดต่อของทุกบัญชีที่ใช้ในอุปกรณ์ของคุณ"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"สามารถอ่านการแจ้งเตือนทั้งหมด รวมถึงข้อมูลอย่างรายชื่อติดต่อ ข้อความ และรูปภาพ"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"สตรีมแอปของโทรศัพท์คุณ"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml
index 86e6898..79c23aa 100644
--- a/packages/CompanionDeviceManager/res/values-tl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na i-access ang iyong <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"relo"</string>
<string name="chooser_title" msgid="2262294130493605839">"Pumili ng <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para pamahalaan ng <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Kailangan ang app para mapamahalaan ang iyong <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na makipag-ugnayan sa mga notification mo at i-access ang iyong pahintulot sa Telepono, SMS, Mga Contact, Kalendaryo, Log ng mga tawag, at Mga kalapit na device."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Kailangan ang app para mapamahalaan ang iyong <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Papayagan ang <xliff:g id="APP_NAME">%2$s</xliff:g> na makipag-ugnayan sa mga pahintulot na ito:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Payagan ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na i-access ang impormasyong ito sa iyong telepono"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Mga cross-device na serbisyo"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ay humihiling ng pahintulot sa ngalan ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para mag-stream ng mga app sa pagitan ng mga device mo"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Posibleng kabilang dito ang access sa Mikropono, Camera, at Lokasyon, at iba pang pahintulot sa sensitibong impormasyon sa <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Puwede mong baguhin ang mga pahintulot na ito anumang oras sa iyong Mga Setting sa <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icon ng App"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Button ng Dagdag Impormasyon"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telepono"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Mga Contact"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Mga kalapit na device"</string>
<string name="permission_storage" msgid="6831099350839392343">"Mga larawan at media"</string>
<string name="permission_notification" msgid="693762568127741203">"Mga Notification"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Mga App"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Naa-access ang iyong numero ng telepono at impormasyon ng network. Kinakailangan para sa mga pagtawag at VoIP, voicemail, pag-redirect ng tawag, at pag-edit ng mga log ng tawag"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Nakaka-read, nakakagawa, o nakakapag-edit ng aming listahan ng contact, pati na rin nakaka-access ng listahan ng lahat ng account na ginamit sa iyong device"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Magbasa ng lahat ng notification, kabilang ang impormasyon gaya ng mga contact, mensahe, at larawan"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"I-stream ang mga app ng iyong telepono"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index 2cb03f7..ea4e20a 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> cihazınıza erişmesi için <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasına izin verin"</string>
<string name="profile_name_watch" msgid="576290739483672360">"saat"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> tarafından yönetilecek bir <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızın yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> adlı uygulamanın bildirimlerinizle etkileşimde bulunup Telefon, SMS, Kişiler, Takvim, Arama kayıtları ve Yakındaki cihazlar izinlerinize erişmesine izin verilir."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Bu uygulama, <xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazınızın yönetilmesi için gereklidir. <xliff:g id="APP_NAME">%2$s</xliff:g> uygulamasının şu izinlerle etkileşime girmesine izin verilir:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasının, telefonunuzdaki bu bilgilere erişmesine izin verin"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Cihazlar arası hizmetler"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g>, cihazlarınız arasında uygulama akışı gerçekleştirmek için <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınız adına izin istiyor"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Mikrofon, Kamera ve Konum erişiminin yanı sıra <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> cihazındaki diğer hassas bilgilere erişim izinleri de bu kapsamda olabilir.</p> <p>Bu izinleri istediğiniz zaman <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> cihazındaki Ayarlar bölümünden değiştirebilirsiniz.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Uygulama Simgesi"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Daha Fazla Bilgi Düğmesi"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kişiler"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Takvim"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Yakındaki cihazlar"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotoğraflar ve medya"</string>
<string name="permission_notification" msgid="693762568127741203">"Bildirimler"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Uygulamalar"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Telefon numaranıza ve ağ bilgilerinize erişebilir. Arama, VoIP, sesli mesaj, arama yönlendirme gibi işlemleri gerçekleştirmek ve arama kayıtlarını düzenlemek için gereklidir"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Kişi listesini okuyabilir, oluşturabilir veya düzenleyebilir, ayrıca cihazınızda kullanılan tüm hesapların listesine erişebilir"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kişiler, mesajlar ve fotoğraflar da dahil olmak üzere tüm bildirimleri okuyabilir"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefonunuzun uygulamalarını yayınlama"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index ed1453c..71473f7 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو اپنے <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> تک رسائی کی اجازت دیں"</string>
<string name="profile_name_watch" msgid="576290739483672360">"دیکھیں"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> کے ذریعے نظم کئے جانے کیلئے <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کو منتخب کریں"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لئے ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو آپ کی اطلاعات کے ساتھ تعامل کرنے اور آپ کے فون، SMS، رابطوں، کیلنڈر، کال لاگز اور قریبی آلات کی اجازتوں تک رسائی کی اجازت ہوگی۔"</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"آپ کے <xliff:g id="DEVICE_NAME">%1$s</xliff:g> کا نظم کرنے کے لئے ایپ کی ضرورت ہے۔ <xliff:g id="APP_NAME">%2$s</xliff:g> کو ان اجازتوں کے ساتھ تعامل کرنے کی اجازت ہوگی:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"اپنے فون سے ان معلومات تک رسائی حاصل کرنے کی <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو اجازت دیں"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"کراس ڈیوائس سروسز"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> کی جانب سے آپ کے آلات کے درمیان ایپس کی سلسلہ بندی کرنے کی اجازت کی درخواست کر رہی ہے"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>اس میں مائیکروفون، کیمرا اور مقام تک رسائی اور ;<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong&gt پر دیگر حساس اجازتیں شامل ہو سکتی ہیں۔</p> <p>آپ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g>;</strong&gt پر کسی بھی وقت اپنی ترتیبات میں ان اجازتوں کو تبدیل کر سکتے ہیں۔</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ایپ کا آئیکن"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"مزید معلومات کا بٹن"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"فون"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"رابطے"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"کیلنڈر"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"قریبی آلات"</string>
<string name="permission_storage" msgid="6831099350839392343">"تصاویر اور میڈیا"</string>
<string name="permission_notification" msgid="693762568127741203">"اطلاعات"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"ایپس"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"آپ کے فون نمبر اور نیٹ ورک کی معلومات تک رسائی حاصل کر سکتی ہے۔ کالز کرنے اور VoIP، صوتی میل، کال ری ڈائریکٹ، اور کال لاگز میں ترمیم کرنے کے لیے درکار ہے"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"ہماری رابطوں کی فہرست پڑھ سکتی ہے، اسے تخلیق سکتی ہے یا اس میں ترمیم کر سکتی ہے، نیز آپ کے آلے پر استعمال ہونے والے تمام اکاؤنٹس کی فہرست تک رسائی حاصل کر سکتی ہے"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"رابطوں، پیغامات اور تصاویر جیسی معلومات سمیت تمام اطلاعات پڑھ سکتے ہیں"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"اپنے فون کی ایپس کی سلسلہ بندی کریں"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml
index bc94509..721a338 100644
--- a/packages/CompanionDeviceManager/res/values-uz/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uz/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> qurilmasiga kirish uchun <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga ruxsat bering"</string>
<string name="profile_name_watch" msgid="576290739483672360">"soat"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> boshqaradigan <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qurilmasini tanlang"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Ilova <xliff:g id="DEVICE_NAME">%1$s</xliff:g> profilini boshqarish uchun kerak. <xliff:g id="APP_NAME">%2$s</xliff:g> ilovasiga bildirishnomalar bilan ishlash va telefon, SMS, kontaktlar, taqvim, chaqiruvlar jurnali va yaqin-atrofdagi qurilmalarga kirishga ruxsat beriladi."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Ilova <xliff:g id="DEVICE_NAME">%1$s</xliff:g> profilini boshqarish uchun kerak. <xliff:g id="APP_NAME">%2$s</xliff:g> ilovasiga quyidagi ruxsatlar bilan ishlashga ruxsat beriladi:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga telefondagi ushbu maʼlumot uchun ruxsat bering"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Qurilmalararo xizmatlar"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"Qurilamalararo ilovalar strimingi uchun <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> nomidan ruxsat soʻramoqda"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Bunga <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> qurilmasidagi Mikrofon, Kamera, Joylashuv kabi muhim ruxsatlar kirishi mumkin.</p> <p>Bu ruxsatlarni istalgan vaqt <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> Sozlamalari orqali oʻzgartirish mumkin.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ilova belgisi"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Batafsil axborot tugmasi"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Kontaktlar"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Taqvim"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Atrofdagi qurilmalar"</string>
<string name="permission_storage" msgid="6831099350839392343">"Suratlar va media"</string>
<string name="permission_notification" msgid="693762568127741203">"Bildirishnomalar"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Ilovalar"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Telefon raqamingiz va tarmoq maʼlumotlariga kira oladi. Telefon qilish va VoIP, ovozli xabar, chaqiruvlarni yoʻnaltirish va chaqiruvlar jurnallarini tahrirlash uchun talab qilinadi"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Kontaktlar roʻyxatini oʻqishi, yaratishi yoki tahrirlashi, shuningdek, qurilmangizda foydalaniladigan barcha hisoblar roʻyxatiga kirishi mumkin"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Barcha bildirishnomalarni, jumladan, kontaktlar, xabarlar va suratlarni oʻqishi mumkin"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefondagi ilovalarni translatsiya qilish"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml
index c5dd928..cb9e558 100644
--- a/packages/CompanionDeviceManager/res/values-vi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truy cập <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> của bạn"</string>
<string name="profile_name_watch" msgid="576290739483672360">"đồng hồ"</string>
<string name="chooser_title" msgid="2262294130493605839">"Chọn một <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sẽ do <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> quản lý"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"Cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g> của bạn. <xliff:g id="APP_NAME">%2$s</xliff:g> sẽ được phép tương tác với thông báo và truy cập vào Điện thoại, SMS, Danh bạ, Lịch, Nhật ký cuộc gọi và Thiết bị ở gần."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"Cần có ứng dụng này để quản lý <xliff:g id="DEVICE_NAME">%1$s</xliff:g> của bạn. <xliff:g id="APP_NAME">%2$s</xliff:g> được quyền tương tác với những chức năng sau:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Cho phép <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> truy cập vào thông tin này trên điện thoại của bạn"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Dịch vụ trên nhiều thiết bị"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang yêu cầu quyền thay cho <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> để truyền trực tuyến ứng dụng giữa các thiết bị của bạn"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Những quyền này có thể bao gồm quyền truy cập vào micrô, máy ảnh và thông tin vị trí, cũng như các quyền truy cập thông tin nhạy cảm khác trên <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Bạn có thể thay đổi những quyền này bất cứ lúc nào trong phần Cài đặt trên <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Biểu tượng ứng dụng"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Nút thông tin khác"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Điện thoại"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"Tin nhắn SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Danh bạ"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Lịch"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Thiết bị ở gần"</string>
<string name="permission_storage" msgid="6831099350839392343">"Ảnh và nội dung nghe nhìn"</string>
<string name="permission_notification" msgid="693762568127741203">"Thông báo"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Ứng dụng"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Có thể truy cập vào thông tin mạng và số điện thoại của bạn. Điện thoại cần được cấp quyền này để gọi điện và gọi bằng dịch vụ VoIP, soạn thư thoại, chuyển hướng cuộc gọi, đồng thời chỉnh sửa nhật ký cuộc gọi"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Có thể tạo, đọc, chỉnh sửa, đồng thời truy cập danh bạ của mọi tài khoản được sử dụng trên thiết bị"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Có thể đọc tất cả các thông báo, kể cả những thông tin như danh bạ, tin nhắn và ảnh"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Truyền các ứng dụng trên điện thoại của bạn"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
index b08e8f4..dad4709 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"允许<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>访问您的<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"手表"</string>
<string name="chooser_title" msgid="2262294130493605839">"选择要由<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"需要使用此应用,才能管理您的<xliff:g id="DEVICE_NAME">%1$s</xliff:g>。<xliff:g id="APP_NAME">%2$s</xliff:g>将能与通知交互,并可获得电话、短信、通讯录、日历、通话记录和附近设备的访问权限。"</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"需要使用此应用,才能管理您的<xliff:g id="DEVICE_NAME">%1$s</xliff:g>。<xliff:g id="APP_NAME">%2$s</xliff:g>可与以下权限交互:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"允许“<xliff:g id="APP_NAME">%1$s</xliff:g>”<strong></strong>访问您手机中的这项信息"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"跨设备服务"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表您的<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>请求在您的设备之间流式传输应用内容"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>这可能包括<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>的麦克风、摄像头和位置信息访问权限,以及其他敏感权限。</p> <p>您可以随时在<strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>的“设置”中更改这些权限。</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"应用图标"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"更多信息按钮"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"手机"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"短信"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"通讯录"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"日历"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"附近的设备"</string>
<string name="permission_storage" msgid="6831099350839392343">"照片和媒体内容"</string>
<string name="permission_notification" msgid="693762568127741203">"通知"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"应用"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"可以访问您的电话号码和网络信息。具备此权限才能实现电话拨打以及 VoIP、语音信箱、电话转接和通话记录编辑功能"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"可以读取、创建或修改您的联系人列表,以及访问您设备上使用的所有帐号的联系人列表"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"可以读取所有通知,包括合同、消息和照片等信息"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"流式传输手机上的应用"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
index 94ebb3d..50c4214 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"允許<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 存取您的 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"手錶"</string>
<string name="chooser_title" msgid="2262294130493605839">"選擇由 <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> 管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可存取通知、電話、短訊、通訊錄和日曆、通話記錄和附近的裝置權限。"</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"必須使用此應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可存取以下權限:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>存取您手機中的這項資料"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"跨裝置服務"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在為 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 要求權限,以在裝置之間串流應用程式內容"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>這可能包括 <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p> 的麥克風、相機和位置存取權和其他敏感資料權限。您隨時可透過 <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p> 變更這些權限。"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"應用程式圖示"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"「更多資料」按鈕"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"手機"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"短訊"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"通訊錄"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"日曆"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"附近的裝置"</string>
<string name="permission_storage" msgid="6831099350839392343">"相片和媒體"</string>
<string name="permission_notification" msgid="693762568127741203">"通知"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"應用程式"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"可存取您的電話號碼及網絡資訊。必須授予此權限才可撥打電話和 VoIP 通話、留言、轉駁來電及編輯通話記錄"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"可讀取、建立或編輯通訊錄,以及存取您裝置上所有用過的帳戶清單"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"可以讀取所有通知,包括聯絡人、訊息和電話等資訊"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"串流播放手機應用程式內容"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
index adf8708..7cbd9a7 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>存取「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」<strong></strong>"</string>
<string name="profile_name_watch" msgid="576290739483672360">"手錶"</string>
<string name="chooser_title" msgid="2262294130493605839">"選擇要讓「<xliff:g id="APP_NAME">%2$s</xliff:g>」<strong></strong>管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可存取通知、電話、簡訊、聯絡人和日曆、通話記錄和鄰近裝置的權限。"</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"你必須使用這個應用程式,才能管理「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」。「<xliff:g id="APP_NAME">%2$s</xliff:g>」將可與下列權限互動:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>存取手機中的這項資訊"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"跨裝置服務"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表你的「<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>」要求必要權限,以便在裝置之間串流傳輸應用程式內容"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>這可能包括「<xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g>」<strong></strong>.</p>的麥克風、相機和位置資訊存取權和其他機密權限。</p> <p>你隨時可透過「<xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g>」<strong></strong>的設定變更這些權限。</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"應用程式圖示"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"更多資訊按鈕"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"電話"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"簡訊"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"聯絡人"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"日曆"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"鄰近裝置"</string>
<string name="permission_storage" msgid="6831099350839392343">"相片和媒體"</string>
<string name="permission_notification" msgid="693762568127741203">"通知"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"應用程式"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"可存取你的電話號碼和網路資訊。你必須授予這項權限,才能撥打電話和進行 VoIP 通話、聽取語音留言、轉接來電,以及編輯通話記錄"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"可讀取、建立或編輯你的聯絡人清單,還能存取裝置上所有帳戶的聯絡人清單"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"可讀取所有通知,包括聯絡人、訊息和電話等資訊"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"串流傳輸手機應用程式內容"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml
index c4e634c..231f71c 100644
--- a/packages/CompanionDeviceManager/res/values-zu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zu/strings.xml
@@ -20,10 +20,8 @@
<string name="confirmation_title" msgid="3785000297483688997">"Vumela i-<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukuthi ifinyelele i-<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> yakho"</string>
<string name="profile_name_watch" msgid="576290739483672360">"buka"</string>
<string name="chooser_title" msgid="2262294130493605839">"Khetha i-<xliff:g id="PROFILE_NAME">%1$s</xliff:g> ezophathwa yi-<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
- <!-- no translation found for summary_watch (4085794790142204006) -->
- <skip />
- <!-- no translation found for summary_watch_single_device (1523091550243476756) -->
- <skip />
+ <string name="summary_watch" msgid="4085794790142204006">"I-app iyadingeka ukuphatha i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> yakho. I-<xliff:g id="APP_NAME">%2$s</xliff:g> izovunyelwa ukuthi ihlanganyele nezaziso zakho futhi ifinyelele Ifoni yakho, i-SMS, Oxhumana nabo, Ikhalenda, Amarekhodi wamakholi Nezimvume zamadivayisi aseduze."</string>
+ <string name="summary_watch_single_device" msgid="1523091550243476756">"I-app iyadingeka ukuphatha i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g> yakho. <xliff:g id="APP_NAME">%2$s</xliff:g> uzovunyelwa ukusebenzisana nalezi zimvume:"</string>
<string name="title_app_streaming" msgid="2270331024626446950">"Vumela i-<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ifinyelele lolu lwazi kusukela efonini yakho"</string>
<string name="helper_title_app_streaming" msgid="4151687003439969765">"Amasevisi amadivayisi amaningi"</string>
<string name="helper_summary_app_streaming" msgid="5977509499890099">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yakho ukuze isakaze-bukhoma ama-app phakathi kwamadivayisi akho"</string>
@@ -42,29 +40,20 @@
<string name="permission_sync_summary" msgid="4866838188678457084">"<p>Lokhu kungase kuhlanganisa Imakrofoni, Ikhamera, kanye Nokufinyelela kwendawo, kanye nezinye izimvume ezibucayi <strong>ku-<xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Ungashintsha lezi zimvume nganoma yisiphi isikhathi Kumasethingi akho <strong>ku-<xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Isithonjana Se-app"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Inkinobho Yolwazi Olwengeziwe"</string>
- <!-- no translation found for permission_phone (2661081078692784919) -->
- <skip />
- <!-- no translation found for permission_sms (6337141296535774786) -->
- <skip />
- <!-- no translation found for permission_contacts (3858319347208004438) -->
- <skip />
- <!-- no translation found for permission_calendar (6805668388691290395) -->
- <skip />
- <!-- no translation found for permission_nearby_devices (7530973297737123481) -->
- <skip />
+ <string name="permission_phone" msgid="2661081078692784919">"Ifoni"</string>
+ <string name="permission_sms" msgid="6337141296535774786">"I-SMS"</string>
+ <string name="permission_contacts" msgid="3858319347208004438">"Oxhumana nabo"</string>
+ <string name="permission_calendar" msgid="6805668388691290395">"Ikhalenda"</string>
+ <string name="permission_nearby_devices" msgid="7530973297737123481">"Amadivayisi aseduze"</string>
<string name="permission_storage" msgid="6831099350839392343">"Izithombe nemidiya"</string>
<string name="permission_notification" msgid="693762568127741203">"Izaziso"</string>
- <!-- no translation found for permission_app_streaming (6009695219091526422) -->
- <skip />
- <!-- no translation found for permission_phone_summary (6154198036705702389) -->
- <skip />
+ <string name="permission_app_streaming" msgid="6009695219091526422">"Ama-app"</string>
+ <string name="permission_phone_summary" msgid="6154198036705702389">"Ingakwazi ukufinyelela inombolo yakho yefoni kanye nolwazi lwenethiwekhi. Iyadingeka ekwenzeni amakholi ne-VoIP, ivoyisimeyili, ukuqondisa kabusha ikholi, nokuhlela amarekhodi amakholi"</string>
<string name="permission_sms_summary" msgid="5107174184224165570"></string>
- <!-- no translation found for permission_contacts_summary (7850901746005070792) -->
- <skip />
+ <string name="permission_contacts_summary" msgid="7850901746005070792">"Angafunda, asungule, noma ahlele uhlu lwethu loxhumana nabo, futhi afinyelele uhlu lwawo wonke ama-akhawunti asetshenziswa kudivayisi yakho"</string>
<string name="permission_calendar_summary" msgid="9070743747408808156"></string>
<string name="permission_nearby_devices_summary" msgid="8587497797301075494"></string>
<string name="permission_notification_summary" msgid="884075314530071011">"Ingafunda zonke izaziso, okubandakanya ulwazi olufana noxhumana nabo, imilayezo, nezithombe"</string>
- <!-- no translation found for permission_app_streaming_summary (606923325679670624) -->
- <skip />
+ <string name="permission_app_streaming_summary" msgid="606923325679670624">"Sakaza ama-app wefoni yakho"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
</resources>
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index e3ed3d9..1db1d1c 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -128,7 +128,7 @@
// TODO: handle runtime cast error
providerEnabledList as List<GetCredentialProviderData>, context)
// TODO: covert from real requestInfo
- val requestDisplayInfo = com.android.credentialmanager.getflow.RequestDisplayInfo("tribank")
+ val requestDisplayInfo = com.android.credentialmanager.getflow.RequestDisplayInfo("the app")
return GetCredentialUiState(
providerEnabledList,
GetScreenState.PRIMARY_SELECTION,
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 61e11fe..f1f453d 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
@@ -62,7 +62,6 @@
import com.android.credentialmanager.common.material.ModalBottomSheetValue.Expanded
import com.android.credentialmanager.common.material.ModalBottomSheetValue.HalfExpanded
import com.android.credentialmanager.common.material.ModalBottomSheetValue.Hidden
-import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.launch
import kotlin.math.max
@@ -319,7 +318,7 @@
rememberModalBottomSheetState(Hidden),
sheetShape: Shape = MaterialTheme.shapes.large,
sheetElevation: Dp = ModalBottomSheetDefaults.Elevation,
- sheetBackgroundColor: Color = ModalBottomSheetDefaults.scrimColor,
+ sheetBackgroundColor: Color = MaterialTheme.colorScheme.surface,
sheetContentColor: Color = contentColorFor(sheetBackgroundColor),
scrimColor: Color = ModalBottomSheetDefaults.scrimColor,
content: @Composable () -> Unit
@@ -477,5 +476,5 @@
*/
val scrimColor: Color
@Composable
- get() = LocalAndroidColorScheme.current.colorSurfaceHighlight
+ get() = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.32f)
}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/CancelButton.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/CancelButton.kt
index 177d0e0..80764b5 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/CancelButton.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/CancelButton.kt
@@ -16,13 +16,20 @@
package com.android.credentialmanager.common.ui
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
@Composable
fun CancelButton(text: String, onClick: () -> Unit) {
- TextButton(onClick = onClick) {
+ TextButton(
+ onClick = onClick,
+ colors = ButtonDefaults.textButtonColors(
+ contentColor = MaterialTheme.colorScheme.primary,
+ )
+ ) {
Text(text = text)
}
}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
new file mode 100644
index 0000000..aaabce3
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
@@ -0,0 +1,50 @@
+/*
+ * 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 com.android.credentialmanager.common.ui
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Shape
+
+/**
+ * By default the card is filled with surfaceVariant color. This container card instead fills the
+ * background color with surface corlor.
+ */
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun ContainerCard(
+ modifier: Modifier = Modifier,
+ shape: Shape = CardDefaults.shape,
+ border: BorderStroke? = null,
+ content: @Composable ColumnScope.() -> Unit,
+) {
+ Card(
+ modifier = modifier,
+ shape = shape,
+ border = border,
+ colors = CardDefaults.cardColors(
+ containerColor = MaterialTheme.colorScheme.surface,
+ ),
+ content = content,
+ )
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt
index b2b0bdc..d8ee750 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt
@@ -16,13 +16,21 @@
package com.android.credentialmanager.common.ui
+import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.FilledTonalButton
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@Composable
fun ConfirmButton(text: String, onClick: () -> Unit) {
- FilledTonalButton(onClick = onClick) {
+ FilledTonalButton(
+ onClick = onClick,
+ colors = ButtonDefaults.filledTonalButtonColors(
+ containerColor = MaterialTheme.colorScheme.primaryContainer,
+ contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
+ )
+ ) {
Text(text = text)
}
}
\ 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 51a1cbb..aefd534 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
@@ -18,13 +18,13 @@
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SuggestionChip
import androidx.compose.material3.SuggestionChipDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import com.android.credentialmanager.ui.theme.EntryShape
-import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -42,7 +42,9 @@
icon = icon,
border = null,
colors = SuggestionChipDefaults.suggestionChipColors(
- containerColor = LocalAndroidColorScheme.current.colorSurface,
+ containerColor = MaterialTheme.colorScheme.surfaceVariant,
+ labelColor = MaterialTheme.colorScheme.onSurfaceVariant,
+ iconContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
),
)
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
new file mode 100644
index 0000000..3a66dda
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
@@ -0,0 +1,84 @@
+/*
+ * 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 com.android.credentialmanager.common.ui
+
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.style.TextAlign
+
+@Composable
+fun TextOnSurface(
+ text: String,
+ modifier: Modifier = Modifier,
+ textAlign: TextAlign? = null,
+ style: TextStyle,
+) {
+ TextInternal(
+ text = text,
+ color = MaterialTheme.colorScheme.onSurface,
+ modifier = modifier,
+ textAlign = textAlign,
+ style = style,
+ )
+}
+
+@Composable
+fun TextSecondary(
+ text: String,
+ modifier: Modifier = Modifier,
+ textAlign: TextAlign? = null,
+ style: TextStyle,
+) {
+ TextInternal(
+ text = text,
+ color = MaterialTheme.colorScheme.secondary,
+ modifier = modifier,
+ textAlign = textAlign,
+ style = style,
+ )
+}
+
+@Composable
+fun TextOnSurfaceVariant(
+ text: String,
+ modifier: Modifier = Modifier,
+ textAlign: TextAlign? = null,
+ style: TextStyle,
+) {
+ TextInternal(
+ text = text,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = modifier,
+ textAlign = textAlign,
+ style = style,
+ )
+}
+
+@Composable
+private fun TextInternal(
+ text: String,
+ color: Color,
+ modifier: Modifier,
+ textAlign: TextAlign?,
+ style: TextStyle,
+) {
+ Text(text = text, color = color, modifier = modifier, textAlign = textAlign, style = style)
+}
\ 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 5552d05..d8dd1a7 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -14,7 +14,7 @@
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.material3.Card
+import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
@@ -46,6 +46,10 @@
import com.android.credentialmanager.common.ui.CancelButton
import com.android.credentialmanager.common.ui.ConfirmButton
import com.android.credentialmanager.common.ui.Entry
+import com.android.credentialmanager.common.ui.TextOnSurface
+import com.android.credentialmanager.common.ui.TextSecondary
+import com.android.credentialmanager.common.ui.TextOnSurfaceVariant
+import com.android.credentialmanager.common.ui.ContainerCard
import com.android.credentialmanager.ui.theme.EntryShape
import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
@@ -53,715 +57,767 @@
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CreateCredentialScreen(
- viewModel: CreateCredentialViewModel,
- providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
+ viewModel: CreateCredentialViewModel,
+ providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
) {
- val selectEntryCallback: (EntryInfo) -> Unit = {
- viewModel.onEntrySelected(it, providerActivityLauncher)
- }
- val confirmEntryCallback: () -> Unit = {
- viewModel.onConfirmEntrySelected(providerActivityLauncher)
- }
- val state = rememberModalBottomSheetState(
- initialValue = ModalBottomSheetValue.Expanded,
- skipHalfExpanded = true
- )
- ModalBottomSheetLayout(
- sheetState = state,
- sheetContent = {
- val uiState = viewModel.uiState
- when (uiState.currentScreenState) {
- CreateScreenState.PASSKEY_INTRO -> ConfirmationCard(
- onConfirm = viewModel::onConfirmIntro,
- onCancel = viewModel::onCancel,
- )
- CreateScreenState.PROVIDER_SELECTION -> ProviderSelectionCard(
- requestDisplayInfo = uiState.requestDisplayInfo,
- enabledProviderList = uiState.enabledProviders,
- disabledProviderList = uiState.disabledProviders,
- onCancel = viewModel::onCancel,
- onOptionSelected = viewModel::onEntrySelectedFromFirstUseScreen,
- onDisabledPasswordManagerSelected = viewModel::onDisabledPasswordManagerSelected,
- onRemoteEntrySelected = selectEntryCallback,
- )
- CreateScreenState.CREATION_OPTION_SELECTION -> CreationSelectionCard(
- requestDisplayInfo = uiState.requestDisplayInfo,
- enabledProviderList = uiState.enabledProviders,
- providerInfo = uiState.activeEntry?.activeProvider!!,
- createOptionInfo = uiState.activeEntry.activeEntryInfo as CreateOptionInfo,
- showActiveEntryOnly = uiState.showActiveEntryOnly,
- onOptionSelected = selectEntryCallback,
- onConfirm = confirmEntryCallback,
- onCancel = viewModel::onCancel,
- onMoreOptionsSelected = viewModel::onMoreOptionsSelected,
- )
- CreateScreenState.MORE_OPTIONS_SELECTION -> MoreOptionsSelectionCard(
- requestDisplayInfo = uiState.requestDisplayInfo,
- enabledProviderList = uiState.enabledProviders,
- disabledProviderList = uiState.disabledProviders,
- onBackButtonSelected = viewModel::onBackButtonSelected,
- onOptionSelected = viewModel::onEntrySelectedFromMoreOptionScreen,
- onDisabledPasswordManagerSelected = viewModel::onDisabledPasswordManagerSelected,
- onRemoteEntrySelected = selectEntryCallback,
- )
- CreateScreenState.MORE_OPTIONS_ROW_INTRO -> MoreOptionsRowIntroCard(
- providerInfo = uiState.activeEntry?.activeProvider!!,
- onDefaultOrNotSelected = viewModel::onDefaultOrNotSelected
- )
- CreateScreenState.EXTERNAL_ONLY_SELECTION -> ExternalOnlySelectionCard(
- requestDisplayInfo = uiState.requestDisplayInfo,
- activeRemoteEntry = uiState.activeEntry?.activeEntryInfo!!,
- onOptionSelected = selectEntryCallback,
- onConfirm = confirmEntryCallback,
- onCancel = viewModel::onCancel,
- )
- }
- },
- scrimColor = MaterialTheme.colorScheme.scrim.copy(alpha = 0.8f),
- sheetShape = EntryShape.TopRoundedCorner,
- ) {}
- LaunchedEffect(state.currentValue) {
- if (state.currentValue == ModalBottomSheetValue.Hidden) {
- viewModel.onCancel()
+ val selectEntryCallback: (EntryInfo) -> Unit = {
+ viewModel.onEntrySelected(it, providerActivityLauncher)
}
- }
+ val confirmEntryCallback: () -> Unit = {
+ viewModel.onConfirmEntrySelected(providerActivityLauncher)
+ }
+ val state = rememberModalBottomSheetState(
+ initialValue = ModalBottomSheetValue.Expanded,
+ skipHalfExpanded = true
+ )
+ ModalBottomSheetLayout(
+ sheetBackgroundColor = MaterialTheme.colorScheme.surface,
+ sheetState = state,
+ sheetContent = {
+ val uiState = viewModel.uiState
+ when (uiState.currentScreenState) {
+ CreateScreenState.PASSKEY_INTRO -> ConfirmationCard(
+ onConfirm = viewModel::onConfirmIntro,
+ onCancel = viewModel::onCancel,
+ )
+ CreateScreenState.PROVIDER_SELECTION -> ProviderSelectionCard(
+ requestDisplayInfo = uiState.requestDisplayInfo,
+ enabledProviderList = uiState.enabledProviders,
+ disabledProviderList = uiState.disabledProviders,
+ onCancel = viewModel::onCancel,
+ onOptionSelected = viewModel::onEntrySelectedFromFirstUseScreen,
+ onDisabledPasswordManagerSelected =
+ viewModel::onDisabledPasswordManagerSelected,
+ onRemoteEntrySelected = selectEntryCallback,
+ )
+ CreateScreenState.CREATION_OPTION_SELECTION -> CreationSelectionCard(
+ requestDisplayInfo = uiState.requestDisplayInfo,
+ enabledProviderList = uiState.enabledProviders,
+ providerInfo = uiState.activeEntry?.activeProvider!!,
+ createOptionInfo = uiState.activeEntry.activeEntryInfo as CreateOptionInfo,
+ showActiveEntryOnly = uiState.showActiveEntryOnly,
+ onOptionSelected = selectEntryCallback,
+ onConfirm = confirmEntryCallback,
+ onCancel = viewModel::onCancel,
+ onMoreOptionsSelected = viewModel::onMoreOptionsSelected,
+ )
+ CreateScreenState.MORE_OPTIONS_SELECTION -> MoreOptionsSelectionCard(
+ requestDisplayInfo = uiState.requestDisplayInfo,
+ enabledProviderList = uiState.enabledProviders,
+ disabledProviderList = uiState.disabledProviders,
+ onBackButtonSelected = viewModel::onBackButtonSelected,
+ onOptionSelected = viewModel::onEntrySelectedFromMoreOptionScreen,
+ onDisabledPasswordManagerSelected =
+ viewModel::onDisabledPasswordManagerSelected,
+ onRemoteEntrySelected = selectEntryCallback,
+ )
+ CreateScreenState.MORE_OPTIONS_ROW_INTRO -> MoreOptionsRowIntroCard(
+ providerInfo = uiState.activeEntry?.activeProvider!!,
+ onDefaultOrNotSelected = viewModel::onDefaultOrNotSelected
+ )
+ CreateScreenState.EXTERNAL_ONLY_SELECTION -> ExternalOnlySelectionCard(
+ requestDisplayInfo = uiState.requestDisplayInfo,
+ activeRemoteEntry = uiState.activeEntry?.activeEntryInfo!!,
+ onOptionSelected = selectEntryCallback,
+ onConfirm = confirmEntryCallback,
+ onCancel = viewModel::onCancel,
+ )
+ }
+ },
+ scrimColor = MaterialTheme.colorScheme.scrim.copy(alpha = 0.8f),
+ sheetShape = EntryShape.TopRoundedCorner,
+ ) {}
+ LaunchedEffect(state.currentValue) {
+ if (state.currentValue == ModalBottomSheetValue.Hidden) {
+ viewModel.onCancel()
+ }
+ }
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ConfirmationCard(
- onConfirm: () -> Unit,
- onCancel: () -> Unit,
+ onConfirm: () -> Unit,
+ onCancel: () -> Unit,
) {
- Card() {
- Column() {
- Icon(
- painter = painterResource(R.drawable.ic_passkey),
- contentDescription = null,
- tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
- modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
- .padding(top = 24.dp, bottom = 12.dp)
- )
- Text(
- text = stringResource(R.string.passkey_creation_intro_title),
- style = MaterialTheme.typography.titleMedium,
- modifier = Modifier
- .padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- textAlign = TextAlign.Center
- )
- Divider(
- thickness = 16.dp,
- color = Color.Transparent
- )
- Text(
- text = stringResource(R.string.passkey_creation_intro_body),
- style = MaterialTheme.typography.bodyLarge,
- modifier = Modifier.padding(horizontal = 28.dp)
- )
- Divider(
- thickness = 32.dp,
- color = Color.Transparent
- )
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- CancelButton(
- stringResource(R.string.string_cancel),
- onClick = onCancel
- )
- ConfirmButton(
- stringResource(R.string.string_continue),
- onClick = onConfirm
- )
- }
- Divider(
- thickness = 18.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 18.dp)
- )
+ ContainerCard() {
+ Column() {
+ Icon(
+ painter = painterResource(R.drawable.ic_passkey),
+ contentDescription = null,
+ tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
+ modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
+ .padding(top = 24.dp, bottom = 12.dp)
+ )
+ TextOnSurface(
+ text = stringResource(R.string.passkey_creation_intro_title),
+ style = MaterialTheme.typography.titleMedium,
+ modifier = Modifier
+ .padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ textAlign = TextAlign.Center,
+ )
+ Divider(
+ thickness = 16.dp,
+ color = Color.Transparent
+ )
+ TextSecondary(
+ text = stringResource(R.string.passkey_creation_intro_body),
+ style = MaterialTheme.typography.bodyLarge,
+ modifier = Modifier.padding(horizontal = 28.dp),
+ )
+ Divider(
+ thickness = 32.dp,
+ color = Color.Transparent
+ )
+ Row(
+ horizontalArrangement = Arrangement.SpaceBetween,
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
+ ) {
+ CancelButton(
+ stringResource(R.string.string_cancel),
+ onClick = onCancel
+ )
+ ConfirmButton(
+ stringResource(R.string.string_continue),
+ onClick = onConfirm
+ )
+ }
+ Divider(
+ thickness = 18.dp,
+ color = Color.Transparent,
+ modifier = Modifier.padding(bottom = 18.dp)
+ )
+ }
}
- }
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ProviderSelectionCard(
- requestDisplayInfo: RequestDisplayInfo,
- enabledProviderList: List<EnabledProviderInfo>,
- disabledProviderList: List<DisabledProviderInfo>?,
- onOptionSelected: (ActiveEntry) -> Unit,
- onDisabledPasswordManagerSelected: () -> Unit,
- onCancel: () -> Unit,
- onRemoteEntrySelected: (EntryInfo) -> Unit,
+ requestDisplayInfo: RequestDisplayInfo,
+ enabledProviderList: List<EnabledProviderInfo>,
+ disabledProviderList: List<DisabledProviderInfo>?,
+ onOptionSelected: (ActiveEntry) -> Unit,
+ onDisabledPasswordManagerSelected: () -> Unit,
+ onCancel: () -> Unit,
+ onRemoteEntrySelected: (EntryInfo) -> Unit,
) {
- Card() {
- Column() {
- Icon(
- bitmap = requestDisplayInfo.typeIcon.toBitmap().asImageBitmap(),
- contentDescription = null,
- tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
- modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
- .padding(top = 24.dp, bottom = 16.dp).size(32.dp)
- )
- Text(
- text = stringResource(
- R.string.choose_provider_title,
- when (requestDisplayInfo.type) {
- TYPE_PUBLIC_KEY_CREDENTIAL -> stringResource(R.string.create_your_passkeys)
- TYPE_PASSWORD_CREDENTIAL -> stringResource(R.string.save_your_password)
- else -> stringResource(R.string.save_your_sign_in_info)
- },
- ),
- style = MaterialTheme.typography.titleMedium,
- modifier = Modifier.padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- textAlign = TextAlign.Center
- )
- Divider(
- thickness = 16.dp,
- color = Color.Transparent
- )
- Text(
- text = stringResource(R.string.choose_provider_body),
- style = MaterialTheme.typography.bodyLarge,
- modifier = Modifier.padding(horizontal = 28.dp)
- )
- Divider(
- thickness = 18.dp,
- color = Color.Transparent
- )
- Card(
- shape = MaterialTheme.shapes.medium,
- modifier = Modifier
- .padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- ) {
- LazyColumn(
- verticalArrangement = Arrangement.spacedBy(2.dp)
- ) {
- enabledProviderList.forEach { enabledProviderInfo ->
- enabledProviderInfo.createOptions.forEach { createOptionInfo ->
- item {
- MoreOptionsInfoRow(
- providerInfo = enabledProviderInfo,
- createOptionInfo = createOptionInfo,
- onOptionSelected = {
- onOptionSelected(ActiveEntry(enabledProviderInfo, createOptionInfo))
- })
- }
- }
- }
- if (disabledProviderList != null) {
- item {
- MoreOptionsDisabledProvidersRow(
- disabledProviders = disabledProviderList,
- onDisabledPasswordManagerSelected = onDisabledPasswordManagerSelected,
- )
- }
- }
- }
- }
- // TODO: handle the error situation that if multiple remoteInfos exists
- enabledProviderList.forEach { enabledProvider ->
- if (enabledProvider.remoteEntry != null) {
- TextButton(
- onClick = {
- onRemoteEntrySelected(enabledProvider.remoteEntry!!) },
- modifier = Modifier
- .padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally)
- ) {
- Text(
- text = stringResource(R.string.string_save_to_another_device),
- textAlign = TextAlign.Center,
+ ContainerCard() {
+ Column() {
+ Icon(
+ bitmap = requestDisplayInfo.typeIcon.toBitmap().asImageBitmap(),
+ contentDescription = null,
+ tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
+ modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
+ .padding(top = 24.dp, bottom = 16.dp).size(32.dp)
)
- }
+ TextOnSurface(
+ text = stringResource(
+ R.string.choose_provider_title,
+ when (requestDisplayInfo.type) {
+ TYPE_PUBLIC_KEY_CREDENTIAL -> stringResource(R.string.create_your_passkeys)
+ TYPE_PASSWORD_CREDENTIAL -> stringResource(R.string.save_your_password)
+ else -> stringResource(R.string.save_your_sign_in_info)
+ },
+ ),
+ style = MaterialTheme.typography.titleMedium,
+ modifier = Modifier.padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ textAlign = TextAlign.Center,
+ )
+ Divider(
+ thickness = 16.dp,
+ color = Color.Transparent
+ )
+ TextSecondary(
+ text = stringResource(R.string.choose_provider_body),
+ style = MaterialTheme.typography.bodyLarge,
+ modifier = Modifier.padding(horizontal = 28.dp),
+ )
+ Divider(
+ thickness = 18.dp,
+ color = Color.Transparent
+ )
+ ContainerCard(
+ shape = MaterialTheme.shapes.medium,
+ modifier = Modifier
+ .padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ ) {
+ LazyColumn(
+ verticalArrangement = Arrangement.spacedBy(2.dp)
+ ) {
+ enabledProviderList.forEach { enabledProviderInfo ->
+ enabledProviderInfo.createOptions.forEach { createOptionInfo ->
+ item {
+ MoreOptionsInfoRow(
+ providerInfo = enabledProviderInfo,
+ createOptionInfo = createOptionInfo,
+ onOptionSelected = {
+ onOptionSelected(
+ ActiveEntry(
+ enabledProviderInfo,
+ createOptionInfo
+ )
+ )
+ })
+ }
+ }
+ }
+ if (disabledProviderList != null) {
+ item {
+ MoreOptionsDisabledProvidersRow(
+ disabledProviders = disabledProviderList,
+ onDisabledPasswordManagerSelected =
+ onDisabledPasswordManagerSelected,
+ )
+ }
+ }
+ }
+ }
+ // TODO: handle the error situation that if multiple remoteInfos exists
+ enabledProviderList.forEach { enabledProvider ->
+ if (enabledProvider.remoteEntry != null) {
+ TextButton(
+ onClick = {
+ onRemoteEntrySelected(enabledProvider.remoteEntry!!)
+ },
+ modifier = Modifier
+ .padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ colors = ButtonDefaults.textButtonColors(
+ contentColor = MaterialTheme.colorScheme.primary,
+ )
+ ) {
+ Text(
+ text = stringResource(R.string.string_save_to_another_device),
+ textAlign = TextAlign.Center,
+ )
+ }
+ }
+ }
+ Divider(
+ thickness = 24.dp,
+ color = Color.Transparent
+ )
+ Row(
+ horizontalArrangement = Arrangement.Start,
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
+ ) {
+ CancelButton(stringResource(R.string.string_cancel), onCancel)
+ }
+ Divider(
+ thickness = 18.dp,
+ color = Color.Transparent,
+ modifier = Modifier.padding(bottom = 16.dp)
+ )
}
- }
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
- )
- Row(
- horizontalArrangement = Arrangement.Start,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- CancelButton(stringResource(R.string.string_cancel), onCancel)
- }
- Divider(
- thickness = 18.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 16.dp)
- )
}
- }
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MoreOptionsSelectionCard(
- requestDisplayInfo: RequestDisplayInfo,
- enabledProviderList: List<EnabledProviderInfo>,
- disabledProviderList: List<DisabledProviderInfo>?,
- onBackButtonSelected: () -> Unit,
- onOptionSelected: (ActiveEntry) -> Unit,
- onDisabledPasswordManagerSelected: () -> Unit,
- onRemoteEntrySelected: (EntryInfo) -> Unit,
+ requestDisplayInfo: RequestDisplayInfo,
+ enabledProviderList: List<EnabledProviderInfo>,
+ disabledProviderList: List<DisabledProviderInfo>?,
+ onBackButtonSelected: () -> Unit,
+ onOptionSelected: (ActiveEntry) -> Unit,
+ onDisabledPasswordManagerSelected: () -> Unit,
+ onRemoteEntrySelected: (EntryInfo) -> Unit,
) {
- Card() {
- Column() {
- TopAppBar(
- title = {
- Text(
- text = when (requestDisplayInfo.type) {
- TYPE_PUBLIC_KEY_CREDENTIAL -> stringResource(R.string.create_passkey_in_title)
- TYPE_PASSWORD_CREDENTIAL -> stringResource(R.string.save_password_to_title)
- else -> stringResource(R.string.save_sign_in_to_title)
- },
- style = MaterialTheme.typography.titleMedium
- )
- },
- navigationIcon = {
- IconButton(onClick = onBackButtonSelected) {
- Icon(
- Icons.Filled.ArrowBack,
- stringResource(R.string.accessibility_back_arrow_button))
- }
- },
- colors = TopAppBarDefaults.smallTopAppBarColors
- (containerColor = Color.Transparent),
- )
- Divider(
- thickness = 8.dp,
- color = Color.Transparent
- )
- Card(
- shape = MaterialTheme.shapes.medium,
- modifier = Modifier
- .padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally)
- ) {
- LazyColumn(
- verticalArrangement = Arrangement.spacedBy(2.dp)
- ) {
- enabledProviderList.forEach { enabledProviderInfo ->
- enabledProviderInfo.createOptions.forEach { createOptionInfo ->
- item {
- MoreOptionsInfoRow(
- providerInfo = enabledProviderInfo,
- createOptionInfo = createOptionInfo,
- onOptionSelected = {
- onOptionSelected(ActiveEntry(enabledProviderInfo, createOptionInfo))
- })
- }
+ ContainerCard() {
+ Column() {
+ TopAppBar(
+ title = {
+ TextOnSurface(
+ text = when (requestDisplayInfo.type) {
+ TYPE_PUBLIC_KEY_CREDENTIAL ->
+ stringResource(R.string.create_passkey_in_title)
+ TYPE_PASSWORD_CREDENTIAL ->
+ stringResource(R.string.save_password_to_title)
+ else -> stringResource(R.string.save_sign_in_to_title)
+ },
+ style = MaterialTheme.typography.titleMedium,
+ )
+ },
+ navigationIcon = {
+ IconButton(onClick = onBackButtonSelected) {
+ Icon(
+ Icons.Filled.ArrowBack,
+ stringResource(R.string.accessibility_back_arrow_button)
+ )
+ }
+ },
+ colors = TopAppBarDefaults.smallTopAppBarColors
+ (containerColor = Color.Transparent),
+ )
+ Divider(
+ thickness = 8.dp,
+ color = Color.Transparent
+ )
+ ContainerCard(
+ shape = MaterialTheme.shapes.medium,
+ modifier = Modifier
+ .padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally)
+ ) {
+ LazyColumn(
+ verticalArrangement = Arrangement.spacedBy(2.dp)
+ ) {
+ enabledProviderList.forEach { enabledProviderInfo ->
+ enabledProviderInfo.createOptions.forEach { createOptionInfo ->
+ item {
+ MoreOptionsInfoRow(
+ providerInfo = enabledProviderInfo,
+ createOptionInfo = createOptionInfo,
+ onOptionSelected = {
+ onOptionSelected(
+ ActiveEntry(
+ enabledProviderInfo,
+ createOptionInfo
+ )
+ )
+ })
+ }
+ }
+ }
+ if (disabledProviderList != null) {
+ item {
+ MoreOptionsDisabledProvidersRow(
+ disabledProviders = disabledProviderList,
+ onDisabledPasswordManagerSelected =
+ onDisabledPasswordManagerSelected,
+ )
+ }
+ }
+ // TODO: handle the error situation that if multiple remoteInfos exists
+ enabledProviderList.forEach {
+ if (it.remoteEntry != null) {
+ item {
+ RemoteEntryRow(
+ remoteInfo = it.remoteEntry!!,
+ onRemoteEntrySelected = onRemoteEntrySelected,
+ )
+ }
+ }
+ }
+ }
}
- }
- if (disabledProviderList != null) {
- item {
- MoreOptionsDisabledProvidersRow(
- disabledProviders = disabledProviderList,
- onDisabledPasswordManagerSelected = onDisabledPasswordManagerSelected,
- )
- }
- }
- // TODO: handle the error situation that if multiple remoteInfos exists
- enabledProviderList.forEach {
- if (it.remoteEntry != null) {
- item {
- RemoteEntryRow(
- remoteInfo = it.remoteEntry!!,
- onRemoteEntrySelected = onRemoteEntrySelected,
- )
- }
- }
- }
+ Divider(
+ thickness = 18.dp,
+ color = Color.Transparent,
+ modifier = Modifier.padding(bottom = 40.dp)
+ )
}
- }
- Divider(
- thickness = 18.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 40.dp)
- )
}
- }
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MoreOptionsRowIntroCard(
- providerInfo: EnabledProviderInfo,
- onDefaultOrNotSelected: () -> Unit,
+ providerInfo: EnabledProviderInfo,
+ onDefaultOrNotSelected: () -> Unit,
) {
- Card() {
- Column() {
- Icon(
- Icons.Outlined.NewReleases,
- contentDescription = null,
- modifier = Modifier.align(alignment = Alignment.CenterHorizontally).padding(all = 24.dp)
- )
- Text(
- text = stringResource(R.string.use_provider_for_all_title, providerInfo.displayName),
- style = MaterialTheme.typography.titleMedium,
- modifier = Modifier.padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- textAlign = TextAlign.Center,
- )
- Text(
- text = stringResource(R.string.use_provider_for_all_description),
- style = MaterialTheme.typography.bodyLarge,
- modifier = Modifier.padding(all = 24.dp).align(alignment = Alignment.CenterHorizontally)
- )
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- CancelButton(
- stringResource(R.string.use_once),
- onClick = onDefaultOrNotSelected
- )
- ConfirmButton(
- stringResource(R.string.set_as_default),
- onClick = onDefaultOrNotSelected
- )
- }
- Divider(
- thickness = 18.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 40.dp)
- )
+ ContainerCard() {
+ Column() {
+ Icon(
+ Icons.Outlined.NewReleases,
+ contentDescription = null,
+ modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
+ .padding(all = 24.dp)
+ )
+ TextOnSurface(
+ text = stringResource(
+ R.string.use_provider_for_all_title,
+ providerInfo.displayName
+ ),
+ style = MaterialTheme.typography.titleMedium,
+ modifier = Modifier.padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ textAlign = TextAlign.Center,
+ )
+ TextSecondary(
+ text = stringResource(R.string.use_provider_for_all_description),
+ style = MaterialTheme.typography.bodyLarge,
+ modifier = Modifier.padding(all = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ )
+ Row(
+ horizontalArrangement = Arrangement.SpaceBetween,
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
+ ) {
+ CancelButton(
+ stringResource(R.string.use_once),
+ onClick = onDefaultOrNotSelected
+ )
+ ConfirmButton(
+ stringResource(R.string.set_as_default),
+ onClick = onDefaultOrNotSelected
+ )
+ }
+ Divider(
+ thickness = 18.dp,
+ color = Color.Transparent,
+ modifier = Modifier.padding(bottom = 40.dp)
+ )
+ }
}
- }
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CreationSelectionCard(
- requestDisplayInfo: RequestDisplayInfo,
- enabledProviderList: List<EnabledProviderInfo>,
- providerInfo: EnabledProviderInfo,
- createOptionInfo: CreateOptionInfo,
- showActiveEntryOnly: Boolean,
- onOptionSelected: (EntryInfo) -> Unit,
- onConfirm: () -> Unit,
- onCancel: () -> Unit,
- onMoreOptionsSelected: () -> Unit,
+ requestDisplayInfo: RequestDisplayInfo,
+ enabledProviderList: List<EnabledProviderInfo>,
+ providerInfo: EnabledProviderInfo,
+ createOptionInfo: CreateOptionInfo,
+ showActiveEntryOnly: Boolean,
+ onOptionSelected: (EntryInfo) -> Unit,
+ onConfirm: () -> Unit,
+ onCancel: () -> Unit,
+ onMoreOptionsSelected: () -> Unit,
) {
- Card() {
- Column() {
- Icon(
- bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
- contentDescription = null,
- tint = Color.Unspecified,
- modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
- .padding(all = 24.dp).size(32.dp)
- )
- Text(
- text = when (requestDisplayInfo.type) {
- TYPE_PUBLIC_KEY_CREDENTIAL -> stringResource(R.string.choose_create_option_passkey_title,
- providerInfo.displayName)
- TYPE_PASSWORD_CREDENTIAL -> stringResource(R.string.choose_create_option_password_title,
- providerInfo.displayName)
- else -> stringResource(R.string.choose_create_option_sign_in_title,
- providerInfo.displayName)
- },
- style = MaterialTheme.typography.titleMedium,
- modifier = Modifier.padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- textAlign = TextAlign.Center,
- )
- if (createOptionInfo.userProviderDisplayName != null) {
- Text(
- text = stringResource(
- R.string.choose_create_option_description,
- requestDisplayInfo.appDomainName,
- when (requestDisplayInfo.type) {
- TYPE_PUBLIC_KEY_CREDENTIAL -> stringResource(R.string.passkey)
- TYPE_PASSWORD_CREDENTIAL -> stringResource(R.string.password)
- else -> stringResource(R.string.sign_ins)
- },
- providerInfo.displayName,
- createOptionInfo.userProviderDisplayName
- ),
- style = MaterialTheme.typography.bodyLarge,
- modifier = Modifier.padding(all = 24.dp).align(alignment = Alignment.CenterHorizontally)
- )
- }
- Card(
- shape = MaterialTheme.shapes.medium,
- modifier = Modifier
- .padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- ) {
- PrimaryCreateOptionRow(
- requestDisplayInfo = requestDisplayInfo,
- entryInfo = createOptionInfo,
- onOptionSelected = onOptionSelected
- )
- }
- if (!showActiveEntryOnly) {
- var createOptionsSize = 0
- enabledProviderList.forEach{
- enabledProvider -> createOptionsSize += enabledProvider.createOptions.size}
- if (createOptionsSize > 1) {
- TextButton(
- onClick = onMoreOptionsSelected,
- modifier = Modifier
- .padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally)){
- Text(
- text =
- when (requestDisplayInfo.type) {
- TYPE_PUBLIC_KEY_CREDENTIAL ->
- stringResource(R.string.string_create_in_another_place)
- else -> stringResource(R.string.string_save_to_another_place)},
- textAlign = TextAlign.Center,
+ ContainerCard() {
+ Column() {
+ Icon(
+ bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
+ contentDescription = null,
+ tint = Color.Unspecified,
+ modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
+ .padding(all = 24.dp).size(32.dp)
)
- }
- } else if (
- requestDisplayInfo.type == TYPE_PUBLIC_KEY_CREDENTIAL
- ) {
- // TODO: handle the error situation that if multiple remoteInfos exists
- enabledProviderList.forEach { enabledProvider ->
- if (enabledProvider.remoteEntry != null) {
- TextButton(
- onClick = {
- onOptionSelected(enabledProvider.remoteEntry!!) },
- modifier = Modifier
- .padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally)
- ) {
- Text(
- text = stringResource(R.string.string_use_another_device),
- textAlign = TextAlign.Center,
+ TextOnSurface(
+ text = when (requestDisplayInfo.type) {
+ TYPE_PUBLIC_KEY_CREDENTIAL -> stringResource(
+ R.string.choose_create_option_passkey_title,
+ providerInfo.displayName
+ )
+ TYPE_PASSWORD_CREDENTIAL -> stringResource(
+ R.string.choose_create_option_password_title,
+ providerInfo.displayName
+ )
+ else -> stringResource(
+ R.string.choose_create_option_sign_in_title,
+ providerInfo.displayName
+ )
+ },
+ style = MaterialTheme.typography.titleMedium,
+ modifier = Modifier.padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ textAlign = TextAlign.Center,
+ )
+ if (createOptionInfo.userProviderDisplayName != null) {
+ TextSecondary(
+ text = stringResource(
+ R.string.choose_create_option_description,
+ requestDisplayInfo.appDomainName,
+ when (requestDisplayInfo.type) {
+ TYPE_PUBLIC_KEY_CREDENTIAL -> stringResource(R.string.passkey)
+ TYPE_PASSWORD_CREDENTIAL -> stringResource(R.string.password)
+ else -> stringResource(R.string.sign_ins)
+ },
+ providerInfo.displayName,
+ createOptionInfo.userProviderDisplayName
+ ),
+ style = MaterialTheme.typography.bodyLarge,
+ modifier = Modifier.padding(all = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
)
- }
}
- }
+ ContainerCard(
+ shape = MaterialTheme.shapes.medium,
+ modifier = Modifier
+ .padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ ) {
+ PrimaryCreateOptionRow(
+ requestDisplayInfo = requestDisplayInfo,
+ entryInfo = createOptionInfo,
+ onOptionSelected = onOptionSelected
+ )
+ }
+ if (!showActiveEntryOnly) {
+ var createOptionsSize = 0
+ enabledProviderList.forEach { enabledProvider ->
+ createOptionsSize += enabledProvider.createOptions.size
+ }
+ if (createOptionsSize > 1) {
+ TextButton(
+ onClick = onMoreOptionsSelected,
+ modifier = Modifier
+ .padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ colors = ButtonDefaults.textButtonColors(
+ contentColor = MaterialTheme.colorScheme.primary,
+ ),
+ ) {
+ Text(
+ text =
+ when (requestDisplayInfo.type) {
+ TYPE_PUBLIC_KEY_CREDENTIAL ->
+ stringResource(R.string.string_create_in_another_place)
+ else -> stringResource(R.string.string_save_to_another_place)
+ },
+ textAlign = TextAlign.Center,
+ )
+ }
+ } else if (
+ requestDisplayInfo.type == TYPE_PUBLIC_KEY_CREDENTIAL
+ ) {
+ // TODO: handle the error situation that if multiple remoteInfos exists
+ enabledProviderList.forEach { enabledProvider ->
+ if (enabledProvider.remoteEntry != null) {
+ TextButton(
+ onClick = {
+ onOptionSelected(enabledProvider.remoteEntry!!)
+ },
+ modifier = Modifier
+ .padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ colors = ButtonDefaults.textButtonColors(
+ contentColor = MaterialTheme.colorScheme.primary,
+ ),
+ ) {
+ Text(
+ text = stringResource(R.string.string_use_another_device),
+ textAlign = TextAlign.Center,
+ )
+ }
+ }
+ }
+ }
+ }
+ Divider(
+ thickness = 24.dp,
+ color = Color.Transparent
+ )
+ Row(
+ horizontalArrangement = Arrangement.SpaceBetween,
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
+ ) {
+ CancelButton(
+ stringResource(R.string.string_cancel),
+ onClick = onCancel
+ )
+ ConfirmButton(
+ stringResource(R.string.string_continue),
+ onClick = onConfirm
+ )
+ }
+ Divider(
+ thickness = 18.dp,
+ color = Color.Transparent,
+ modifier = Modifier.padding(bottom = 16.dp)
+ )
}
- }
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
- )
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- CancelButton(
- stringResource(R.string.string_cancel),
- onClick = onCancel
- )
- ConfirmButton(
- stringResource(R.string.string_continue),
- onClick = onConfirm
- )
- }
- Divider(
- thickness = 18.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 16.dp)
- )
}
- }
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ExternalOnlySelectionCard(
- requestDisplayInfo: RequestDisplayInfo,
- activeRemoteEntry: EntryInfo,
- onOptionSelected: (EntryInfo) -> Unit,
- onConfirm: () -> Unit,
- onCancel: () -> Unit,
+ requestDisplayInfo: RequestDisplayInfo,
+ activeRemoteEntry: EntryInfo,
+ onOptionSelected: (EntryInfo) -> Unit,
+ onConfirm: () -> Unit,
+ onCancel: () -> Unit,
) {
- Card() {
- Column() {
- Icon(
- painter = painterResource(R.drawable.ic_other_devices),
- contentDescription = null,
- tint = Color.Unspecified,
- modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
- .padding(all = 24.dp).size(32.dp)
- )
- Text(
- text = stringResource(R.string.create_passkey_in_other_device_title),
- style = MaterialTheme.typography.titleMedium,
- modifier = Modifier.padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- textAlign = TextAlign.Center,
- )
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
- )
- Card(
- shape = MaterialTheme.shapes.medium,
- modifier = Modifier
- .padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally),
- ) {
- PrimaryCreateOptionRow(
- requestDisplayInfo = requestDisplayInfo,
- entryInfo = activeRemoteEntry,
- onOptionSelected = onOptionSelected
- )
- }
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
- )
- Row(
- horizontalArrangement = Arrangement.SpaceBetween,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- CancelButton(
- stringResource(R.string.string_cancel),
- onClick = onCancel
- )
- ConfirmButton(
- stringResource(R.string.string_continue),
- onClick = onConfirm
- )
- }
- Divider(
- thickness = 18.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 16.dp)
- )
+ ContainerCard() {
+ Column() {
+ Icon(
+ painter = painterResource(R.drawable.ic_other_devices),
+ contentDescription = null,
+ tint = Color.Unspecified,
+ modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
+ .padding(all = 24.dp).size(32.dp)
+ )
+ TextOnSurface(
+ text = stringResource(R.string.create_passkey_in_other_device_title),
+ style = MaterialTheme.typography.titleMedium,
+ modifier = Modifier.padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ textAlign = TextAlign.Center,
+ )
+ Divider(
+ thickness = 24.dp,
+ color = Color.Transparent
+ )
+ ContainerCard(
+ shape = MaterialTheme.shapes.medium,
+ modifier = Modifier
+ .padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ ) {
+ PrimaryCreateOptionRow(
+ requestDisplayInfo = requestDisplayInfo,
+ entryInfo = activeRemoteEntry,
+ onOptionSelected = onOptionSelected
+ )
+ }
+ Divider(
+ thickness = 24.dp,
+ color = Color.Transparent
+ )
+ Row(
+ horizontalArrangement = Arrangement.SpaceBetween,
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
+ ) {
+ CancelButton(
+ stringResource(R.string.string_cancel),
+ onClick = onCancel
+ )
+ ConfirmButton(
+ stringResource(R.string.string_continue),
+ onClick = onConfirm
+ )
+ }
+ Divider(
+ thickness = 18.dp,
+ color = Color.Transparent,
+ modifier = Modifier.padding(bottom = 16.dp)
+ )
+ }
}
- }
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PrimaryCreateOptionRow(
- requestDisplayInfo: RequestDisplayInfo,
- entryInfo: EntryInfo,
- onOptionSelected: (EntryInfo) -> Unit
+ requestDisplayInfo: RequestDisplayInfo,
+ entryInfo: EntryInfo,
+ onOptionSelected: (EntryInfo) -> Unit
) {
- Entry(
- onClick = {onOptionSelected(entryInfo)},
- icon = {
- Icon(
- bitmap = if (entryInfo is CreateOptionInfo) {
- entryInfo.profileIcon.toBitmap().asImageBitmap()
- } else {requestDisplayInfo.typeIcon.toBitmap().asImageBitmap()},
- contentDescription = null,
- tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
- modifier = Modifier.padding(start = 18.dp).size(32.dp)
- )
- },
- label = {
- Column() {
- // TODO: Add the function to hide/view password when the type is create password
- when (requestDisplayInfo.type) {
- TYPE_PUBLIC_KEY_CREDENTIAL -> {
- Text(
- text = requestDisplayInfo.title,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp)
- )
- Text(
- text = if (requestDisplayInfo.subtitle != null) {
- stringResource(
- R.string.passkey_before_subtitle) + " - " + requestDisplayInfo.subtitle
- } else {stringResource(R.string.passkey_before_subtitle)},
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp)
- )
- }
- TYPE_PASSWORD_CREDENTIAL -> {
- Text(
- text = requestDisplayInfo.title,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp)
- )
- Text(
- // This subtitle would never be null for create password
- text = requestDisplayInfo.subtitle ?: "",
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp)
- )
- }
- else -> {
- Text(
- text = requestDisplayInfo.title,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp, bottom = 16.dp)
- )
+ Entry(
+ onClick = { onOptionSelected(entryInfo) },
+ icon = {
+ Icon(
+ bitmap = if (entryInfo is CreateOptionInfo) {
+ entryInfo.profileIcon.toBitmap().asImageBitmap()
+ } else {
+ requestDisplayInfo.typeIcon.toBitmap().asImageBitmap()
+ },
+ contentDescription = null,
+ tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
+ modifier = Modifier.padding(start = 18.dp).size(32.dp)
+ )
+ },
+ label = {
+ Column() {
+ // TODO: Add the function to hide/view password when the type is create password
+ when (requestDisplayInfo.type) {
+ TYPE_PUBLIC_KEY_CREDENTIAL -> {
+ TextOnSurfaceVariant(
+ text = requestDisplayInfo.title,
+ style = MaterialTheme.typography.titleLarge,
+ modifier = Modifier.padding(top = 16.dp),
+ )
+ TextSecondary(
+ text = if (requestDisplayInfo.subtitle != null) {
+ stringResource(
+ R.string.passkey_before_subtitle
+ ) + " - " + requestDisplayInfo.subtitle
+ } else {
+ stringResource(R.string.passkey_before_subtitle)
+ },
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.padding(bottom = 16.dp),
+ )
+ }
+ TYPE_PASSWORD_CREDENTIAL -> {
+ TextOnSurfaceVariant(
+ text = requestDisplayInfo.title,
+ style = MaterialTheme.typography.titleLarge,
+ modifier = Modifier.padding(top = 16.dp),
+ )
+ TextSecondary(
+ // This subtitle would never be null for create password
+ text = requestDisplayInfo.subtitle ?: "",
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.padding(bottom = 16.dp),
+ )
+ }
+ else -> {
+ TextOnSurfaceVariant(
+ text = requestDisplayInfo.title,
+ style = MaterialTheme.typography.titleLarge,
+ modifier = Modifier.padding(top = 16.dp, bottom = 16.dp),
+ )
+ }
+ }
}
}
- }
- }
- )
+ )
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MoreOptionsInfoRow(
- providerInfo: EnabledProviderInfo,
- createOptionInfo: CreateOptionInfo,
- onOptionSelected: () -> Unit
+ providerInfo: EnabledProviderInfo,
+ createOptionInfo: CreateOptionInfo,
+ onOptionSelected: () -> Unit
) {
- Entry(
+ Entry(
onClick = onOptionSelected,
icon = {
- Image(modifier = Modifier.size(32.dp).padding(start = 16.dp),
+ Image(
+ modifier = Modifier.size(32.dp).padding(start = 16.dp),
bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
- contentDescription = null)
+ contentDescription = null
+ )
},
label = {
- Column() {
- Text(
- text = providerInfo.displayName,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp, start = 16.dp)
- )
- if (createOptionInfo.userProviderDisplayName != null) {
- Text(
- text = createOptionInfo.userProviderDisplayName,
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(start = 16.dp)
- )
+ Column() {
+ TextOnSurfaceVariant(
+ text = providerInfo.displayName,
+ style = MaterialTheme.typography.titleLarge,
+ modifier = Modifier.padding(top = 16.dp, start = 16.dp),
+ )
+ if (createOptionInfo.userProviderDisplayName != null) {
+ TextSecondary(
+ text = createOptionInfo.userProviderDisplayName,
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.padding(start = 16.dp),
+ )
+ }
+ if (createOptionInfo.passwordCount != null &&
+ createOptionInfo.passkeyCount != null) {
+ TextSecondary(
+ text =
+ stringResource(
+ R.string.more_options_usage_passwords_passkeys,
+ createOptionInfo.passwordCount,
+ createOptionInfo.passkeyCount
+ ),
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.padding(bottom = 16.dp, start = 16.dp),
+ )
+ } else if (createOptionInfo.passwordCount != null) {
+ TextSecondary(
+ text =
+ stringResource(
+ R.string.more_options_usage_passwords,
+ createOptionInfo.passwordCount
+ ),
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.padding(bottom = 16.dp, start = 16.dp),
+ )
+ } else if (createOptionInfo.passkeyCount != null) {
+ TextSecondary(
+ text =
+ stringResource(
+ R.string.more_options_usage_passkeys,
+ createOptionInfo.passkeyCount
+ ),
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.padding(bottom = 16.dp, start = 16.dp),
+ )
+ } else if (createOptionInfo.totalCredentialCount != null) {
+ // TODO: Handle the case when there is total count
+ // but no passwords and passkeys after design is set
+ }
}
- if (createOptionInfo.passwordCount != null && createOptionInfo.passkeyCount != null) {
- Text(
- text =
- stringResource(
- R.string.more_options_usage_passwords_passkeys,
- createOptionInfo.passwordCount,
- createOptionInfo.passkeyCount
- ),
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp, start = 16.dp)
- )
- } else if (createOptionInfo.passwordCount != null) {
- Text(
- text =
- stringResource(
- R.string.more_options_usage_passwords,
- createOptionInfo.passwordCount
- ),
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp, start = 16.dp)
- )
- } else if (createOptionInfo.passkeyCount != null) {
- Text(
- text =
- stringResource(
- R.string.more_options_usage_passkeys,
- createOptionInfo.passkeyCount
- ),
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp, start = 16.dp)
- )
- } else if (createOptionInfo.totalCredentialCount != null) {
- // TODO: Handle the case when there is total count
- // but no passwords and passkeys after design is set
- }
- }
}
)
}
@@ -769,61 +825,61 @@
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MoreOptionsDisabledProvidersRow(
- disabledProviders: List<ProviderInfo>,
- onDisabledPasswordManagerSelected: () -> Unit,
+ disabledProviders: List<ProviderInfo>,
+ onDisabledPasswordManagerSelected: () -> Unit,
) {
- Entry(
- onClick = onDisabledPasswordManagerSelected,
- icon = {
- Icon(
- Icons.Filled.Add,
- contentDescription = null,
- modifier = Modifier.padding(start = 16.dp)
- )
- },
- label = {
- Column() {
- Text(
- text = stringResource(R.string.other_password_manager),
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp, start = 16.dp)
- )
- // TODO: Update the subtitle once design is confirmed
- Text(
- text = disabledProviders.joinToString(separator = ", "){ it.displayName },
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp, start = 16.dp)
- )
- }
- }
- )
+ Entry(
+ onClick = onDisabledPasswordManagerSelected,
+ icon = {
+ Icon(
+ Icons.Filled.Add,
+ contentDescription = null,
+ modifier = Modifier.padding(start = 16.dp)
+ )
+ },
+ label = {
+ Column() {
+ TextOnSurfaceVariant(
+ text = stringResource(R.string.other_password_manager),
+ style = MaterialTheme.typography.titleLarge,
+ modifier = Modifier.padding(top = 16.dp, start = 16.dp),
+ )
+ // TODO: Update the subtitle once design is confirmed
+ TextSecondary(
+ text = disabledProviders.joinToString(separator = ", ") { it.displayName },
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.padding(bottom = 16.dp, start = 16.dp),
+ )
+ }
+ }
+ )
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RemoteEntryRow(
- remoteInfo: RemoteInfo,
- onRemoteEntrySelected: (RemoteInfo) -> Unit,
+ remoteInfo: RemoteInfo,
+ onRemoteEntrySelected: (RemoteInfo) -> Unit,
) {
- Entry(
- onClick = {onRemoteEntrySelected(remoteInfo)},
- icon = {
- Icon(
- painter = painterResource(R.drawable.ic_other_devices),
- contentDescription = null,
- tint = Color.Unspecified,
- modifier = Modifier.padding(start = 18.dp)
- )
- },
- label = {
- Column() {
- Text(
- text = stringResource(R.string.another_device),
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(start = 16.dp, top = 18.dp, bottom = 18.dp)
- .align(alignment = Alignment.CenterHorizontally)
- )
- }
- }
- )
+ Entry(
+ onClick = { onRemoteEntrySelected(remoteInfo) },
+ icon = {
+ Icon(
+ painter = painterResource(R.drawable.ic_other_devices),
+ contentDescription = null,
+ tint = Color.Unspecified,
+ modifier = Modifier.padding(start = 18.dp)
+ )
+ },
+ label = {
+ Column() {
+ TextOnSurfaceVariant(
+ text = stringResource(R.string.another_device),
+ style = MaterialTheme.typography.titleLarge,
+ modifier = Modifier.padding(start = 16.dp, top = 18.dp, bottom = 18.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ )
+ }
+ }
+ )
}
\ 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 720f231..31dc069 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -22,6 +22,7 @@
import androidx.activity.result.IntentSenderRequest
import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -31,13 +32,11 @@
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
-import androidx.compose.material3.Card
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material.icons.Icons
@@ -59,202 +58,216 @@
import com.android.credentialmanager.common.material.rememberModalBottomSheetState
import com.android.credentialmanager.common.ui.CancelButton
import com.android.credentialmanager.common.ui.Entry
+import com.android.credentialmanager.common.ui.TextOnSurface
+import com.android.credentialmanager.common.ui.TextSecondary
+import com.android.credentialmanager.common.ui.TextOnSurfaceVariant
+import com.android.credentialmanager.common.ui.ContainerCard
import com.android.credentialmanager.common.ui.TransparentBackgroundEntry
import com.android.credentialmanager.jetpack.developer.PublicKeyCredential
import com.android.credentialmanager.ui.theme.EntryShape
@Composable
fun GetCredentialScreen(
- viewModel: GetCredentialViewModel,
- providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
+ viewModel: GetCredentialViewModel,
+ providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
) {
- val entrySelectionCallback: (EntryInfo) -> Unit = {
- viewModel.onEntrySelected(it, providerActivityLauncher)
- }
- val state = rememberModalBottomSheetState(
- initialValue = ModalBottomSheetValue.Expanded,
- skipHalfExpanded = true
- )
- ModalBottomSheetLayout(
- sheetState = state,
- sheetContent = {
- val uiState = viewModel.uiState
- when (uiState.currentScreenState) {
- GetScreenState.PRIMARY_SELECTION -> PrimarySelectionCard(
- requestDisplayInfo = uiState.requestDisplayInfo,
- providerDisplayInfo = uiState.providerDisplayInfo,
- onEntrySelected = entrySelectionCallback,
- onCancel = viewModel::onCancel,
- onMoreOptionSelected = viewModel::onMoreOptionSelected,
- )
- GetScreenState.ALL_SIGN_IN_OPTIONS -> AllSignInOptionCard(
- providerInfoList = uiState.providerInfoList,
- providerDisplayInfo = uiState.providerDisplayInfo,
- onEntrySelected = entrySelectionCallback,
- onBackButtonClicked = viewModel::onBackToPrimarySelectionScreen,
- )
- }
- },
- scrimColor = MaterialTheme.colorScheme.scrim.copy(alpha = 0.8f),
- sheetShape = EntryShape.TopRoundedCorner,
- ) {}
- LaunchedEffect(state.currentValue) {
- if (state.currentValue == ModalBottomSheetValue.Hidden) {
- viewModel.onCancel()
+ val entrySelectionCallback: (EntryInfo) -> Unit = {
+ viewModel.onEntrySelected(it, providerActivityLauncher)
}
- }
+ val state = rememberModalBottomSheetState(
+ initialValue = ModalBottomSheetValue.Expanded,
+ skipHalfExpanded = true
+ )
+ ModalBottomSheetLayout(
+ sheetBackgroundColor = MaterialTheme.colorScheme.surface,
+ modifier = Modifier.background(Color.Transparent),
+ sheetState = state,
+ sheetContent = {
+ val uiState = viewModel.uiState
+ when (uiState.currentScreenState) {
+ GetScreenState.PRIMARY_SELECTION -> PrimarySelectionCard(
+ requestDisplayInfo = uiState.requestDisplayInfo,
+ providerDisplayInfo = uiState.providerDisplayInfo,
+ onEntrySelected = entrySelectionCallback,
+ onCancel = viewModel::onCancel,
+ onMoreOptionSelected = viewModel::onMoreOptionSelected,
+ )
+ GetScreenState.ALL_SIGN_IN_OPTIONS -> AllSignInOptionCard(
+ providerInfoList = uiState.providerInfoList,
+ providerDisplayInfo = uiState.providerDisplayInfo,
+ onEntrySelected = entrySelectionCallback,
+ onBackButtonClicked = viewModel::onBackToPrimarySelectionScreen,
+ )
+ }
+ },
+ scrimColor = MaterialTheme.colorScheme.scrim.copy(alpha = 0.8f),
+ sheetShape = EntryShape.TopRoundedCorner,
+ ) {}
+ LaunchedEffect(state.currentValue) {
+ if (state.currentValue == ModalBottomSheetValue.Hidden) {
+ viewModel.onCancel()
+ }
+ }
}
/** Draws the primary credential selection page. */
@Composable
fun PrimarySelectionCard(
- requestDisplayInfo: RequestDisplayInfo,
- providerDisplayInfo: ProviderDisplayInfo,
- onEntrySelected: (EntryInfo) -> Unit,
- onCancel: () -> Unit,
- onMoreOptionSelected: () -> Unit,
+ requestDisplayInfo: RequestDisplayInfo,
+ providerDisplayInfo: ProviderDisplayInfo,
+ onEntrySelected: (EntryInfo) -> Unit,
+ onCancel: () -> Unit,
+ onMoreOptionSelected: () -> Unit,
) {
- val sortedUserNameToCredentialEntryList = providerDisplayInfo.sortedUserNameToCredentialEntryList
- val authenticationEntryList = providerDisplayInfo.authenticationEntryList
- Card() {
- Column() {
- Text(
- modifier = Modifier.padding(all = 24.dp),
- textAlign = TextAlign.Center,
- style = MaterialTheme.typography.headlineSmall,
- text = stringResource(
- if (sortedUserNameToCredentialEntryList.size == 1) {
- if (sortedUserNameToCredentialEntryList.first().sortedCredentialEntryList
- .first().credentialType == PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL
+ val sortedUserNameToCredentialEntryList =
+ providerDisplayInfo.sortedUserNameToCredentialEntryList
+ val authenticationEntryList = providerDisplayInfo.authenticationEntryList
+ ContainerCard() {
+ Column() {
+ TextOnSurface(
+ modifier = Modifier.padding(all = 24.dp),
+ textAlign = TextAlign.Center,
+ style = MaterialTheme.typography.headlineSmall,
+ text = stringResource(
+ if (sortedUserNameToCredentialEntryList.size == 1) {
+ if (sortedUserNameToCredentialEntryList.first().sortedCredentialEntryList
+ .first().credentialType
+ == PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL
+ )
+ R.string.get_dialog_title_use_passkey_for
+ else R.string.get_dialog_title_use_sign_in_for
+ } else R.string.get_dialog_title_choose_sign_in_for,
+ requestDisplayInfo.appDomainName
+ ),
)
- R.string.get_dialog_title_use_passkey_for
- else R.string.get_dialog_title_use_sign_in_for
- } else R.string.get_dialog_title_choose_sign_in_for,
- requestDisplayInfo.appDomainName
- ),
- )
- Card(
- shape = MaterialTheme.shapes.medium,
- modifier = Modifier
- .padding(horizontal = 24.dp)
- .align(alignment = Alignment.CenterHorizontally)
- ) {
- LazyColumn(
- verticalArrangement = Arrangement.spacedBy(2.dp)
- ) {
- items(sortedUserNameToCredentialEntryList) {
- CredentialEntryRow(
- credentialEntryInfo = it.sortedCredentialEntryList.first(),
- onEntrySelected = onEntrySelected,
+ ContainerCard(
+ shape = MaterialTheme.shapes.medium,
+ modifier = Modifier
+ .padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally)
+ ) {
+ LazyColumn(
+ verticalArrangement = Arrangement.spacedBy(2.dp)
+ ) {
+ items(sortedUserNameToCredentialEntryList) {
+ CredentialEntryRow(
+ credentialEntryInfo = it.sortedCredentialEntryList.first(),
+ onEntrySelected = onEntrySelected,
+ )
+ }
+ items(authenticationEntryList) {
+ AuthenticationEntryRow(
+ authenticationEntryInfo = it,
+ onEntrySelected = onEntrySelected,
+ )
+ }
+ item {
+ SignInAnotherWayRow(onSelect = onMoreOptionSelected)
+ }
+ }
+ }
+ Divider(
+ thickness = 24.dp,
+ color = Color.Transparent
)
- }
- items(authenticationEntryList) {
- AuthenticationEntryRow(
- authenticationEntryInfo = it,
- onEntrySelected = onEntrySelected,
+ Row(
+ horizontalArrangement = Arrangement.Start,
+ modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
+ ) {
+ CancelButton(stringResource(R.string.get_dialog_button_label_no_thanks), onCancel)
+ }
+ Divider(
+ thickness = 18.dp,
+ color = Color.Transparent,
+ modifier = Modifier.padding(bottom = 16.dp)
)
- }
- item {
- SignInAnotherWayRow(onSelect = onMoreOptionSelected)
- }
}
- }
- Divider(
- thickness = 24.dp,
- color = Color.Transparent
- )
- Row(
- horizontalArrangement = Arrangement.Start,
- modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
- ) {
- CancelButton(stringResource(R.string.get_dialog_button_label_no_thanks), onCancel)
- }
- Divider(
- thickness = 18.dp,
- color = Color.Transparent,
- modifier = Modifier.padding(bottom = 16.dp)
- )
}
- }
}
/** Draws the secondary credential selection page, where all sign-in options are listed. */
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AllSignInOptionCard(
- providerInfoList: List<ProviderInfo>,
- providerDisplayInfo: ProviderDisplayInfo,
- onEntrySelected: (EntryInfo) -> Unit,
- onBackButtonClicked: () -> Unit,
+ providerInfoList: List<ProviderInfo>,
+ providerDisplayInfo: ProviderDisplayInfo,
+ onEntrySelected: (EntryInfo) -> Unit,
+ onBackButtonClicked: () -> Unit,
) {
- val sortedUserNameToCredentialEntryList = providerDisplayInfo.sortedUserNameToCredentialEntryList
- val authenticationEntryList = providerDisplayInfo.authenticationEntryList
- Card() {
- Column() {
- TopAppBar(
- colors = TopAppBarDefaults.smallTopAppBarColors(
- containerColor = Color.Transparent,
- ),
- title = {
- Text(
- text = stringResource(R.string.get_dialog_title_sign_in_options),
- style = MaterialTheme.typography.titleMedium
- )
- },
- navigationIcon = {
- IconButton(onClick = onBackButtonClicked) {
- Icon(
- Icons.Filled.ArrowBack,
- contentDescription = stringResource(R.string.accessibility_back_arrow_button))
- }
- },
- modifier = Modifier.padding(top = 12.dp)
- )
-
- Card(
- shape = MaterialTheme.shapes.large,
- modifier = Modifier
- .padding(start = 24.dp, end = 24.dp, bottom = 24.dp)
- .align(alignment = Alignment.CenterHorizontally)
- ) {
- LazyColumn(
- verticalArrangement = Arrangement.spacedBy(8.dp)
- ) {
- // For username
- items(sortedUserNameToCredentialEntryList) { item ->
- PerUserNameCredentials(
- perUserNameCredentialEntryList = item,
- onEntrySelected = onEntrySelected,
+ val sortedUserNameToCredentialEntryList =
+ providerDisplayInfo.sortedUserNameToCredentialEntryList
+ val authenticationEntryList = providerDisplayInfo.authenticationEntryList
+ ContainerCard() {
+ Column() {
+ TopAppBar(
+ colors = TopAppBarDefaults.smallTopAppBarColors(
+ containerColor = Color.Transparent,
+ ),
+ title = {
+ TextOnSurface(
+ text = stringResource(R.string.get_dialog_title_sign_in_options),
+ style = MaterialTheme.typography.titleMedium
+ )
+ },
+ navigationIcon = {
+ IconButton(onClick = onBackButtonClicked) {
+ Icon(
+ Icons.Filled.ArrowBack,
+ contentDescription = stringResource(
+ R.string.accessibility_back_arrow_button)
+ )
+ }
+ },
+ modifier = Modifier.padding(top = 12.dp)
)
- }
- // Locked password manager
- if (!authenticationEntryList.isEmpty()) {
- item {
- LockedCredentials(
- authenticationEntryList = authenticationEntryList,
- onEntrySelected = onEntrySelected,
- )
+
+ ContainerCard(
+ shape = MaterialTheme.shapes.large,
+ modifier = Modifier
+ .padding(start = 24.dp, end = 24.dp, bottom = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ ) {
+ LazyColumn(
+ verticalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ // For username
+ items(sortedUserNameToCredentialEntryList) { item ->
+ PerUserNameCredentials(
+ perUserNameCredentialEntryList = item,
+ onEntrySelected = onEntrySelected,
+ )
+ }
+ // Locked password manager
+ if (!authenticationEntryList.isEmpty()) {
+ item {
+ LockedCredentials(
+ authenticationEntryList = authenticationEntryList,
+ onEntrySelected = onEntrySelected,
+ )
+ }
+ }
+ // From another device
+ val remoteEntry = providerDisplayInfo.remoteEntry
+ if (remoteEntry != null) {
+ item {
+ RemoteEntryCard(
+ remoteEntry = remoteEntry,
+ onEntrySelected = onEntrySelected,
+ )
+ }
+ }
+ // Manage sign-ins (action chips)
+ item {
+ ActionChips(
+ providerInfoList = providerInfoList,
+ onEntrySelected = onEntrySelected
+ )
+ }
+ }
}
- }
- // From another device
- val remoteEntry = providerDisplayInfo.remoteEntry
- if (remoteEntry != null) {
- item {
- RemoteEntryCard(
- remoteEntry = remoteEntry,
- onEntrySelected = onEntrySelected,
- )
- }
- }
- // Manage sign-ins (action chips)
- item {
- ActionChips(providerInfoList = providerInfoList, onEntrySelected = onEntrySelected)
- }
}
- }
}
- }
}
// TODO: create separate rows for primary and secondary pages.
@@ -262,236 +275,245 @@
@Composable
fun ActionChips(
- providerInfoList: List<ProviderInfo>,
- onEntrySelected: (EntryInfo) -> Unit,
+ providerInfoList: List<ProviderInfo>,
+ onEntrySelected: (EntryInfo) -> Unit,
) {
- val actionChips = providerInfoList.flatMap { it.actionEntryList }
- if (actionChips.isEmpty()) {
- return
- }
-
- Text(
- text = stringResource(R.string.get_dialog_heading_manage_sign_ins),
- style = MaterialTheme.typography.labelLarge,
- modifier = Modifier.padding(vertical = 8.dp)
- )
- // TODO: tweak padding.
- Card(
- modifier = Modifier.fillMaxWidth().wrapContentHeight(),
- shape = MaterialTheme.shapes.medium,
- ) {
- Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
- actionChips.forEach {
- ActionEntryRow(it, onEntrySelected)
- }
+ val actionChips = providerInfoList.flatMap { it.actionEntryList }
+ if (actionChips.isEmpty()) {
+ return
}
- }
+
+ TextSecondary(
+ text = stringResource(R.string.get_dialog_heading_manage_sign_ins),
+ style = MaterialTheme.typography.labelLarge,
+ modifier = Modifier.padding(vertical = 8.dp)
+ )
+ // TODO: tweak padding.
+ ContainerCard(
+ modifier = Modifier.fillMaxWidth().wrapContentHeight(),
+ shape = MaterialTheme.shapes.medium,
+ ) {
+ Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
+ actionChips.forEach {
+ ActionEntryRow(it, onEntrySelected)
+ }
+ }
+ }
}
@Composable
fun RemoteEntryCard(
- remoteEntry: RemoteEntryInfo,
- onEntrySelected: (EntryInfo) -> Unit,
+ remoteEntry: RemoteEntryInfo,
+ onEntrySelected: (EntryInfo) -> Unit,
) {
- Text(
- text = stringResource(R.string.get_dialog_heading_from_another_device),
- style = MaterialTheme.typography.labelLarge,
- modifier = Modifier.padding(vertical = 8.dp)
- )
- Card(
- modifier = Modifier.fillMaxWidth().wrapContentHeight(),
- shape = MaterialTheme.shapes.medium,
- ) {
- Column(
- modifier = Modifier.fillMaxWidth().wrapContentHeight(),
- verticalArrangement = Arrangement.spacedBy(2.dp),
+ TextSecondary(
+ text = stringResource(R.string.get_dialog_heading_from_another_device),
+ style = MaterialTheme.typography.labelLarge,
+ modifier = Modifier.padding(vertical = 8.dp)
+ )
+ ContainerCard(
+ modifier = Modifier.fillMaxWidth().wrapContentHeight(),
+ shape = MaterialTheme.shapes.medium,
) {
- Entry(
- onClick = {onEntrySelected(remoteEntry)},
- icon = {
- Icon(
- painter = painterResource(R.drawable.ic_other_devices),
- contentDescription = null,
- tint = Color.Unspecified,
- modifier = Modifier.padding(start = 18.dp)
- )
- },
- label = {
- Text(
- text = stringResource(R.string.get_dialog_option_headline_use_a_different_device),
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(start = 16.dp, top = 18.dp, bottom = 18.dp)
- .align(alignment = Alignment.CenterHorizontally)
- )
+ Column(
+ modifier = Modifier.fillMaxWidth().wrapContentHeight(),
+ verticalArrangement = Arrangement.spacedBy(2.dp),
+ ) {
+ Entry(
+ onClick = { onEntrySelected(remoteEntry) },
+ icon = {
+ Icon(
+ painter = painterResource(R.drawable.ic_other_devices),
+ contentDescription = null,
+ tint = Color.Unspecified,
+ modifier = Modifier.padding(start = 18.dp)
+ )
+ },
+ label = {
+ TextOnSurfaceVariant(
+ text = stringResource(
+ R.string.get_dialog_option_headline_use_a_different_device),
+ style = MaterialTheme.typography.titleLarge,
+ modifier = Modifier.padding(start = 16.dp, top = 18.dp, bottom = 18.dp)
+ .align(alignment = Alignment.CenterHorizontally)
+ )
+ }
+ )
}
- )
}
- }
}
@Composable
fun LockedCredentials(
- authenticationEntryList: List<AuthenticationEntryInfo>,
- onEntrySelected: (EntryInfo) -> Unit,
+ authenticationEntryList: List<AuthenticationEntryInfo>,
+ onEntrySelected: (EntryInfo) -> Unit,
) {
- Text(
- text = stringResource(R.string.get_dialog_heading_locked_password_managers),
- style = MaterialTheme.typography.labelLarge,
- modifier = Modifier.padding(vertical = 8.dp)
- )
- Card(
- modifier = Modifier.fillMaxWidth().wrapContentHeight(),
- shape = MaterialTheme.shapes.medium,
- ) {
- Column(
- modifier = Modifier.fillMaxWidth().wrapContentHeight(),
- verticalArrangement = Arrangement.spacedBy(2.dp),
+ TextSecondary(
+ text = stringResource(R.string.get_dialog_heading_locked_password_managers),
+ style = MaterialTheme.typography.labelLarge,
+ modifier = Modifier.padding(vertical = 8.dp)
+ )
+ ContainerCard(
+ modifier = Modifier.fillMaxWidth().wrapContentHeight(),
+ shape = MaterialTheme.shapes.medium,
) {
- authenticationEntryList.forEach {
- AuthenticationEntryRow(it, onEntrySelected)
- }
+ Column(
+ modifier = Modifier.fillMaxWidth().wrapContentHeight(),
+ verticalArrangement = Arrangement.spacedBy(2.dp),
+ ) {
+ authenticationEntryList.forEach {
+ AuthenticationEntryRow(it, onEntrySelected)
+ }
+ }
}
- }
}
@Composable
fun PerUserNameCredentials(
- perUserNameCredentialEntryList: PerUserNameCredentialEntryList,
- onEntrySelected: (EntryInfo) -> Unit,
+ perUserNameCredentialEntryList: PerUserNameCredentialEntryList,
+ onEntrySelected: (EntryInfo) -> Unit,
) {
- Text(
- text = stringResource(
- R.string.get_dialog_heading_for_username, perUserNameCredentialEntryList.userName),
- style = MaterialTheme.typography.labelLarge,
- modifier = Modifier.padding(vertical = 8.dp)
- )
- Card(
- modifier = Modifier.fillMaxWidth().wrapContentHeight(),
- shape = MaterialTheme.shapes.medium,
- ) {
- Column(
- modifier = Modifier.fillMaxWidth().wrapContentHeight(),
- verticalArrangement = Arrangement.spacedBy(2.dp),
+ TextSecondary(
+ text = stringResource(
+ R.string.get_dialog_heading_for_username, perUserNameCredentialEntryList.userName
+ ),
+ style = MaterialTheme.typography.labelLarge,
+ modifier = Modifier.padding(vertical = 8.dp)
+ )
+ ContainerCard(
+ modifier = Modifier.fillMaxWidth().wrapContentHeight(),
+ shape = MaterialTheme.shapes.medium,
) {
- perUserNameCredentialEntryList.sortedCredentialEntryList.forEach {
- CredentialEntryRow(it, onEntrySelected)
- }
+ Column(
+ modifier = Modifier.fillMaxWidth().wrapContentHeight(),
+ verticalArrangement = Arrangement.spacedBy(2.dp),
+ ) {
+ perUserNameCredentialEntryList.sortedCredentialEntryList.forEach {
+ CredentialEntryRow(it, onEntrySelected)
+ }
+ }
}
- }
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CredentialEntryRow(
- credentialEntryInfo: CredentialEntryInfo,
- onEntrySelected: (EntryInfo) -> Unit,
+ credentialEntryInfo: CredentialEntryInfo,
+ onEntrySelected: (EntryInfo) -> Unit,
) {
- Entry(
- onClick = {onEntrySelected(credentialEntryInfo)},
- icon = {
- Image(modifier = Modifier.padding(start = 10.dp).size(32.dp),
- bitmap = credentialEntryInfo.icon.toBitmap().asImageBitmap(),
- // TODO: add description.
- contentDescription = "")
- },
- label = {
- Column() {
- // TODO: fix the text values.
- Text(
- text = credentialEntryInfo.userName,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp)
- )
- Text(
- text =
- if (TextUtils.isEmpty(credentialEntryInfo.displayName))
- credentialEntryInfo.credentialTypeDisplayName
- else
- credentialEntryInfo.credentialTypeDisplayName +
- stringResource(R.string.get_dialog_sign_in_type_username_separator) +
- credentialEntryInfo.displayName,
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp)
- )
- }
- }
- )
+ Entry(
+ onClick = { onEntrySelected(credentialEntryInfo) },
+ icon = {
+ Image(
+ modifier = Modifier.padding(start = 10.dp).size(32.dp),
+ bitmap = credentialEntryInfo.icon.toBitmap().asImageBitmap(),
+ // TODO: add description.
+ contentDescription = ""
+ )
+ },
+ label = {
+ Column() {
+ // TODO: fix the text values.
+ TextOnSurfaceVariant(
+ text = credentialEntryInfo.userName,
+ style = MaterialTheme.typography.titleLarge,
+ modifier = Modifier.padding(top = 16.dp)
+ )
+ TextSecondary(
+ text =
+ if (TextUtils.isEmpty(credentialEntryInfo.displayName))
+ credentialEntryInfo.credentialTypeDisplayName
+ else
+ credentialEntryInfo.credentialTypeDisplayName +
+ stringResource(
+ R.string.get_dialog_sign_in_type_username_separator) +
+ credentialEntryInfo.displayName,
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.padding(bottom = 16.dp)
+ )
+ }
+ }
+ )
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AuthenticationEntryRow(
- authenticationEntryInfo: AuthenticationEntryInfo,
- onEntrySelected: (EntryInfo) -> Unit,
+ authenticationEntryInfo: AuthenticationEntryInfo,
+ onEntrySelected: (EntryInfo) -> Unit,
) {
- Entry(
- onClick = {onEntrySelected(authenticationEntryInfo)},
- icon = {
- Image(modifier = Modifier.padding(start = 10.dp).size(32.dp),
- bitmap = authenticationEntryInfo.icon.toBitmap().asImageBitmap(),
- // TODO: add description.
- contentDescription = "")
- },
- label = {
- Column() {
- // TODO: fix the text values.
- Text(
- text = authenticationEntryInfo.title,
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp)
- )
- Text(
- text = stringResource(R.string.locked_credential_entry_label_subtext),
- style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp)
- )
- }
- }
- )
+ Entry(
+ onClick = { onEntrySelected(authenticationEntryInfo) },
+ icon = {
+ Image(
+ modifier = Modifier.padding(start = 10.dp).size(32.dp),
+ bitmap = authenticationEntryInfo.icon.toBitmap().asImageBitmap(),
+ // TODO: add description.
+ contentDescription = ""
+ )
+ },
+ label = {
+ Column() {
+ // TODO: fix the text values.
+ TextOnSurfaceVariant(
+ text = authenticationEntryInfo.title,
+ style = MaterialTheme.typography.titleLarge,
+ modifier = Modifier.padding(top = 16.dp)
+ )
+ TextSecondary(
+ text = stringResource(R.string.locked_credential_entry_label_subtext),
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.padding(bottom = 16.dp)
+ )
+ }
+ }
+ )
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ActionEntryRow(
- actionEntryInfo: ActionEntryInfo,
- onEntrySelected: (EntryInfo) -> Unit,
+ actionEntryInfo: ActionEntryInfo,
+ onEntrySelected: (EntryInfo) -> Unit,
) {
- TransparentBackgroundEntry(
- icon = {
- Image(modifier = Modifier.padding(start = 10.dp).size(32.dp),
- bitmap = actionEntryInfo.icon.toBitmap().asImageBitmap(),
- // TODO: add description.
- contentDescription = "")
- },
- label = {
- Column() {
- Text(
- text = actionEntryInfo.title,
- style = MaterialTheme.typography.titleLarge,
- )
- if (actionEntryInfo.subTitle != null) {
- Text(
- text = actionEntryInfo.subTitle,
- style = MaterialTheme.typography.bodyMedium,
- )
- }
- }
- },
- onClick = { onEntrySelected(actionEntryInfo) },
- )
+ TransparentBackgroundEntry(
+ icon = {
+ Image(
+ modifier = Modifier.padding(start = 10.dp).size(32.dp),
+ bitmap = actionEntryInfo.icon.toBitmap().asImageBitmap(),
+ // TODO: add description.
+ contentDescription = ""
+ )
+ },
+ label = {
+ Column() {
+ TextOnSurfaceVariant(
+ text = actionEntryInfo.title,
+ style = MaterialTheme.typography.titleLarge,
+ )
+ if (actionEntryInfo.subTitle != null) {
+ TextSecondary(
+ text = actionEntryInfo.subTitle,
+ style = MaterialTheme.typography.bodyMedium,
+ )
+ }
+ }
+ },
+ onClick = { onEntrySelected(actionEntryInfo) },
+ )
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SignInAnotherWayRow(onSelect: () -> Unit) {
- Entry(
- onClick = onSelect,
- label = {
- Text(
- text = stringResource(R.string.get_dialog_use_saved_passkey_for),
- style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(vertical = 16.dp)
- )
- }
- )
+ Entry(
+ onClick = onSelect,
+ label = {
+ TextOnSurfaceVariant(
+ text = stringResource(R.string.get_dialog_use_saved_passkey_for),
+ style = MaterialTheme.typography.titleLarge,
+ modifier = Modifier.padding(vertical = 16.dp)
+ )
+ }
+ )
}
diff --git a/packages/PackageInstaller/Android.bp b/packages/PackageInstaller/Android.bp
index 4757513..fe640ad 100644
--- a/packages/PackageInstaller/Android.bp
+++ b/packages/PackageInstaller/Android.bp
@@ -58,6 +58,7 @@
privileged: true,
platform_apis: true,
rename_resources_package: false,
+ overrides: ["PackageInstaller"],
static_libs: [
"xz-java",
@@ -76,6 +77,7 @@
privileged: true,
platform_apis: true,
rename_resources_package: false,
+ overrides: ["PackageInstaller"],
static_libs: [
"xz-java",
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-af/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-af/strings.xml
new file mode 100644
index 0000000..3ad7bb0
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-af/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Geen apps nie."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Wys stelsel"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Versteek stelsel"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Toegelaat"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nie toegelaat nie"</string>
+ <string name="version_text" msgid="4001669804596458577">"weergawe <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-am/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-am/strings.xml
new file mode 100644
index 0000000..4c2525bfd
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-am/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"መተግበሪያዎች የሉም።"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"ሥርዓትን አሳይ"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"ሥርዓትን ደብቅ"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"ይፈቀዳል"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"አይፈቀድም"</string>
+ <string name="version_text" msgid="4001669804596458577">"ሥሪት <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml
new file mode 100644
index 0000000..436914d
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"ليس هناك أي تطبيقات."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"إظهار عمليات النظام"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"إخفاء عمليات النظام"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"مسموح به"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"غير مسموح به"</string>
+ <string name="version_text" msgid="4001669804596458577">"الإصدار <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-as/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-as/strings.xml
new file mode 100644
index 0000000..c1c88f2
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-as/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"কোনো এপ্ নাই।"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"ছিষ্টেম দেখুৱাওক"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"ছিষ্টেম লুকুৱাওক"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"অনুমতি দিয়া হৈছে"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"অনুমতি নাই"</string>
+ <string name="version_text" msgid="4001669804596458577">"সংস্কৰণ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-az/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-az/strings.xml
new file mode 100644
index 0000000..4fc090a
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-az/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Tətbiq yoxdur."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Sistemi göstərin"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Sistemi gizlədin"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"İcazə verildi"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"İcazə verilməyib"</string>
+ <string name="version_text" msgid="4001669804596458577">"versiya <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..3708503
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Nema aplikacija."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Prikaži sistemske"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Sakrij sistemske"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Dozvoljeno"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nije dozvoljeno"</string>
+ <string name="version_text" msgid="4001669804596458577">"verzija <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-be/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-be/strings.xml
new file mode 100644
index 0000000..38fb12b
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-be/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Няма праграм."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Паказаць сістэмныя працэсы"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Схаваць сістэмныя працэсы"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Дазволена"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Забаронена"</string>
+ <string name="version_text" msgid="4001669804596458577">"версія <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-bg/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-bg/strings.xml
new file mode 100644
index 0000000..b9b03bf
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-bg/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Няма приложения."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Показване на системните процеси"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Скриване на системните процеси"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Разрешено"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Не е разрешено"</string>
+ <string name="version_text" msgid="4001669804596458577">"версия <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-bn/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-bn/strings.xml
new file mode 100644
index 0000000..b805b3c
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-bn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"কোনও অ্যাপ নেই।"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"সিস্টেম দেখুন"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"সিস্টেম লুকান"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"অনুমোদিত"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"অননুমোদিত"</string>
+ <string name="version_text" msgid="4001669804596458577">"ভার্সন <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-bs/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-bs/strings.xml
new file mode 100644
index 0000000..9ceb340
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-bs/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Nema aplikacija."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Prikaži sistemske aplikacije"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Sakrij sistemske aplikacije"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Dozvoljeno"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nije dozvoljeno"</string>
+ <string name="version_text" msgid="4001669804596458577">"verzija <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ca/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ca/strings.xml
new file mode 100644
index 0000000..00cb41b
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ca/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"No hi ha cap aplicació."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Mostra el sistema"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Amaga el sistema"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Amb permís"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Sense permís"</string>
+ <string name="version_text" msgid="4001669804596458577">"versió <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-cs/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-cs/strings.xml
new file mode 100644
index 0000000..7b28f11
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-cs/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Žádné aplikace"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Zobrazit systémové aplikace"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Skrýt systémové aplikace"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Povoleno"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nepovoleno"</string>
+ <string name="version_text" msgid="4001669804596458577">"verze <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-da/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-da/strings.xml
new file mode 100644
index 0000000..f1893be
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-da/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Ingen apps."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Vis system"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Skjul system"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Tilladt"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ikke tilladt"</string>
+ <string name="version_text" msgid="4001669804596458577">"version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-de/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-de/strings.xml
new file mode 100644
index 0000000..471a7a7
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-de/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Keine Apps."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"System-Apps anzeigen"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"System-Apps ausblenden"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Zulässig"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nicht zulässig"</string>
+ <string name="version_text" msgid="4001669804596458577">"Version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-el/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-el/strings.xml
new file mode 100644
index 0000000..6c46e27
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-el/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Δεν υπάρχουν εφαρμογές."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Εμφάνιση συστήματος"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Απόκρυψη συστήματος"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Επιτρέπεται"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Δεν επιτρέπεται"</string>
+ <string name="version_text" msgid="4001669804596458577">"έκδοση <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-en-rAU/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..de48ff1
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-en-rAU/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"No apps."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Show system"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Hide system"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Allowed"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Not allowed"</string>
+ <string name="version_text" msgid="4001669804596458577">"Version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-en-rGB/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..de48ff1
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-en-rGB/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"No apps."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Show system"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Hide system"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Allowed"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Not allowed"</string>
+ <string name="version_text" msgid="4001669804596458577">"Version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-en-rIN/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..de48ff1
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-en-rIN/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"No apps."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Show system"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Hide system"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Allowed"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Not allowed"</string>
+ <string name="version_text" msgid="4001669804596458577">"Version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-es-rUS/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..d211eeb
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-es-rUS/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"No hay apps."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Mostrar sistema"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Ocultar sistema"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permitida"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"No se permite"</string>
+ <string name="version_text" msgid="4001669804596458577">"versión <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-es/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-es/strings.xml
new file mode 100644
index 0000000..d907cb8
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-es/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"No hay aplicaciones."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Mostrar sistema"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Ocultar sistema"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permitida"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"No permitida"</string>
+ <string name="version_text" msgid="4001669804596458577">"versión <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-et/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-et/strings.xml
new file mode 100644
index 0000000..2be2967
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-et/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Rakendusi pole."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Kuva süsteem"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Peida süsteem"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Lubatud"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Pole lubatud"</string>
+ <string name="version_text" msgid="4001669804596458577">"versioon <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-eu/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-eu/strings.xml
new file mode 100644
index 0000000..7fb2ee28
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-eu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Ez dago aplikaziorik."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Erakutsi sistemaren aplikazioak"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Ezkutatu sistemaren aplikazioak"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Baimena dauka"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ez dauka baimenik"</string>
+ <string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> bertsioa"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-fa/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-fa/strings.xml
new file mode 100644
index 0000000..7711cac
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-fa/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"برنامهای وجود ندارد."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"نمایش سیستم"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"پنهان کردن سیستم"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"مجاز"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"غیرمجاز"</string>
+ <string name="version_text" msgid="4001669804596458577">"نسخه <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-fi/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-fi/strings.xml
new file mode 100644
index 0000000..af65bfe
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-fi/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Ei sovelluksia."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Näytä järjestelmä"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Piilota järjestelmä"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Sallittu"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ei sallittu"</string>
+ <string name="version_text" msgid="4001669804596458577">"versio <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-fr-rCA/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..31f1ee0
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-fr-rCA/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Aucune application"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Afficher le système"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Masquer le système"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Autorisé"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Non autorisée"</string>
+ <string name="version_text" msgid="4001669804596458577">"version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-fr/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-fr/strings.xml
new file mode 100644
index 0000000..5b7b5e6
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-fr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Aucune appli."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Afficher le système"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Masquer le système"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Autorisé"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Non autorisé"</string>
+ <string name="version_text" msgid="4001669804596458577">"version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-gl/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-gl/strings.xml
new file mode 100644
index 0000000..3d1f9d8
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-gl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Ningunha aplicación"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Mostrar sistema"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Ocultar sistema"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permitida"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Non permitida"</string>
+ <string name="version_text" msgid="4001669804596458577">"versión <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-gu/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-gu/strings.xml
new file mode 100644
index 0000000..c598b70
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-gu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"કોઈ ઍપ નથી."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"સિસ્ટમ બતાવો"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"સિસ્ટમ છુપાવો"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"મંજૂરી છે"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"મંજૂરી નથી"</string>
+ <string name="version_text" msgid="4001669804596458577">"વર્ઝન <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-hi/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-hi/strings.xml
new file mode 100644
index 0000000..809afd3
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-hi/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"कोई ऐप्लिकेशन नहीं है."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"सिस्टम के ऐप्लिकेशन दिखाएं"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"सिस्टम के ऐप्लिकेशन छिपाएं"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"अनुमति है"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"अनुमति नहीं है"</string>
+ <string name="version_text" msgid="4001669804596458577">"वर्शन <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-hr/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-hr/strings.xml
new file mode 100644
index 0000000..1a87974
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-hr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Nema aplikacija."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Prikaži sustav"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Sakrij sustav"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Dopušteno"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nije dopušteno"</string>
+ <string name="version_text" msgid="4001669804596458577">"verzija <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-hu/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-hu/strings.xml
new file mode 100644
index 0000000..1ae7cdf
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-hu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Nincsenek alkalmazások."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Rendszerfolyamatok megjelenítése"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Rendszerfolyamatok elrejtése"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Engedélyezve"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nem engedélyezett"</string>
+ <string name="version_text" msgid="4001669804596458577">"verzió: <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-hy/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-hy/strings.xml
new file mode 100644
index 0000000..353af77
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-hy/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Հավելվածներ չկան։"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Ցույց տալ համակարգային գործընթացները"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Թաքցնել համակարգային գործընթացները"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Թույլատրված է"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Արգելված է"</string>
+ <string name="version_text" msgid="4001669804596458577">"տարբերակ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml
new file mode 100644
index 0000000..8b766b0
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Tidak ada aplikasi."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Tampilkan sistem"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Sembunyikan sistem"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Diizinkan"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Tidak diizinkan"</string>
+ <string name="version_text" msgid="4001669804596458577">"versi <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-is/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-is/strings.xml
new file mode 100644
index 0000000..cbd412d
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-is/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Engin forrit."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Sýna kerfi"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Fela kerfi"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Leyft"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ekki leyft"</string>
+ <string name="version_text" msgid="4001669804596458577">"útgáfa <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-it/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-it/strings.xml
new file mode 100644
index 0000000..d83c70d
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-it/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Nessuna app."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Mostra sistema"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Nascondi sistema"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Consentita"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Non consentita"</string>
+ <string name="version_text" msgid="4001669804596458577">"versione <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-iw/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-iw/strings.xml
new file mode 100644
index 0000000..7ed8a6b
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-iw/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"אין אפליקציות."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"הצגת תהליכי מערכת"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"הסתרת תהליכי מערכת"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"יש הרשאה"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"אין הרשאה"</string>
+ <string name="version_text" msgid="4001669804596458577">"גרסה <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ja/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ja/strings.xml
new file mode 100644
index 0000000..b12cb5c
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ja/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"アプリはありません。"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"システムアプリを表示"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"システムアプリを表示しない"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"許可"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"許可しない"</string>
+ <string name="version_text" msgid="4001669804596458577">"バージョン <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ka/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ka/strings.xml
new file mode 100644
index 0000000..c01a028
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ka/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"არ არის აპები."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"სისტემის ჩვენება"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"სისტემის დამალვა"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"დაშვებულია"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"დაუშვებელია"</string>
+ <string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> ვერსია"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-kk/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-kk/strings.xml
new file mode 100644
index 0000000..fb94404
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-kk/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Қолданба жоқ."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Жүйені көрсету"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Жүйені жасыру"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Рұқсат етілген"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Рұқсат етілмеген"</string>
+ <string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> нұсқасы"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-km/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-km/strings.xml
new file mode 100644
index 0000000..610123d
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-km/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"គ្មានកម្មវិធី។"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"បង្ហាញប្រព័ន្ធ"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"លាក់ប្រព័ន្ធ"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"បានអនុញ្ញាត"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"មិនអនុញ្ញាតទេ"</string>
+ <string name="version_text" msgid="4001669804596458577">"កំណែ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-kn/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-kn/strings.xml
new file mode 100644
index 0000000..b61c008
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-kn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"ಯಾವುದೇ ಆ್ಯಪ್ಗಳಿಲ್ಲ."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"ಸಿಸ್ಟಂ ತೋರಿಸಿ"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"ಸಿಸ್ಟಂ ಮರೆಮಾಡಿ"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"ಅನುಮತಿಸಲಾಗಿದೆ"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ"</string>
+ <string name="version_text" msgid="4001669804596458577">"ಆವೃತ್ತಿ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ko/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ko/strings.xml
new file mode 100644
index 0000000..660dc0e
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ko/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"앱 없음"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"시스템 표시"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"시스템 숨기기"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"허용됨"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"허용되지 않음"</string>
+ <string name="version_text" msgid="4001669804596458577">"버전 <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ky/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ky/strings.xml
new file mode 100644
index 0000000..898ec09
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ky/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Бир дагы колдонмо жок."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Системаны көрсөтүү"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Системаны жашыруу"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Уруксат берилген"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Тыюу салынган"</string>
+ <string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> версиясы"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-lo/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-lo/strings.xml
new file mode 100644
index 0000000..d0f77e4
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-lo/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"ບໍ່ມີແອັບ."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"ສະແດງລະບົບ"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"ເຊື່ອງລະບົບ"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"ອະນຸຍາດແລ້ວ"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ບໍ່ໄດ້ອະນຸຍາດ"</string>
+ <string name="version_text" msgid="4001669804596458577">"ເວີຊັນ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-lt/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-lt/strings.xml
new file mode 100644
index 0000000..7d33f91
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-lt/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Nėra programų"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Rodyti sistemą"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Slėpti sistemą"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Leidžiama"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Neleidžiama"</string>
+ <string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> versija"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-lv/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-lv/strings.xml
new file mode 100644
index 0000000..66dc44d
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-lv/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Nav lietotņu."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Rādīt sistēmas procesus"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Slēpt sistēmas procesus"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Atļauja piešķirta"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Atļauja nav piešķirta"</string>
+ <string name="version_text" msgid="4001669804596458577">"versija <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-mk/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-mk/strings.xml
new file mode 100644
index 0000000..db55600
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-mk/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Нема апликации."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Прикажи го системот"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Сокриј го системот"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Со дозволен пристап"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Без дозволен пристап"</string>
+ <string name="version_text" msgid="4001669804596458577">"верзија <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ml/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ml/strings.xml
new file mode 100644
index 0000000..c99d0d3
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ml/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"ആപ്പുകളൊന്നുമില്ല."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"സിസ്റ്റം കാണിക്കുക"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"സിസ്റ്റം മറയ്ക്കുക"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"അനുവാദം ലഭിച്ചു"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"അനുവാദം ലഭിച്ചില്ല"</string>
+ <string name="version_text" msgid="4001669804596458577">"പതിപ്പ് <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-mn/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-mn/strings.xml
new file mode 100644
index 0000000..bc0864b
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-mn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Апп байхгүй."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Системийг харуулах"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Системийг нуух"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Зөвшөөрсөн"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Зөвшөөрөөгүй"</string>
+ <string name="version_text" msgid="4001669804596458577">"хувилбар <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-mr/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-mr/strings.xml
new file mode 100644
index 0000000..55a178b
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-mr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"अॅप्स नाहीत."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"सिस्टीम दाखवा"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"सिस्टीम लपवा"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"अनुमती असलेले"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"अनुमती नाही"</string>
+ <string name="version_text" msgid="4001669804596458577">"आवृत्ती <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ms/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ms/strings.xml
new file mode 100644
index 0000000..a736de9
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ms/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Tiada aplikasi."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Tunjukkan sistem"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Sembunyikan sistem"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Dibenarkan"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Tidak dibenarkan"</string>
+ <string name="version_text" msgid="4001669804596458577">"versi <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-my/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-my/strings.xml
new file mode 100644
index 0000000..3bed608
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-my/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"အက်ပ်မရှိပါ။"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"စနစ်ကိုပြပါ"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"စနစ်ကိုဖျောက်ထားရန်"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"ခွင့်ပြုထားသည်"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ခွင့်ပြုမထားပါ"</string>
+ <string name="version_text" msgid="4001669804596458577">"ဗားရှင်း <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-nb/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-nb/strings.xml
new file mode 100644
index 0000000..d6bd063
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-nb/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Ingen apper."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Vis systemprosesser"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Skjul systemprosesser"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Tillatt"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ikke tillatt"</string>
+ <string name="version_text" msgid="4001669804596458577">"versjon <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml
new file mode 100644
index 0000000..97db4ea
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"कुनै पनि एप छैन।"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"सिस्टम देखाइयोस्"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"सिस्टम लुकाइयोस्"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"अनुमति दिइएका एप"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"अनुमति नदिइएका एप"</string>
+ <string name="version_text" msgid="4001669804596458577">"संस्करण <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-nl/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-nl/strings.xml
new file mode 100644
index 0000000..7157e3f
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-nl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Geen apps."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Systeem-apps tonen"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Systeem-apps verbergen"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Toegestaan"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Niet toegestaan"</string>
+ <string name="version_text" msgid="4001669804596458577">"versie <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-or/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-or/strings.xml
new file mode 100644
index 0000000..24779e3
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-or/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"କୌଣସି ଆପ୍ସ ନାହିଁ।"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"ସିଷ୍ଟମ ଦେଖାନ୍ତୁ"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"ସିଷ୍ଟମକୁ ଲୁଚାନ୍ତୁ"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"ଅନୁମତି ଦିଆଯାଇଛି"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ଅନୁମତି ଦିଆଯାଇନାହିଁ"</string>
+ <string name="version_text" msgid="4001669804596458577">"ଭର୍ସନ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-pa/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-pa/strings.xml
new file mode 100644
index 0000000..fe1a3eb
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-pa/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"ਕੋਈ ਐਪ ਨਹੀਂ।"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"ਸਿਸਟਮ ਦਿਖਾਓ"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"ਸਿਸਟਮ ਲੁਕਾਓ"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"ਆਗਿਆ ਹੈ"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ਆਗਿਆ ਨਹੀਂ ਹੈ"</string>
+ <string name="version_text" msgid="4001669804596458577">"ਵਰਜਨ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-pl/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-pl/strings.xml
new file mode 100644
index 0000000..9d5ba9d
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-pl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Brak aplikacji."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Pokaż systemowe"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Ukryj systemowe"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Dozwolone"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Niedozwolone"</string>
+ <string name="version_text" msgid="4001669804596458577">"wersja <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-pt-rBR/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..18a31d8
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-pt-rBR/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Nenhum app."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Mostrar sistema"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Ocultar sistema"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permitido"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Não permitido"</string>
+ <string name="version_text" msgid="4001669804596458577">"Versão <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-pt-rPT/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..ddf5e51
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-pt-rPT/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Sem apps."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Mostrar sistema"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Ocultar sistema"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permitida"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Não permitida"</string>
+ <string name="version_text" msgid="4001669804596458577">"versão <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-pt/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-pt/strings.xml
new file mode 100644
index 0000000..18a31d8
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-pt/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Nenhum app."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Mostrar sistema"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Ocultar sistema"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permitido"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Não permitido"</string>
+ <string name="version_text" msgid="4001669804596458577">"Versão <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ro/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ro/strings.xml
new file mode 100644
index 0000000..ef58fb8
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ro/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Nu există aplicații."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Afișează procesele de sistem"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Ascunde procesele de sistem"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permisă"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nepermisă"</string>
+ <string name="version_text" msgid="4001669804596458577">"versiunea <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ru/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ru/strings.xml
new file mode 100644
index 0000000..6d69c80
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ru/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Нет приложений."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Показать системные процессы"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Скрыть системные процессы"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Разрешено"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Запрещено"</string>
+ <string name="version_text" msgid="4001669804596458577">"версия <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-si/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-si/strings.xml
new file mode 100644
index 0000000..d2c20e6
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-si/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"යෙදුම් නොමැත."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"පද්ධතිය පෙන්වන්න"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"පද්ධතිය සඟවන්න"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"ඉඩ දුන්"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ඉඩ නොදෙන"</string>
+ <string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> අනුවාදය"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-sk/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-sk/strings.xml
new file mode 100644
index 0000000..0d0984f
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-sk/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Žiadne aplikácie."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Zobraziť systémové procesy"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Skryť systémové procesy"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Povolené"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nepovolené"</string>
+ <string name="version_text" msgid="4001669804596458577">"verzia <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-sl/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-sl/strings.xml
new file mode 100644
index 0000000..c8bd15a
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-sl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Ni aplikacij."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Prikaži sistemske procese"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Skrij sistemske procese"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Dovoljeno"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ni dovoljeno"</string>
+ <string name="version_text" msgid="4001669804596458577">"različica <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-sq/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-sq/strings.xml
new file mode 100644
index 0000000..112868a
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-sq/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Asnjë aplikacion"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Shfaq sistemin"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Fshih sistemin"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Lejohet"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nuk lejohet"</string>
+ <string name="version_text" msgid="4001669804596458577">"versioni <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-sr/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-sr/strings.xml
new file mode 100644
index 0000000..4c99d60
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-sr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Нема апликација."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Прикажи системске"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Сакриј системске"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Дозвољено"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Није дозвољено"</string>
+ <string name="version_text" msgid="4001669804596458577">"верзија <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-sv/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-sv/strings.xml
new file mode 100644
index 0000000..1dd5efd
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-sv/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Inga appar."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Visa systemet"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Dölj systemet"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Tillåts"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Tillåts inte"</string>
+ <string name="version_text" msgid="4001669804596458577">"version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-sw/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-sw/strings.xml
new file mode 100644
index 0000000..a0ee70c
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-sw/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Hakuna programu yoyote."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Onyesha mfumo"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Ficha mfumo"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Inaruhusiwa"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Hairuhusiwi"</string>
+ <string name="version_text" msgid="4001669804596458577">"toleo la <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ta/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ta/strings.xml
new file mode 100644
index 0000000..36d64e8
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ta/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"ஆப்ஸ் இல்லை."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"சிஸ்டம் ஆப்ஸைக் காட்டு"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"சிஸ்டம் ஆப்ஸை மறை"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"அனுமதிக்கப்பட்டது"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"அனுமதிக்கப்படவில்லை"</string>
+ <string name="version_text" msgid="4001669804596458577">"பதிப்பு <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-te/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-te/strings.xml
new file mode 100644
index 0000000..a908dd4
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-te/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"యాప్లు ఏవి లేవు."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"సిస్టమ్ ప్రాసెస్లను చూపించండి"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"సిస్టమ్ను దాచండి"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"అనుమతించబడినవి"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"అనుమతించబడలేదు"</string>
+ <string name="version_text" msgid="4001669804596458577">"వెర్షన్ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-th/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-th/strings.xml
new file mode 100644
index 0000000..1d7db1a
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-th/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"ไม่มีแอป"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"แสดงระบบ"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"ซ่อนระบบ"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"อนุญาต"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ไม่อนุญาต"</string>
+ <string name="version_text" msgid="4001669804596458577">"เวอร์ชัน <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-tl/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-tl/strings.xml
new file mode 100644
index 0000000..fb56559a
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-tl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Walang app."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Ipakita ang system"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Itago ang system"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Pinapahintulutan"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Hindi pinapahintulutan"</string>
+ <string name="version_text" msgid="4001669804596458577">"bersyon <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-tr/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-tr/strings.xml
new file mode 100644
index 0000000..5f5722b
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-tr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Uygulama yok"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Sistemi göster"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Sistemi gizle"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"İzin veriliyor"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"İzin verilmiyor"</string>
+ <string name="version_text" msgid="4001669804596458577">"sürüm: <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-uk/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-uk/strings.xml
new file mode 100644
index 0000000..a8632ca
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-uk/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Додатків немає."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Показати системні додатки"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Сховати системні додатки"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Дозволено"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Заборонено"</string>
+ <string name="version_text" msgid="4001669804596458577">"версія <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ur/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ur/strings.xml
new file mode 100644
index 0000000..4b969bb
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ur/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"کوئی ایپ نہیں ہے۔"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"سسٹم دکھائیں"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"سسٹم چھپائیں"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"اجازت ہے"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"اجازت نہیں ہے"</string>
+ <string name="version_text" msgid="4001669804596458577">"ورژن <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-uz/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-uz/strings.xml
new file mode 100644
index 0000000..aed34e6
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-uz/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Hech narsa topilmadi."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Tizimga oid jarayonlar"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Tizimga oid jarayonlarni berkitish"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Ruxsat berilgan"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ruxsat berilmagan"</string>
+ <string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> versiya"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-vi/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-vi/strings.xml
new file mode 100644
index 0000000..75700c7
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-vi/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Không có ứng dụng nào."</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Hiện hệ thống"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Ẩn hệ thống"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Được phép"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Không được phép"</string>
+ <string name="version_text" msgid="4001669804596458577">"phiên bản <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-zh-rCN/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..2c864cb
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-zh-rCN/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"没有应用。"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"显示系统进程"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"隐藏系统进程"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"已允许"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"不允许"</string>
+ <string name="version_text" msgid="4001669804596458577">"版本 <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-zh-rHK/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..667a10a
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-zh-rHK/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"沒有應用程式。"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"顯示系統程序"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"隱藏系統程序"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"允許"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"不允許"</string>
+ <string name="version_text" msgid="4001669804596458577">"版本 <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-zh-rTW/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..667a10a
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-zh-rTW/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"沒有應用程式。"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"顯示系統程序"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"隱藏系統程序"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"允許"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"不允許"</string>
+ <string name="version_text" msgid="4001669804596458577">"版本 <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-zu/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-zu/strings.xml
new file mode 100644
index 0000000..d3a614a
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/res/values-zu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="no_applications" msgid="5800789569715871963">"Awekho ama-app"</string>
+ <string name="menu_show_system" msgid="906304605807554788">"Bonisa isistimu"</string>
+ <string name="menu_hide_system" msgid="374571689914923020">"Fihla isistimu"</string>
+ <string name="app_permission_summary_allowed" msgid="6115213465364138103">"Kuvumelekile"</string>
+ <string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Akuvumelekile"</string>
+ <string name="version_text" msgid="4001669804596458577">"Uhlobo <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index a39a2b9..0234330 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> oor tot vol"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> oor tot vol"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Laaiproses is onderbreek"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Laai"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laai tans vinnig"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index d953678..29b188c 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"እስኪሞላ ድረስ <xliff:g id="TIME">%1$s</xliff:g> ይቀራል"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - እስኪሞላ ድረስ <xliff:g id="TIME">%2$s</xliff:g> ይቀራል"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ኃይል መሙላት ባለበት ቆሟል"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ያልታወቀ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ኃይል በመሙላት ላይ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ኃይል በፍጥነት በመሙላት ላይ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 3b00d26..28a3f18 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"يتبقّى <xliff:g id="TIME">%1$s</xliff:g> حتى اكتمال شحن البطارية."</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - يتبقّى <xliff:g id="TIME">%2$s</xliff:g> حتى اكتمال شحن البطارية."</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - تم إيقاف الشحن مؤقتًا"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"غير معروف"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"جارٍ الشحن"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"جارٍ الشحن سريعًا"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 0acd7ee6..fc54e04 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"সম্পূৰ্ণ হ’বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"সম্পূৰ্ণ হ’বলৈ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - চাৰ্জিং পজ কৰা হৈছে"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"অজ্ঞাত"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"চাৰ্জ কৰি থকা হৈছে"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্ৰুততাৰে চাৰ্জ হৈছে"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 33efb4fd..e2e294f 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Tam şarj edilənədək <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - tam şarj edilənədək <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Şarj durdurulub"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Naməlum"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Enerji doldurma"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Sürətlə doldurulur"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 108a136..479c9ca 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do kraja punjenja"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do kraja punjenja"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Punjenje je zaustavljeno"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Puni se"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo se puni"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 5a70202..b45996c 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Да поўнай зарадкі засталося <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – да поўнай зарадкі засталося: <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Зарадка прыпынена"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Невядома"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Зарадка"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хуткая зарадка"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 7e97dd3..ecb5208 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Оставащо време до пълно зареждане: <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: Зареждането е на пауза"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Зарежда се"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Зарежда се бързо"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 023be24..fda27ed 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>-এ ব্যাটারি পুরো চার্জ হয়ে যাবে"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এ ব্যাটারি পুরো চার্জ হয়ে যাবে"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - চার্জিং পজ করা হয়েছে"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"অজানা"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"চার্জ হচ্ছে"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্রুত চার্জ হচ্ছে"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 3cb4190..cae96e9 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do potpune napunjenosti"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do potpune napunjenosti"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Punjenje je pauzirano"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index efa29ee..51a4a02 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: la càrrega s\'ha posat en pausa"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconegut"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"S\'està carregant"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregant ràpidament"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 3736f93..a50e527 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do úplného nabití"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabití"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Nabíjení je pozastaveno"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Neznámé"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíjí se"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rychlé nabíjení"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 849604d..95e0130 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Fuldt opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – fuldt opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Opladningen er sat på pause"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Ukendt"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Oplader"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Oplader hurtigt"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index d736d59..12fce37 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Voll in <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – voll in <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladevorgang angehalten"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unbekannt"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Wird aufgeladen"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Schnelles Aufladen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index e76b933..f54d5d2 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> για πλήρη φόρτιση"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - Απομένουν <xliff:g id="TIME">%2$s</xliff:g> για πλήρη φόρτιση"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Η φόρτιση τέθηκε σε παύση"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Άγνωστο"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Φόρτιση"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ταχεία φόρτιση"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 09bc065..208dbfa 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging is paused"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 4714a0b..aac80ab 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -468,6 +468,7 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging is paused"</string>
+ <string name="power_charging_future_paused" msgid="6829683663982987290">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging to <xliff:g id="DOCK_DEFENDER_THRESHOLD">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 09bc065..208dbfa 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging is paused"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 09bc065..208dbfa 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging is paused"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index f82a757..bfd7e83 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -468,6 +468,7 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> left until full"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> left until full"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging is paused"</string>
+ <string name="power_charging_future_paused" msgid="6829683663982987290">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging to <xliff:g id="DOCK_DEFENDER_THRESHOLD">%2$s</xliff:g>"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 1a4e307..c11d6eb0 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -232,7 +232,7 @@
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver y usar los dispositivos disponibles, activa la depuración inalámbrica"</string>
<string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Vincular dispositivo mediante código QR"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Vincular dispositivos nuevos mediante escáner de código QR"</string>
- <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Vincular dispositivo con código de sincronización"</string>
+ <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Vincular dispositivo con un código de vinculación"</string>
<string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Vincular dispositivos nuevos mediante código de seis dígitos"</string>
<string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivos vinculados"</string>
<string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Conectado actualmente"</string>
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> para completar"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Se pausó la carga"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápidamente"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index fdf99e0..1ef351a 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> hasta la carga completa"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> hasta la carga completa"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carga en pausa"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carga rápida"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index bcd395c..e156011 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Täislaadimiseks kulub <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – täislaadimiseks kulub <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – laadimine on peatatud"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Tundmatu"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Laadimine"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Kiirlaadimine"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index cd1e7d1..e5f399c 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Kargatze-prozesua etenda dago"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Ezezaguna"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Kargatzen"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Bizkor kargatzen"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index d40f692..ccacfde 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> تا شارژ کامل باقی مانده است"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل باقی مانده است"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - شارژ موقتاً متوقف شده است"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ناشناس"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"در حال شارژ شدن"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"درحال شارژ شدن سریع"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 0d6036a..101dc67 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> kunnes täynnä"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kunnes täynnä"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Lataus on keskeytetty"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Tuntematon"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Ladataan"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Nopea lataus"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index f276236..ff58a51 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la recharge complète"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la recharge complète)"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - La recharge est interrompue"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Charge en cours…"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Recharge rapide"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 7c4afa7..f9725f6 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Chargée à 100 %% dans <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - chargée à 100 %% dans <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – La recharge est en pause"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Batterie en charge"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charge rapide"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 95d5e21..3ceb99c 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> para completar a carga"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> para completar a carga)"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: a carga está en pausa"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Descoñecido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rapidamente"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index e8acbd5..1821546 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"પૂર્ણ ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી છે"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - પૂર્ણ ચાર્જ થવામાં <xliff:g id="TIME">%2$s</xliff:g> બાકી છે"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જિંગ થોભાવવામાં આવ્યું છે"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"અજાણ્યું"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ચાર્જ થઈ રહ્યું છે"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ઝડપથી ચાર્જ થાય છે"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index b1ef50a..4b899bb 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> में बैटरी पूरी चार्ज हो जाएगी"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में बैटरी पूरी चार्ज हो जाएगी"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्जिंग को रोका गया है"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हो रही है"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"तेज़ चार्ज हो रही है"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 06166f6..46c8b90 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do napunjenosti"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do napunjenosti"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je pauzirano"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index af5a114..d74490f 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> a teljes töltöttségig"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a teljes töltöttségig"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – A töltés szünetel"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Ismeretlen"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Töltés"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Gyorstöltés"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 61c3e7e..c26f94f 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> մինչև լրիվ լիցքավորումը"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լրիվ լիցքավորումը"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Լիցքավորումը դադարեցված է"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Անհայտ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Լիցքավորում"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Արագ լիցքավորում"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index d7f5857..203485f 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> lagi sampai penuh"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi sampai penuh"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengisian daya dijeda"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Mengisi daya"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengisi daya cepat"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 4862904..9185877 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> fram að fullri hleðslu"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> fram að fullri hleðslu"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Hlé var gert á hleðslu"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Óþekkt"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Í hleðslu"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hröð hleðsla"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 9e5a224..0cd9e1e 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> alla ricarica completa"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla ricarica completa"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ricarica in pausa"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Sconosciuta"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"In carica"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ricarica veloce"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index c6afad9..6293105 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"הזמן הנותר לטעינה מלאה: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – הזמן הנותר לטעינה מלאה: <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – הטעינה הושהתה"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"לא ידוע"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"בטעינה"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"הסוללה נטענת מהר"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 43fe178..9a9d6ea 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"完了まであと <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - 完了まであと <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電は一時停止中"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"急速充電中"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index c498b61..2fa2d80 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> — სრულ დატენვამდე დარჩენილია <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - დატენვა ᲨეᲩერებულია"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"უცნობი"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"იტენება"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"სწრაფად იტენება"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 314683b..a332004 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Толық зарядталғанға дейін <xliff:g id="TIME">%1$s</xliff:g> қалды."</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – толық зарядталғанға дейін <xliff:g id="TIME">%2$s</xliff:g> қалды."</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядтау кідіртілді."</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Белгісіз"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Зарядталуда"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Жылдам зарядталуда"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 00668fe..2d78295 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើបពេញ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - នៅសល់ <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើបពេញ"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ការសាកថ្មត្រូវបានផ្អាក"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"មិនស្គាល់"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"កំពុងសាកថ្ម"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index ebf742b..5db4b16 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> - ಸಮಯದಲ್ಲಿ ಪೂರ್ತಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯದಲ್ಲಿ ಪೂರ್ತಿ ಚಾರ್ಜ್ ಆಗುತ್ತದೆ"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ಅಪರಿಚಿತ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ವೇಗದ ಚಾರ್ಜಿಂಗ್"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 21c8091..30ab26c 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> 후 충전 완료"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> 후 충전 완료"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 일시중지됨"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"알 수 없음"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"충전 중"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"고속 충전 중"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 076f317a..baacfd7 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> кийин толук кубатталат"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталат"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Кубаттоо тындырылды"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Белгисиз"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Кубатталууда"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ыкчам кубатталууда"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 9ebe67a..36755f7 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ຍັງເຫຼືອອີກ <xliff:g id="TIME">%1$s</xliff:g> ຈຶ່ງຈະສາກເຕັມ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"ຍັງເຫຼືອອີກ <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈຶ່ງຈະສາກເຕັມ"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ການສາກໄຟຖືກຢຸດໄວ້ຊົ່ວຄາວ"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ບໍ່ຮູ້ຈັກ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ກຳລັງສາກໄຟ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ກຳລັງສາກໄຟດ່ວນ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index fcea778..50652ea 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Liko <xliff:g id="TIME">%1$s</xliff:g>, kol bus visiškai įkrauta"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – liko <xliff:g id="TIME">%2$s</xliff:g>, kol bus visiškai įkrauta"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – įkrovimas pristabdytas"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nežinomas"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Kraunasi..."</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Greitai įkraunama"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index c280737..c199fea 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> līdz pilnai uzlādei"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> — uzlāde ir pārtraukta"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nezināms"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Uzlāde"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Notiek ātrā uzlāde"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index f849900..957f68b 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до полна батерија"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> до полна батерија"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Полнењето е паузирано"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Се полни"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо полнење"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index cc15e03..1cc92ca 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"പൂർണ്ണമാകാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമാകാൻ <xliff:g id="TIME">%2$s</xliff:g> ശേഷിക്കുന്നു"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ചാർജിംഗ് താൽക്കാലികമായി നിർത്തി"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"അജ്ഞാതം"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ചാർജ് ചെയ്യുന്നു"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"അതിവേഗ ചാർജിംഗ്"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 3701a30..a107c70 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Дүүрэх хүртэл <xliff:g id="TIME">%1$s</xliff:g> үлдсэн"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - дүүрэх хүртэл <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Цэнэглэхийг түр зогсоосон"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Тодорхойгүй"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Цэнэглэж байна"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хурдан цэнэглэж байна"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 3fffc1a..d5c83a8 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"पूर्ण चार्ज होण्यासाठी <xliff:g id="TIME">%1$s</xliff:g> शिल्लक आहेत"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूर्ण चार्ज होण्यासाठी <xliff:g id="TIME">%2$s</xliff:g> शिल्लक आहे"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज करणे थांबवले आहे"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज होत आहे"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"वेगाने चार्ज होत आहे"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 79553c0..ae8be8e 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> lagi sebelum penuh"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi sebelum penuh"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengecasan dijeda"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Mengecas"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengecas dgn cepat"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index fc38626..f16cdca 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> လိုသည်"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"အားပြည့်ရန် <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> လိုသည်"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားသွင်းခြင်းကို ခဏရပ်ထားသည်"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"မသိ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"အားသွင်းနေပါသည်"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"အမြန် အားသွင်းနေသည်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 59a2517..f7a10a6 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Fulladet om <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fulladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ladingen er satt på pause"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Ukjent"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Lader"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Lader raskt"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 777c897..a966f15 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"पूरा चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> लाग्ने छ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - पूरा चार्ज हुन <xliff:g id="TIME">%2$s</xliff:g> लाग्ने छ"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - चार्ज गर्ने प्रक्रिया रोकिएको छ"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हुँदै छ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"द्रुत गतिमा चार्ज गरिँदै छ"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index d30a21f..c5406ee 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Vol over <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - vol over <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Opladen is onderbroken"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Opladen"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Snel opladen"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 0120768..37cc25e 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ପୂର୍ଣ୍ଣ ହେବାକୁ ଆଉ <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - ପୂର୍ଣ୍ଣ ହେବାକୁ ଆଉ <xliff:g id="TIME">%2$s</xliff:g> ବାକି ଅଛି"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ଚାର୍ଜିଂକୁ ବିରତ କରାଯାଇଛି"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ଅଜ୍ଞାତ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ଚାର୍ଜ ହେଉଛି"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 1481767..767cbc5 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"ਬੈਟਰੀ ਪੂਰੀ ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਬੈਟਰੀ ਪੂਰੀ ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਚਾਰਜਿੰਗ ਨੂੰ ਰੋਕਿਆ ਗਿਆ ਹੈ"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ਅਗਿਆਤ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 83f8e49..48bc82e 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do pełnego naładowania"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do pełnego naładowania"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – ładowanie zostało wstrzymane"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Nieznane"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Ładowanie"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Szybkie ładowanie"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index d9a7c69..68a1c49 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até a conclusão"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a conclusão"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: o carregamento está pausado"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index c24589c..87bab50 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até à carga máxima"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até à carga máxima"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – O carregamento está pausado"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"A carregar"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregamento rápido"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index d9a7c69..68a1c49 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> até a conclusão"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a conclusão"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: o carregamento está pausado"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 04c58ae..f81ef4c 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> până la finalizare"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> până la finalizare"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Încărcarea este întreruptă"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Necunoscut"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Se încarcă"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Se încarcă rapid"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 704d848..4dcee13 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: зарядка приостановлена"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Идет зарядка"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Быстрая зарядка"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index d67060e..17c59ea 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"සම්පූර්ණ වීමට <xliff:g id="TIME">%1$s</xliff:g>ක් ඉතිරියි"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - සම්පූර්ණ වීමට <xliff:g id="TIME">%2$s</xliff:g>ක් ඉතිරියි"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය විරාම කර ඇත"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"නොදනී"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ආරෝපණය වෙමින්"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ශීඝ්ර ආරෝපණය"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 1982893..d9ce6cf 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> do úplného nabitia"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Nabíjanie je pozastavené"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Neznáme"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíja sa"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rýchle nabíjanie"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 262ecfd..8f9b059 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Še <xliff:g id="TIME">%1$s</xliff:g> do napolnjenosti"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – še <xliff:g id="TIME">%2$s</xliff:g> do napolnjenosti"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Polnjenje je začasno zaustavljeno"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Neznano"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Polnjenje"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hitro polnjenje"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index d0f1f7c..d467eea 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> derisa të mbushet"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të mbushet"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Karikimi është vendosur në pauzë"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"I panjohur"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Po karikohet"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Karikim i shpejtë"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index b102d3a..9cc43d9 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до краја пуњења"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до краја пуњења"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Пуњење је заустављено"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Пуни се"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо се пуни"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 17a06c2..89deafa 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> kvar tills fulladdat"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> kvar tills fulladdat"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Laddningen har pausats"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Okänd"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Laddar"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laddas snabbt"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 72a3751..1fa5edd 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Zimesalia <xliff:g id="TIME">%1$s</xliff:g> ijae chaji"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> zimesalia ijae chaji"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Imesitisha kuchaji"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Haijulikani"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Inachaji"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Inachaji kwa kasi"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 8714958..1b7b643 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"முழுவதும் சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழுவதும் சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - சார்ஜ் ஏறுவது இடைநிறுத்தப்பட்டுள்ளது"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"அறியப்படாத"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"சார்ஜ் ஆகிறது"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"வேகமாக சார்ஜாகிறது"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 5e00b1d..27e9dbd 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>లో పూర్తిగా ఛార్జ్ అవుతుంది"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జింగ్ పాజ్ చేయబడింది"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"తెలియదు"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ఛార్జ్ అవుతోంది"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"వేగవంతమైన ఛార్జింగ్"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index f386e5d..6b9c077 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"อีก <xliff:g id="TIME">%1$s</xliff:g>จึงจะเต็ม"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - อีก <xliff:g id="TIME">%2$s</xliff:g> จึงจะเต็ม"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - การชาร์จหยุดชั่วคราว"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"ไม่ทราบ"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"กำลังชาร์จ"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"กำลังชาร์จอย่างเร็ว"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index db27382..fddc1d0 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> na lang bago mapuno"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> na lang bago mapuno"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Naka-pause ang pag-charge"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Hindi Kilala"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Nagcha-charge"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mabilis na charge"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 8f4bae4..31dcedb8 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Tamamen şarj olmasına <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - Tamamen şarj olmasına <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g>: Şarj işlemi duraklatıldı"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Bilinmiyor"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Şarj oluyor"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hızlı şarj oluyor"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index a0c68c1..2fdc227 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> до повного заряду"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Заряджання призупинено"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Невідомо"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Заряджається"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Швидке заряджання"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index d0a1204..82dbdb3 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"مکمل چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی ہے"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"مکمل چارج ہونے میں <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - چارجنگ موقوف ہے"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"نامعلوم"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"چارج ہو رہا ہے"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"تیزی سے چارج ہو رہا ہے"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index efb5eb9..ab997b6 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"Toʻlishiga <xliff:g id="TIME">%1$s</xliff:g> qoldi"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – Toʻlishiga <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Quvvatlash pauza qilindi"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Noma’lum"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Quvvat olmoqda"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Tezkor quvvat olmoqda"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index f7f4c0e..44c820a5 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -268,7 +268,7 @@
<string name="mock_location_app_set" msgid="4706722469342913843">"Ứng dụng vị trí mô phỏng: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"Mạng"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"Chứng nhận hiển thị không dây"</string>
- <string name="wifi_verbose_logging" msgid="1785910450009679371">"Bật ghi nhật ký chi tiết Wi‑Fi"</string>
+ <string name="wifi_verbose_logging" msgid="1785910450009679371">"Bật tính năng ghi nhật ký chi tiết Wi‑Fi"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"Hạn chế quét tìm Wi-Fi"</string>
<string name="wifi_non_persistent_mac_randomization" msgid="7482769677894247316">"Tạo địa chỉ MAC ngẫu nhiên, không cố định mỗi khi kết nối Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"Dữ liệu di động luôn hoạt động"</string>
@@ -280,7 +280,7 @@
<string name="bluetooth_select_avrcp_version_dialog_title" msgid="7846922290083709633">"Chọn phiên bản Bluetooth AVRCP"</string>
<string name="bluetooth_select_map_version_string" msgid="526308145174175327">"Phiên bản Bluetooth MAP"</string>
<string name="bluetooth_select_map_version_dialog_title" msgid="7085934373987428460">"Chọn phiên bản Bluetooth MAP"</string>
- <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Codec âm thanh Bluetooth"</string>
+ <string name="bluetooth_select_a2dp_codec_type" msgid="952001408455456494">"Bộ mã hoá và giải mã âm thanh qua Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="7510542404227225545">"Kích hoạt chế độ chọn codec\nâm thanh Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate" msgid="1638623076480928191">"Tốc độ lấy mẫu âm thanh Bluetooth"</string>
<string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5876305103137067798">"Kích hoạt chế độ chọn codec\nâm thanh Bluetooth: Tần số lấy mẫu"</string>
@@ -374,7 +374,7 @@
<string name="window_blurs" msgid="6831008984828425106">"Cho phép làm mờ cửa sổ"</string>
<string name="force_msaa" msgid="4081288296137775550">"Bắt buộc 4x MSAA"</string>
<string name="force_msaa_summary" msgid="9070437493586769500">"Bật 4x MSAA trong ứng dụng OpenGL ES 2.0"</string>
- <string name="show_non_rect_clip" msgid="7499758654867881817">"Gỡ lỗi hoạt động của clip không phải là hình chữ nhật"</string>
+ <string name="show_non_rect_clip" msgid="7499758654867881817">"Gỡ lỗi hoạt động của đoạn không phải hình chữ nhật"</string>
<string name="track_frame_time" msgid="522674651937771106">"Kết xuất HWUI cấu hình"</string>
<string name="enable_gpu_debug_layers" msgid="4986675516188740397">"Bật lớp gỡ lỗi GPU"</string>
<string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"Cho phép tải lớp gỡ lỗi GPU cho ứng dụng gỡ lỗi"</string>
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> nữa là pin đầy"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> nữa là pin đầy"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> – Đã tạm dừng sạc"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Không xác định"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Đang sạc"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Đang sạc nhanh"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index f536bb9..eae1c39 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"还需<xliff:g id="TIME">%1$s</xliff:g>充满"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - 还需<xliff:g id="TIME">%2$s</xliff:g>充满"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充电已暂停"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"正在充电"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充电"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 357302b..4371bb3 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>後充滿電"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充滿電"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - 已暫停充電"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 4ae28304..d76a4a4 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g>後充飽"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - 已暫停充電"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index c113dc8..4dc7651 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -468,6 +468,8 @@
<string name="power_remaining_charging_duration_only" msgid="8085099012811384899">"<xliff:g id="TIME">%1$s</xliff:g> okusele kuze kugcwale"</string>
<string name="power_charging_duration" msgid="6127154952524919719">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> okusele kuze kugcwale"</string>
<string name="power_charging_limited" msgid="6971664137170239141">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ukushaja kumisiwe okwesikhashana"</string>
+ <!-- no translation found for power_charging_future_paused (6829683663982987290) -->
+ <skip />
<string name="battery_info_status_unknown" msgid="268625384868401114">"Akwaziwa"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"Iyashaja"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ishaja ngokushesha"</string>
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index cf7c7c5..46876b4 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -336,6 +336,7 @@
VALIDATORS.put(Global.Wearable.COOLDOWN_MODE_ON, BOOLEAN_VALIDATOR);
VALIDATORS.put(
Global.Wearable.GESTURE_TOUCH_AND_HOLD_WATCH_FACE_ENABLED, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Global.Wearable.RSB_WAKE_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.Wearable.SCREEN_UNLOCK_SOUND_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.Wearable.CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.Wearable.BEDTIME_MODE, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 24c1435..aa194b9 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -659,7 +659,8 @@
Settings.Global.Wearable.SCREEN_UNLOCK_SOUND_ENABLED,
Settings.Global.Wearable.BEDTIME_MODE,
Settings.Global.Wearable.BEDTIME_HARD_MODE,
- Settings.Global.Wearable.EARLY_UPDATES_STATUS);
+ Settings.Global.Wearable.EARLY_UPDATES_STATUS,
+ Settings.Global.Wearable.RSB_WAKE_ENABLED);
private static final Set<String> BACKUP_DENY_LIST_SECURE_SETTINGS =
newHashSet(
diff --git a/packages/SystemUI/animation/Android.bp b/packages/SystemUI/animation/Android.bp
index 5df79e1..17ad55f 100644
--- a/packages/SystemUI/animation/Android.bp
+++ b/packages/SystemUI/animation/Android.bp
@@ -37,6 +37,8 @@
static_libs: [
"PluginCoreLib",
"androidx.core_core-animation-nodeps",
+ "androidx.core_core-ktx",
+ "androidx.annotation_annotation",
],
manifest: "AndroidManifest.xml",
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index fdfad2b..54aa351 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -75,7 +75,7 @@
*/
interface Controller {
/** The [ViewRootImpl] of this controller. */
- val viewRoot: ViewRootImpl
+ val viewRoot: ViewRootImpl?
/**
* The identity object of the source animated by this controller. This animator will ensure
@@ -807,15 +807,17 @@
* inversely, removed from the overlay when the source is moved back to its original position).
*/
private fun synchronizeNextDraw(then: () -> Unit) {
- if (forceDisableSynchronization) {
- // Don't synchronize when inside an automated test.
+ val controllerRootView = controller.viewRoot?.view
+ if (forceDisableSynchronization || controllerRootView == null) {
+ // Don't synchronize when inside an automated test or if the controller root view is
+ // detached.
then()
return
}
- ViewRootSync.synchronizeNextDraw(controller.viewRoot.view, decorView, then)
+ ViewRootSync.synchronizeNextDraw(controllerRootView, decorView, then)
decorView.invalidate()
- controller.viewRoot.view.invalidate()
+ controllerRootView.invalidate()
}
private fun findFirstViewGroupWithBackground(view: View): ViewGroup? {
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 43bfa74..0e2d23b 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
@@ -195,8 +195,16 @@
val out = ArrayList<RemoteAnimationTarget>()
for (i in info.changes.indices) {
val change = info.changes[i]
- val changeIsWallpaper = change.flags and TransitionInfo.FLAG_IS_WALLPAPER != 0
- if (wallpapers != changeIsWallpaper) continue
+ if (change.hasFlags(TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)) {
+ // For embedded container, when the parent Task is also in the transition, we
+ // should only animate the parent Task.
+ if (change.parent != null) continue
+ // For embedded container without parent, we should only animate if it fills
+ // the Task. Otherwise we may animate only partial of the Task.
+ if (!change.hasFlags(TransitionInfo.FLAG_FILLS_TASK)) continue
+ }
+ // Check if it is wallpaper
+ if (wallpapers != change.hasFlags(TransitionInfo.FLAG_IS_WALLPAPER)) continue
out.add(createTarget(change, info.changes.size - i, info, t))
if (leashMap != null) {
leashMap[change.leash] = out[out.size - 1].leash
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt
index ecee598..964ef8c 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt
@@ -28,7 +28,7 @@
private val source: View,
override val cuj: DialogCuj?,
) : DialogLaunchAnimator.Controller {
- override val viewRoot: ViewRootImpl
+ override val viewRoot: ViewRootImpl?
get() = source.viewRootImpl
override val sourceIdentity: Any = source
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleController.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/MultiRippleController.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleController.kt
rename to packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/MultiRippleController.kt
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt
rename to packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt
index f558fee..b8dc223 100644
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/MultiRippleView.kt
@@ -22,6 +22,7 @@
import android.util.AttributeSet
import android.util.Log
import android.view.View
+import androidx.annotation.VisibleForTesting
/**
* A view that allows multiple ripples to play.
@@ -30,7 +31,8 @@
*/
class MultiRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
- internal val ripples = ArrayList<RippleAnimation>()
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ val ripples = ArrayList<RippleAnimation>()
private val listeners = ArrayList<RipplesFinishedListener>()
private val ripplePaint = Paint()
private var isWarningLogged = false
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
rename to packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
index b2f8994..0e3d41c 100644
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
@@ -19,11 +19,13 @@
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
+import androidx.annotation.VisibleForTesting
import androidx.core.graphics.ColorUtils
/** A single ripple animation. */
class RippleAnimation(private val config: RippleAnimationConfig) {
- internal val rippleShader: RippleShader = RippleShader(config.rippleShape)
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ val rippleShader: RippleShader = RippleShader(config.rippleShape)
private val animator: ValueAnimator = ValueAnimator.ofFloat(0f, 1f)
init {
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
rename to packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
rename to packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
index a950d34..f55fb97 100644
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
@@ -32,7 +32,7 @@
*
* Modeled after frameworks/base/graphics/java/android/graphics/drawable/RippleShader.java.
*/
-class RippleShader internal constructor(rippleShape: RippleShape = RippleShape.CIRCLE) :
+class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
RuntimeShader(buildShader(rippleShape)) {
/** Shapes that the [RippleShader] supports. */
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
rename to packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
rename to packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt
rename to packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/ShaderUtilLibrary.kt
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
rename to packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt
rename to packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
rename to packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
diff --git a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
rename to packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
index 8649d59..68712c6 100644
--- a/packages/SystemUI/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
@@ -68,7 +68,7 @@
canvas.drawPaint(paint)
}
- internal fun play(config: TurbulenceNoiseAnimationConfig) {
+ fun play(config: TurbulenceNoiseAnimationConfig) {
if (isPlaying) {
return // Ignore if the animation is playing.
}
diff --git a/packages/SystemUI/compose/core/src/com/android/systemui/compose/animation/ExpandableController.kt b/packages/SystemUI/compose/core/src/com/android/systemui/compose/animation/ExpandableController.kt
index 50c3d7e..d6db574 100644
--- a/packages/SystemUI/compose/core/src/com/android/systemui/compose/animation/ExpandableController.kt
+++ b/packages/SystemUI/compose/core/src/com/android/systemui/compose/animation/ExpandableController.kt
@@ -262,7 +262,7 @@
private fun dialogController(cuj: DialogCuj?): DialogLaunchAnimator.Controller {
return object : DialogLaunchAnimator.Controller {
- override val viewRoot: ViewRootImpl = composeViewRoot.viewRootImpl
+ override val viewRoot: ViewRootImpl? = composeViewRoot.viewRootImpl
override val sourceIdentity: Any = this@ExpandableControllerImpl
override val cuj: DialogCuj? = cuj
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 8698844..e1f2174 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
@@ -20,7 +20,6 @@
import android.icu.text.NumberFormat
import android.util.TypedValue
import android.view.LayoutInflater
-import android.view.View
import android.widget.FrameLayout
import androidx.annotation.VisibleForTesting
import com.android.systemui.customization.R
@@ -152,15 +151,9 @@
view: AnimatableClockView,
) : DefaultClockFaceController(view) {
override fun recomputePadding(targetRegion: Rect?) {
- // We center the view within the targetRegion instead of within the parent
- // view by computing the difference and adding that to the padding.
- val parent = view.parent
- val yDiff =
- if (targetRegion != null && parent is View && parent.isLaidOut())
- targetRegion.centerY() - parent.height / 2f
- else 0f
+ // Ignore Target Region until top padding fixed in aod
val lp = view.getLayoutParams() as FrameLayout.LayoutParams
- lp.topMargin = (-0.5f * view.bottom + yDiff).toInt()
+ lp.topMargin = (-0.5f * view.bottom).toInt()
view.setLayoutParams(lp)
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/data/content/FakeKeyguardQuickAffordanceProviderClient.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/data/content/FakeKeyguardQuickAffordanceProviderClient.kt
index f490c54..cb1a5f9 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/data/content/FakeKeyguardQuickAffordanceProviderClient.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/data/content/FakeKeyguardQuickAffordanceProviderClient.kt
@@ -42,17 +42,17 @@
KeyguardQuickAffordanceProviderClient.Affordance(
id = AFFORDANCE_1,
name = AFFORDANCE_1,
- iconResourceId = 0,
+ iconResourceId = 1,
),
KeyguardQuickAffordanceProviderClient.Affordance(
id = AFFORDANCE_2,
name = AFFORDANCE_2,
- iconResourceId = 0,
+ iconResourceId = 2,
),
KeyguardQuickAffordanceProviderClient.Affordance(
id = AFFORDANCE_3,
name = AFFORDANCE_3,
- iconResourceId = 0,
+ iconResourceId = 3,
),
),
flags: List<KeyguardQuickAffordanceProviderClient.Flag> =
@@ -131,7 +131,12 @@
}
override suspend fun getAffordanceIcon(iconResourceId: Int, tintColor: Int): Drawable {
- return BitmapDrawable()
+ return when (iconResourceId) {
+ 1 -> ICON_1
+ 2 -> ICON_2
+ 3 -> ICON_3
+ else -> BitmapDrawable()
+ }
}
fun setFlag(
@@ -186,5 +191,8 @@
const val AFFORDANCE_1 = "affordance_1"
const val AFFORDANCE_2 = "affordance_2"
const val AFFORDANCE_3 = "affordance_3"
+ val ICON_1 = BitmapDrawable()
+ val ICON_2 = BitmapDrawable()
+ val ICON_3 = BitmapDrawable()
}
}
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
index a156aab..7290e7e 100644
--- a/packages/SystemUI/ktfmt_includes.txt
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -753,7 +753,7 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 6976786..e598afe 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -26,14 +26,11 @@
-keep class ** extends androidx.preference.PreferenceFragment
-keep class com.android.systemui.tuner.*
-# The plugins and animation subpackages both act as shared libraries that might be referenced in
+# The plugins subpackage acts as a shared library that might be referenced in
# dynamically-loaded plugin APKs.
-keep class com.android.systemui.plugins.** {
*;
}
--keep class !com.android.systemui.animation.R$**,com.android.systemui.animation.** {
- *;
-}
-keep class com.android.systemui.fragments.FragmentService$FragmentCreator {
*;
}
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index b49afee..218c5cc 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -35,6 +35,7 @@
android:visibility="invisible" />
<FrameLayout
android:id="@+id/lockscreen_clock_view_large"
+ android:layout_marginTop="@dimen/keyguard_large_clock_top_margin"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index 579824a..57e5f8a 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -74,7 +74,7 @@
<string name="kg_password_pin_failed" msgid="5136259126330604009">"Bewerking met pincode voor simkaart is mislukt."</string>
<string name="kg_password_puk_failed" msgid="6778867411556937118">"Bewerking met pukcode voor simkaart is mislukt."</string>
<string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Invoermethode wijzigen"</string>
- <string name="airplane_mode" msgid="2528005343938497866">"Vliegtuigmodus"</string>
+ <string name="airplane_mode" msgid="2528005343938497866">"Vliegtuigmodus"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Patroon vereist nadat het apparaat opnieuw is opgestart"</string>
<string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Pincode vereist nadat het apparaat opnieuw is opgestart"</string>
<string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Wachtwoord vereist nadat het apparaat opnieuw is opgestart"</string>
diff --git a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
index 79ba7ead..aa655e6 100644
--- a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
+++ b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
@@ -41,7 +41,7 @@
android:layout_width="@dimen/qs_media_app_icon_size"
android:layout_height="@dimen/qs_media_app_icon_size"
android:layout_marginStart="@dimen/qs_media_padding"
- android:layout_marginTop="@dimen/qs_media_padding"
+ android:layout_marginTop="@dimen/qs_media_rec_icon_top_margin"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
diff --git a/packages/SystemUI/res/layout/status_bar_no_notifications.xml b/packages/SystemUI/res/layout/status_bar_no_notifications.xml
index a2abdb2..856ba92 100644
--- a/packages/SystemUI/res/layout/status_bar_no_notifications.xml
+++ b/packages/SystemUI/res/layout/status_bar_no_notifications.xml
@@ -21,12 +21,29 @@
android:layout_height="wrap_content"
android:visibility="gone"
>
- <TextView
- android:id="@+id/no_notifications"
+ <LinearLayout android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:minHeight="64dp"
- android:textAppearance="?android:attr/textAppearanceButton"
+ android:layout_gravity="center"
android:gravity="center"
- android:text="@string/empty_shade_text"/>
+ >
+ <TextView
+ android:id="@+id/no_notifications"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="64dp"
+ android:gravity="center"
+ android:textAppearance="?android:attr/textAppearanceButton"
+ android:text="@string/empty_shade_text"/>
+ <TextView
+ android:id="@+id/no_notifications_footer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:gravity="center"
+ android:drawablePadding="8dp"
+ android:visibility="gone"
+ android:textAppearance="?android:attr/textAppearanceButton"
+ android:text="@string/unlock_to_see_notif_text"/>
+ </LinearLayout>
</com.android.systemui.statusbar.EmptyShadeView>
diff --git a/packages/SystemUI/res/values-sw720dp-land/dimens.xml b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
index 868c003..3fc59e3 100644
--- a/packages/SystemUI/res/values-sw720dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
@@ -35,6 +35,11 @@
not appear immediately after user swipes to the side -->
<dimen name="qs_tiles_page_horizontal_margin">20dp</dimen>
+ <!-- Size of Smartspace media recommendations cards in the QSPanel carousel -->
+ <dimen name="qs_media_rec_icon_top_margin">27dp</dimen>
+ <dimen name="qs_media_rec_album_size">152dp</dimen>
+ <dimen name="qs_media_rec_album_side_margin">16dp</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/colors.xml b/packages/SystemUI/res/values/colors.xml
index 8ee39dd..70d53c7 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -133,6 +133,9 @@
<color name="biometric_dialog_accent">@color/material_dynamic_primary40</color>
<color name="biometric_dialog_error">#ffd93025</color> <!-- red 600 -->
+ <!-- SFPS colors -->
+ <color name="sfps_chevron_fill">@color/material_dynamic_primary90</color>
+
<!-- UDFPS colors -->
<color name="udfps_enroll_icon">#699FF3</color>
<color name="udfps_moving_target_fill">#C2D7F7</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index d04e2b1..dc7e4e4 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -403,6 +403,8 @@
(quick_qs_offset_height (60dp) - ongoing_appops_chip_height (24dp) ) / 2 -->
<dimen name="notifications_top_padding_split_shade">18dp</dimen>
+ <dimen name="notifications_unseen_footer_icon_size">16dp</dimen>
+
<!-- Height of the status bar header bar when on Keyguard -->
<dimen name="status_bar_header_height_keyguard">40dp</dimen>
@@ -1055,6 +1057,7 @@
<dimen name="qs_media_session_collapsed_guideline">144dp</dimen>
<!-- Size of Smartspace media recommendations cards in the QSPanel carousel -->
+ <dimen name="qs_media_rec_icon_top_margin">16dp</dimen>
<dimen name="qs_media_rec_album_size">88dp</dimen>
<dimen name="qs_media_rec_album_side_margin">16dp</dimen>
<dimen name="qs_media_rec_album_bottom_margin">8dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7597c62..a4e9983 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1105,6 +1105,12 @@
<!-- Text which is shown in the notification shade when there are no notifications. [CHAR LIMIT=30] -->
<string name="empty_shade_text">No notifications</string>
+ <!-- Text which is shown in the expanded notification shade when there are currently no notifications visible that the user hasn't already seen. [CHAR LIMIT=30] -->
+ <string name="no_unseen_notif_text">No new notifications</string>
+
+ <!-- Text which is shown in the locked notification shade when there are currently no notifications, but if the user were to unlock, notifications would appear. [CHAR LIMIT=40] -->
+ <string name="unlock_to_see_notif_text">Unlock to see older notifications</string>
+
<!-- Disclosure at the bottom of Quick Settings that indicates that parental controls are enabled. [CHAR LIMIT=100] -->
<string name="quick_settings_disclosure_parental_controls">This device is managed by your parent</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
index 4a41b3f..5bb9367 100644
--- a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+++ b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
@@ -48,11 +48,13 @@
import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_OCCLUSION_CHANGED
import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_RESET
import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_VISIBILITY_CHANGED
+import com.android.keyguard.InternalFaceAuthReasons.NON_STRONG_BIOMETRIC_ALLOWED_CHANGED
import com.android.keyguard.InternalFaceAuthReasons.OCCLUDING_APP_REQUESTED
import com.android.keyguard.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN
import com.android.keyguard.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN_OR_WILL_BE_SHOWN
import com.android.keyguard.InternalFaceAuthReasons.RETRY_AFTER_HW_UNAVAILABLE
import com.android.keyguard.InternalFaceAuthReasons.STARTED_WAKING_UP
+import com.android.keyguard.InternalFaceAuthReasons.STRONG_AUTH_ALLOWED_CHANGED
import com.android.keyguard.InternalFaceAuthReasons.TRUST_DISABLED
import com.android.keyguard.InternalFaceAuthReasons.TRUST_ENABLED
import com.android.keyguard.InternalFaceAuthReasons.USER_SWITCHING
@@ -121,6 +123,9 @@
const val FACE_AUTHENTICATED = "Face auth started/stopped because face is authenticated"
const val BIOMETRIC_ENABLED =
"Face auth started/stopped because biometric is enabled on keyguard"
+ const val STRONG_AUTH_ALLOWED_CHANGED = "Face auth stopped because strong auth allowed changed"
+ const val NON_STRONG_BIOMETRIC_ALLOWED_CHANGED =
+ "Face auth stopped because non strong biometric allowed changed"
}
/**
@@ -204,7 +209,11 @@
@UiEvent(doc = FACE_AUTHENTICATED)
FACE_AUTH_UPDATED_ON_FACE_AUTHENTICATED(1187, FACE_AUTHENTICATED),
@UiEvent(doc = BIOMETRIC_ENABLED)
- FACE_AUTH_UPDATED_BIOMETRIC_ENABLED_ON_KEYGUARD(1188, BIOMETRIC_ENABLED);
+ FACE_AUTH_UPDATED_BIOMETRIC_ENABLED_ON_KEYGUARD(1188, BIOMETRIC_ENABLED),
+ @UiEvent(doc = STRONG_AUTH_ALLOWED_CHANGED)
+ FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED(1255, STRONG_AUTH_ALLOWED_CHANGED),
+ @UiEvent(doc = NON_STRONG_BIOMETRIC_ALLOWED_CHANGED)
+ FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED(1256, NON_STRONG_BIOMETRIC_ALLOWED_CHANGED);
override fun getId(): Int = this.id
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
index e6283b8..52ca166 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
@@ -53,17 +53,17 @@
val biometricSettingEnabledForUser: Boolean,
val bouncerFullyShown: Boolean,
val faceAndFpNotAuthenticated: Boolean,
+ val faceAuthAllowed: Boolean,
val faceDisabled: Boolean,
val faceLockedOut: Boolean,
- val fpLockedOut: Boolean,
val goingToSleep: Boolean,
val keyguardAwake: Boolean,
val keyguardGoingAway: Boolean,
val listeningForFaceAssistant: Boolean,
val occludingAppRequestingFaceAuth: Boolean,
val primaryUser: Boolean,
- val scanningAllowedByStrongAuth: Boolean,
val secureCameraLaunched: Boolean,
+ val supportsDetect: Boolean,
val switchingUser: Boolean,
val udfpsBouncerShowing: Boolean,
val udfpsFingerDown: Boolean,
@@ -79,9 +79,8 @@
// keep sorted
val awakeKeyguard: Boolean,
val authInterruptActive: Boolean,
- val encryptedOrTimedOut: Boolean,
- val fpLockout: Boolean,
- val lockDown: Boolean,
+ val fpLockedOut: Boolean,
+ val primaryAuthRequired: Boolean,
val switchingUser: Boolean,
val triggerActiveUnlockForAssistant: Boolean,
val userCanDismissLockScreen: Boolean
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 64fa15e..51ade29 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -34,9 +34,9 @@
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
-import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.keyguard.FaceAuthReasonKt.apiRequestReasonToUiEvent;
+import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_DREAM_STARTED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_FACE_CANCEL_NOT_RECEIVED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_FINISHED_GOING_TO_SLEEP;
@@ -65,6 +65,7 @@
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_ON_KEYGUARD_INIT;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_STARTED_WAKING_UP;
+import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_USER_SWITCHING;
import static com.android.systemui.DejankUtils.whitelistIpcs;
@@ -170,7 +171,6 @@
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.Executor;
-import java.util.function.Consumer;
import java.util.stream.Collectors;
import javax.inject.Inject;
@@ -939,12 +939,16 @@
setFingerprintRunningState(BIOMETRIC_STATE_STOPPED);
}
- if (msgId == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE
- || msgId == FingerprintManager.BIOMETRIC_ERROR_POWER_PRESSED) {
- mLogger.logRetryAfterFpError(msgId, errString);
+ if (msgId == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) {
+ mLogger.logRetryAfterFpErrorWithDelay(msgId, errString, HAL_ERROR_RETRY_TIMEOUT);
mHandler.postDelayed(mRetryFingerprintAuthentication, HAL_ERROR_RETRY_TIMEOUT);
}
+ if (msgId == FingerprintManager.BIOMETRIC_ERROR_POWER_PRESSED) {
+ mLogger.logRetryAfterFpErrorWithDelay(msgId, errString, 0);
+ updateFingerprintListeningState(BIOMETRIC_ACTION_START);
+ }
+
boolean lockedOutStateChanged = false;
if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
lockedOutStateChanged = !mFingerprintLockedOutPermanent;
@@ -1401,6 +1405,9 @@
}
}
+ /**
+ * Whether the user locked down the device. This doesn't include device policy manager lockdown.
+ */
public boolean isUserInLockdown(int userId) {
return containsFlag(mStrongAuthTracker.getStrongAuthForUser(userId),
STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
@@ -1432,7 +1439,8 @@
return mStrongAuthTracker;
}
- private void notifyStrongAuthStateChanged(int userId) {
+ @VisibleForTesting
+ void notifyStrongAuthAllowedChanged(int userId) {
Assert.isMainThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -1440,6 +1448,15 @@
cb.onStrongAuthStateChanged(userId);
}
}
+ if (userId == getCurrentUser()) {
+ FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED.setExtraInfo(
+ mStrongAuthTracker.getStrongAuthForUser(getCurrentUser()));
+
+ // Strong auth is only reset when primary auth is used to enter the device,
+ // so we only check whether to stop biometric listening states here
+ updateBiometricListeningState(
+ BIOMETRIC_ACTION_STOP, FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED);
+ }
}
private void notifyLockedOutStateChanged(BiometricSourceType type) {
@@ -1451,8 +1468,8 @@
}
}
}
-
- private void notifyNonStrongBiometricStateChanged(int userId) {
+ @VisibleForTesting
+ void notifyNonStrongBiometricAllowedChanged(int userId) {
Assert.isMainThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -1460,6 +1477,16 @@
cb.onNonStrongBiometricAllowedChanged(userId);
}
}
+ if (userId == getCurrentUser()) {
+ FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED.setExtraInfo(
+ mStrongAuthTracker.isNonStrongBiometricAllowedAfterIdleTimeout(
+ getCurrentUser()) ? -1 : 1);
+
+ // This is only reset when primary auth is used to enter the device, so we only check
+ // whether to stop biometric listening states here
+ updateBiometricListeningState(BIOMETRIC_ACTION_STOP,
+ FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED);
+ }
}
private void dispatchErrorMessage(CharSequence message) {
@@ -1805,16 +1832,12 @@
}
}
- public static class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
- private final Consumer<Integer> mStrongAuthRequiredChangedCallback;
- private final Consumer<Integer> mNonStrongBiometricAllowedChanged;
-
- public StrongAuthTracker(Context context,
- Consumer<Integer> strongAuthRequiredChangedCallback,
- Consumer<Integer> nonStrongBiometricAllowedChanged) {
+ /**
+ * Updates callbacks when strong auth requirements change.
+ */
+ public class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
+ public StrongAuthTracker(Context context) {
super(context);
- mStrongAuthRequiredChangedCallback = strongAuthRequiredChangedCallback;
- mNonStrongBiometricAllowedChanged = nonStrongBiometricAllowedChanged;
}
public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) {
@@ -1830,7 +1853,7 @@
@Override
public void onStrongAuthRequiredChanged(int userId) {
- mStrongAuthRequiredChangedCallback.accept(userId);
+ notifyStrongAuthAllowedChanged(userId);
}
// TODO(b/247091681): Renaming the inappropriate onIsNonStrongBiometricAllowedChanged
@@ -1838,7 +1861,7 @@
// Strong-Auth
@Override
public void onIsNonStrongBiometricAllowedChanged(int userId) {
- mNonStrongBiometricAllowedChanged.accept(userId);
+ notifyNonStrongBiometricAllowedChanged(userId);
}
}
@@ -1999,8 +2022,7 @@
mUserTracker = userTracker;
mTelephonyListenerManager = telephonyListenerManager;
mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
- mStrongAuthTracker = new StrongAuthTracker(context, this::notifyStrongAuthStateChanged,
- this::notifyNonStrongBiometricStateChanged);
+ mStrongAuthTracker = new StrongAuthTracker(context);
mBackgroundExecutor = backgroundExecutor;
mBroadcastDispatcher = broadcastDispatcher;
mInteractionJankMonitor = interactionJankMonitor;
@@ -2575,24 +2597,17 @@
|| !mLockPatternUtils.isSecure(user);
// Don't trigger active unlock if fp is locked out
- final boolean fpLockedout = mFingerprintLockedOut || mFingerprintLockedOutPermanent;
+ final boolean fpLockedOut = mFingerprintLockedOut || mFingerprintLockedOutPermanent;
// Don't trigger active unlock if primary auth is required
- final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user);
- final boolean isLockDown =
- containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW)
- || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
- final boolean isEncryptedOrTimedOut =
- containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT)
- || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
+ final boolean primaryAuthRequired = !isUnlockingWithBiometricAllowed(true);
final boolean shouldTriggerActiveUnlock =
(mAuthInterruptActive || triggerActiveUnlockForAssistant || awakeKeyguard)
&& !mSwitchingUser
&& !userCanDismissLockScreen
- && !fpLockedout
- && !isLockDown
- && !isEncryptedOrTimedOut
+ && !fpLockedOut
+ && !primaryAuthRequired
&& !mKeyguardGoingAway
&& !mSecureCameraLaunched;
@@ -2604,9 +2619,8 @@
shouldTriggerActiveUnlock,
awakeKeyguard,
mAuthInterruptActive,
- isEncryptedOrTimedOut,
- fpLockedout,
- isLockDown,
+ fpLockedOut,
+ primaryAuthRequired,
mSwitchingUser,
triggerActiveUnlockForAssistant,
userCanDismissLockScreen));
@@ -2658,7 +2672,8 @@
&& !fingerprintDisabledForUser
&& (!mKeyguardGoingAway || !mDeviceInteractive)
&& mIsPrimaryUser
- && biometricEnabledForUser;
+ && biometricEnabledForUser
+ && !isUserInLockdown(user);
final boolean strongerAuthRequired = !isUnlockingWithFingerprintAllowed();
final boolean isSideFps = isSfpsSupported() && isSfpsEnrolled();
final boolean shouldListenBouncerState =
@@ -2720,14 +2735,7 @@
final boolean awakeKeyguard = isKeyguardVisible() && mDeviceInteractive
&& !statusBarShadeLocked;
final int user = getCurrentUser();
- final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user);
- final boolean isLockDown =
- containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW)
- || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
- final boolean isEncryptedOrTimedOut =
- containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT)
- || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
- final boolean fpLockedOut = isFingerprintLockedOut();
+ final boolean faceAuthAllowed = isUnlockingWithBiometricAllowed(FACE);
final boolean canBypass = mKeyguardBypassController != null
&& mKeyguardBypassController.canBypass();
// There's no reason to ask the HAL for authentication when the user can dismiss the
@@ -2735,20 +2743,15 @@
// the lock screen even when TrustAgents are keeping the device unlocked.
final boolean userNotTrustedOrDetectionIsNeeded = !getUserHasTrust(user) || canBypass;
- // Scan even when encrypted or timeout to show a preemptive bouncer when bypassing.
- // Lock-down mode shouldn't scan, since it is more explicit.
- boolean strongAuthAllowsScanning = (!isEncryptedOrTimedOut || canBypass
- && !mPrimaryBouncerFullyShown);
-
- // If the device supports face detection (without authentication) and bypass is enabled,
- // allow face scanning to happen if the device is in lockdown mode.
- // Otherwise, prevent scanning.
- final boolean supportsDetectOnly = !mFaceSensorProperties.isEmpty()
- && canBypass
- && mFaceSensorProperties.get(0).supportsFaceDetection;
- if (isLockDown && !supportsDetectOnly) {
- strongAuthAllowsScanning = false;
- }
+ // If the device supports face detection (without authentication), if bypass is enabled,
+ // allow face detection to happen even if stronger auth is required. When face is detected,
+ // we show the bouncer. However, if the user manually locked down the device themselves,
+ // never attempt to detect face.
+ final boolean supportsDetect = !mFaceSensorProperties.isEmpty()
+ && mFaceSensorProperties.get(0).supportsFaceDetection
+ && canBypass && !mPrimaryBouncerIsOrWillBeShowing
+ && !isUserInLockdown(user);
+ final boolean faceAuthAllowedOrDetectionIsNeeded = faceAuthAllowed || supportsDetect;
// If the face or fp has recently been authenticated do not attempt to authenticate again.
final boolean faceAndFpNotAuthenticated = !getUserUnlockedWithBiometric(user);
@@ -2769,14 +2772,10 @@
|| mUdfpsBouncerShowing)
&& !mSwitchingUser && !faceDisabledForUser && userNotTrustedOrDetectionIsNeeded
&& !mKeyguardGoingAway && biometricEnabledForUser
- && strongAuthAllowsScanning && mIsPrimaryUser
+ && faceAuthAllowedOrDetectionIsNeeded && mIsPrimaryUser
&& (!mSecureCameraLaunched || mOccludingAppRequestingFace)
&& faceAndFpNotAuthenticated
- && !mGoingToSleep
- // We only care about fp locked out state and not face because we still trigger
- // face auth even when face is locked out to show the user a message that face
- // unlock was supposed to run but didn't
- && !fpLockedOut;
+ && !mGoingToSleep;
// Aggregate relevant fields for debug logging.
maybeLogListenerModelData(
@@ -2786,19 +2785,19 @@
shouldListen,
mAuthInterruptActive,
biometricEnabledForUser,
- mPrimaryBouncerFullyShown,
+ mPrimaryBouncerFullyShown,
faceAndFpNotAuthenticated,
+ faceAuthAllowed,
faceDisabledForUser,
isFaceLockedOut(),
- fpLockedOut,
mGoingToSleep,
awakeKeyguard,
mKeyguardGoingAway,
shouldListenForFaceAssistant,
mOccludingAppRequestingFace,
mIsPrimaryUser,
- strongAuthAllowsScanning,
mSecureCameraLaunched,
+ supportsDetect,
mSwitchingUser,
mUdfpsBouncerShowing,
isUdfpsFingerDown,
@@ -2902,9 +2901,11 @@
// This would need to be updated for multi-sensor devices
final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty()
&& mFaceSensorProperties.get(0).supportsFaceDetection;
- if (isEncryptedOrLockdown(userId) && supportsFaceDetection) {
+ if (!isUnlockingWithBiometricAllowed(FACE) && supportsFaceDetection) {
+ mLogger.v("startListeningForFace - detect");
mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId);
} else {
+ mLogger.v("startListeningForFace - authenticate");
final boolean isBypassEnabled = mKeyguardBypassController != null
&& mKeyguardBypassController.isBypassEnabled();
mFaceManager.authenticate(null /* crypto */, mFaceCancelSignal,
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index 1f6441a..b66ae28 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -225,12 +225,13 @@
{ "Retrying face after HW unavailable, attempt $int1" })
}
- fun logRetryAfterFpError(msgId: Int, errString: String?) {
+ fun logRetryAfterFpErrorWithDelay(msgId: Int, errString: String?, delay: Int) {
logBuffer.log(TAG, DEBUG, {
int1 = msgId
+ int2 = delay
str1 = "$errString"
}, {
- "Fingerprint retrying auth due to($int1) -> $str1"
+ "Fingerprint retrying auth after $int2 ms due to($int1) -> $str1"
})
}
diff --git a/packages/SystemUI/src/com/android/systemui/CoreStartable.java b/packages/SystemUI/src/com/android/systemui/CoreStartable.java
index 929ebea..becf5b3 100644
--- a/packages/SystemUI/src/com/android/systemui/CoreStartable.java
+++ b/packages/SystemUI/src/com/android/systemui/CoreStartable.java
@@ -39,10 +39,13 @@
*/
public interface CoreStartable extends Dumpable {
- /** Main entry point for implementations. Called shortly after app startup. */
+ /** Main entry point for implementations. Called shortly after SysUI startup. */
void start();
- /** */
+ /** Called when the device configuration changes. This will not be called before
+ * {@link #start()}, but it could be called before {@link #onBootCompleted()}.
+ *
+ * @see android.app.Application#onConfigurationChanged(Configuration) */
default void onConfigurationChanged(Configuration newConfig) {
}
@@ -50,7 +53,11 @@
default void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
}
- /** Called when the device reports BOOT_COMPLETED. */
+ /** Called immediately after the system broadcasts
+ * {@link android.content.Intent#ACTION_LOCKED_BOOT_COMPLETED} or during SysUI startup if the
+ * property {@code sys.boot_completed} is already set to 1. The latter typically occurs when
+ * starting a new SysUI instance, such as when starting SysUI for a secondary user.
+ * {@link #onBootCompleted()} will never be called before {@link #start()}. */
default void onBootCompleted() {
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index a7519cf..db2239b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -623,6 +623,10 @@
getFingerprintSensorLocationInNaturalOrientation(),
mCachedDisplayInfo);
}
+
+ for (final Callback cb : mCallbacks) {
+ cb.onFingerprintLocationChanged();
+ }
}
/**
@@ -644,6 +648,10 @@
mCachedDisplayInfo
);
}
+
+ for (final Callback cb : mCallbacks) {
+ cb.onFaceSensorLocationChanged();
+ }
}
/**
@@ -1325,8 +1333,24 @@
default void onBiometricPromptDismissed() {}
/**
- * The location in pixels can change due to resolution changes.
+ * Called when the location of the fingerprint sensor changes. The location in pixels can
+ * change due to resolution changes.
+ */
+ default void onFingerprintLocationChanged() {}
+
+ /**
+ * Called when the location of the under display fingerprint sensor changes. The location in
+ * pixels can change due to resolution changes.
+ *
+ * On devices with UDFPS, this is always called alongside
+ * {@link #onFingerprintLocationChanged}.
*/
default void onUdfpsLocationChanged() {}
+
+ /**
+ * Called when the location of the face unlock sensor (typically the front facing camera)
+ * changes. The location in pixels can change due to resolution changes.
+ */
+ default void onFaceSensorLocationChanged() {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index 6ac54fe..d561cd7 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -29,6 +29,8 @@
import com.android.settingslib.Utils
import com.android.systemui.R
import com.android.systemui.animation.Interpolators
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.CircleReveal
@@ -71,7 +73,8 @@
private val biometricUnlockController: BiometricUnlockController,
private val udfpsControllerProvider: Provider<UdfpsController>,
private val statusBarStateController: StatusBarStateController,
- rippleView: AuthRippleView?
+ private val featureFlags: FeatureFlags,
+ rippleView: AuthRippleView?
) : ViewController<AuthRippleView>(rippleView), KeyguardStateController.Callback,
WakefulnessLifecycle.Observer {
@@ -159,12 +162,17 @@
private fun showUnlockedRipple() {
notificationShadeWindowController.setForcePluginOpen(true, this)
- val lightRevealScrim = centralSurfaces.lightRevealScrim
- if (statusBarStateController.isDozing || biometricUnlockController.isWakeAndUnlock) {
- circleReveal?.let {
- lightRevealScrim?.revealAmount = 0f
- lightRevealScrim?.revealEffect = it
- startLightRevealScrimOnKeyguardFadingAway = true
+
+ // This code path is not used if the KeyguardTransitionRepository is managing the light
+ // reveal scrim.
+ if (!featureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) {
+ val lightRevealScrim = centralSurfaces.lightRevealScrim
+ if (statusBarStateController.isDozing || biometricUnlockController.isWakeAndUnlock) {
+ circleReveal?.let {
+ lightRevealScrim?.revealAmount = 0f
+ lightRevealScrim?.revealEffect = it
+ startLightRevealScrimOnKeyguardFadingAway = true
+ }
}
}
@@ -177,6 +185,10 @@
}
override fun onKeyguardFadingAwayChanged() {
+ if (featureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) {
+ return
+ }
+
if (keyguardStateController.isKeyguardFadingAway) {
val lightRevealScrim = centralSurfaces.lightRevealScrim
if (startLightRevealScrimOnKeyguardFadingAway && lightRevealScrim != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
index 1c3dd45..17ebdad 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
@@ -135,7 +135,7 @@
WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
- WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
+ WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS,
PixelFormat.TRANSLUCENT
)
@@ -370,11 +370,15 @@
private fun LottieAnimationView.addOverlayDynamicColor(context: Context) {
fun update() {
val c = context.getColor(R.color.biometric_dialog_accent)
+ val chevronFill = context.getColor(R.color.sfps_chevron_fill)
for (key in listOf(".blue600", ".blue400")) {
addValueCallback(KeyPath(key, "**"), LottieProperty.COLOR_FILTER) {
PorterDuffColorFilter(c, PorterDuff.Mode.SRC_ATOP)
}
}
+ addValueCallback(KeyPath(".black", "**"), LottieProperty.COLOR_FILTER) {
+ PorterDuffColorFilter(chevronFill, PorterDuff.Mode.SRC_ATOP)
+ }
}
if (composition != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
index 705a110..8b4b30c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
@@ -32,6 +32,7 @@
import android.app.UiModeManager;
import android.app.WallpaperManager;
import android.app.admin.DevicePolicyManager;
+import android.app.job.JobScheduler;
import android.app.role.RoleManager;
import android.app.smartspace.SmartspaceManager;
import android.app.trust.TrustManager;
@@ -286,6 +287,12 @@
@Provides
@Singleton
+ static JobScheduler provideJobScheduler(Context context) {
+ return context.getSystemService(JobScheduler.class);
+ }
+
+ @Provides
+ @Singleton
static InteractionJankMonitor provideInteractionJankMonitor() {
return InteractionJankMonitor.getInstance();
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 25b276a..8019b56 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -164,6 +164,13 @@
// TODO(b/256513609): Tracking Bug
@JvmField val ACTIVE_UNLOCK_CHIPBAR = releasedFlag(217, "active_unlock_chipbar")
+ /**
+ * Migrates control of the LightRevealScrim's reveal effect and amount from legacy code to the
+ * new KeyguardTransitionRepository.
+ */
+ @JvmField
+ val LIGHT_REVEAL_MIGRATION = unreleasedFlag(218, "light_reveal_migration", teamfood = true)
+
// 300 - power menu
// TODO(b/254512600): Tracking Bug
@JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite")
@@ -370,7 +377,7 @@
// TODO(b/255854141): Tracking Bug
@JvmField
val WM_ENABLE_PREDICTIVE_BACK_SYSUI =
- unreleasedFlag(1204, "persist.wm.debug.predictive_back_sysui_enable", teamfood = false)
+ unreleasedFlag(1204, "persist.wm.debug.predictive_back_sysui_enable", teamfood = true)
// 1300 - screenshots
// TODO(b/254512719): Tracking Bug
@@ -403,8 +410,8 @@
val LEAVE_SHADE_OPEN_FOR_BUGREPORT =
unreleasedFlag(1800, "leave_shade_open_for_bugreport", teamfood = true)
- // 1900 - note task
- @JvmField val NOTE_TASKS = sysPropBooleanFlag(1900, "persist.sysui.debug.note_tasks")
+ // 1900
+ @JvmField val NOTE_TASKS = unreleasedFlag(1900, "keycode_flag")
// 2000 - device controls
@Keep @JvmField val USE_APP_PANELS = unreleasedFlag(2000, "use_app_panels", teamfood = true)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index 796f2b4..148792b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -16,8 +16,11 @@
package com.android.systemui.keyguard.data.repository
+import android.graphics.Point
+import android.hardware.biometrics.BiometricSourceType
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.biometrics.AuthController
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.common.shared.model.Position
@@ -27,8 +30,8 @@
import com.android.systemui.doze.DozeTransitionCallback
import com.android.systemui.doze.DozeTransitionListener
import com.android.systemui.keyguard.WakefulnessLifecycle
-import com.android.systemui.keyguard.WakefulnessLifecycle.Wakefulness
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.StatusBarState
@@ -88,8 +91,8 @@
* enter to conserve battery when the device is locked and inactive.
*
* Note that it is possible for the system to be transitioning into doze while this flow still
- * returns `false`. In order to account for that, observers should also use the [dozeAmount]
- * flow to check if it's greater than `0`
+ * returns `false`. In order to account for that, observers should also use the
+ * [linearDozeAmount] flow to check if it's greater than `0`
*/
val isDozing: Flow<Boolean>
@@ -111,7 +114,7 @@
* happens during an animation/transition into doze mode. An observer would be wise to account
* for both flows if needed.
*/
- val dozeAmount: Flow<Float>
+ val linearDozeAmount: Flow<Float>
/** Doze state information, as it transitions */
val dozeTransitionModel: Flow<DozeTransitionModel>
@@ -120,11 +123,20 @@
val statusBarState: Flow<StatusBarState>
/** Observable for device wake/sleep state */
- val wakefulnessState: Flow<WakefulnessModel>
+ val wakefulness: Flow<WakefulnessModel>
/** Observable for biometric unlock modes */
val biometricUnlockState: Flow<BiometricUnlockModel>
+ /** Approximate location on the screen of the fingerprint sensor. */
+ val fingerprintSensorLocation: Flow<Point?>
+
+ /** Approximate location on the screen of the face unlock sensor/front facing camera. */
+ val faceSensorLocation: Flow<Point?>
+
+ /** Source of the most recent biometric unlock, such as fingerprint or face. */
+ val biometricUnlockSource: Flow<BiometricUnlockSource?>
+
/**
* Returns `true` if the keyguard is showing; `false` otherwise.
*
@@ -163,6 +175,7 @@
private val keyguardStateController: KeyguardStateController,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val dozeTransitionListener: DozeTransitionListener,
+ private val authController: AuthController,
) : KeyguardRepository {
private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
override val animateBottomAreaDozingTransitions =
@@ -281,11 +294,11 @@
}
.distinctUntilChanged()
- override val dozeAmount: Flow<Float> = conflatedCallbackFlow {
+ override val linearDozeAmount: Flow<Float> = conflatedCallbackFlow {
val callback =
object : StatusBarStateController.StateListener {
override fun onDozeAmountChanged(linear: Float, eased: Float) {
- trySendWithFailureLogging(eased, TAG, "updated dozeAmount")
+ trySendWithFailureLogging(linear, TAG, "updated dozeAmount")
}
}
@@ -348,58 +361,139 @@
awaitClose { statusBarStateController.removeCallback(callback) }
}
- override val wakefulnessState: Flow<WakefulnessModel> = conflatedCallbackFlow {
- val callback =
- object : WakefulnessLifecycle.Observer {
- override fun onStartedWakingUp() {
- trySendWithFailureLogging(
- WakefulnessModel.STARTING_TO_WAKE,
- TAG,
- "Wakefulness: starting to wake"
- )
- }
- override fun onFinishedWakingUp() {
- trySendWithFailureLogging(WakefulnessModel.AWAKE, TAG, "Wakefulness: awake")
- }
- override fun onStartedGoingToSleep() {
- trySendWithFailureLogging(
- WakefulnessModel.STARTING_TO_SLEEP,
- TAG,
- "Wakefulness: starting to sleep"
- )
- }
- override fun onFinishedGoingToSleep() {
- trySendWithFailureLogging(WakefulnessModel.ASLEEP, TAG, "Wakefulness: asleep")
- }
- }
- wakefulnessLifecycle.addObserver(callback)
- trySendWithFailureLogging(
- wakefulnessIntToObject(wakefulnessLifecycle.getWakefulness()),
- TAG,
- "initial wakefulness state"
- )
-
- awaitClose { wakefulnessLifecycle.removeObserver(callback) }
- }
-
override val biometricUnlockState: Flow<BiometricUnlockModel> = conflatedCallbackFlow {
+ fun dispatchUpdate() {
+ trySendWithFailureLogging(
+ biometricModeIntToObject(biometricUnlockController.mode),
+ TAG,
+ "biometric mode"
+ )
+ }
+
val callback =
object : BiometricUnlockController.BiometricModeListener {
override fun onModeChanged(@WakeAndUnlockMode mode: Int) {
- trySendWithFailureLogging(biometricModeIntToObject(mode), TAG, "biometric mode")
+ dispatchUpdate()
+ }
+
+ override fun onResetMode() {
+ dispatchUpdate()
}
}
biometricUnlockController.addBiometricModeListener(callback)
- trySendWithFailureLogging(
- biometricModeIntToObject(biometricUnlockController.getMode()),
- TAG,
- "initial biometric mode"
- )
+ dispatchUpdate()
awaitClose { biometricUnlockController.removeBiometricModeListener(callback) }
}
+ override val wakefulness: Flow<WakefulnessModel> = conflatedCallbackFlow {
+ val observer =
+ object : WakefulnessLifecycle.Observer {
+ override fun onStartedWakingUp() {
+ dispatchNewState()
+ }
+
+ override fun onFinishedWakingUp() {
+ dispatchNewState()
+ }
+
+ override fun onPostFinishedWakingUp() {
+ dispatchNewState()
+ }
+
+ override fun onStartedGoingToSleep() {
+ dispatchNewState()
+ }
+
+ override fun onFinishedGoingToSleep() {
+ dispatchNewState()
+ }
+
+ private fun dispatchNewState() {
+ trySendWithFailureLogging(
+ WakefulnessModel.fromWakefulnessLifecycle(wakefulnessLifecycle),
+ TAG,
+ "updated wakefulness state"
+ )
+ }
+ }
+
+ wakefulnessLifecycle.addObserver(observer)
+ trySendWithFailureLogging(
+ WakefulnessModel.fromWakefulnessLifecycle(wakefulnessLifecycle),
+ TAG,
+ "initial wakefulness state"
+ )
+
+ awaitClose { wakefulnessLifecycle.removeObserver(observer) }
+ }
+
+ override val fingerprintSensorLocation: Flow<Point?> = conflatedCallbackFlow {
+ fun sendFpLocation() {
+ trySendWithFailureLogging(
+ authController.fingerprintSensorLocation,
+ TAG,
+ "AuthController.Callback#onFingerprintLocationChanged"
+ )
+ }
+
+ val callback =
+ object : AuthController.Callback {
+ override fun onFingerprintLocationChanged() {
+ sendFpLocation()
+ }
+ }
+
+ authController.addCallback(callback)
+ sendFpLocation()
+
+ awaitClose { authController.removeCallback(callback) }
+ }
+
+ override val faceSensorLocation: Flow<Point?> = conflatedCallbackFlow {
+ fun sendSensorLocation() {
+ trySendWithFailureLogging(
+ authController.faceSensorLocation,
+ TAG,
+ "AuthController.Callback#onFingerprintLocationChanged"
+ )
+ }
+
+ val callback =
+ object : AuthController.Callback {
+ override fun onFaceSensorLocationChanged() {
+ sendSensorLocation()
+ }
+ }
+
+ authController.addCallback(callback)
+ sendSensorLocation()
+
+ awaitClose { authController.removeCallback(callback) }
+ }
+
+ override val biometricUnlockSource: Flow<BiometricUnlockSource?> = conflatedCallbackFlow {
+ val callback =
+ object : KeyguardUpdateMonitorCallback() {
+ override fun onBiometricAuthenticated(
+ userId: Int,
+ biometricSourceType: BiometricSourceType?,
+ isStrongBiometric: Boolean
+ ) {
+ trySendWithFailureLogging(
+ BiometricUnlockSource.fromBiometricSourceType(biometricSourceType),
+ TAG,
+ "onBiometricAuthenticated"
+ )
+ }
+ }
+
+ keyguardUpdateMonitor.registerCallback(callback)
+ trySendWithFailureLogging(null, TAG, "initial value")
+ awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
+ }
+
override fun setAnimateDozingTransitions(animate: Boolean) {
_animateBottomAreaDozingTransitions.value = animate
}
@@ -423,16 +517,6 @@
}
}
- private fun wakefulnessIntToObject(@Wakefulness value: Int): WakefulnessModel {
- return when (value) {
- 0 -> WakefulnessModel.ASLEEP
- 1 -> WakefulnessModel.STARTING_TO_WAKE
- 2 -> WakefulnessModel.AWAKE
- 3 -> WakefulnessModel.STARTING_TO_SLEEP
- else -> throw IllegalArgumentException("Invalid Wakefulness value: $value")
- }
- }
-
private fun biometricModeIntToObject(@WakeAndUnlockMode value: Int): BiometricUnlockModel {
return when (value) {
0 -> BiometricUnlockModel.NONE
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 0c72520..26f853f 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
@@ -27,4 +27,7 @@
fun keyguardTransitionRepository(
impl: KeyguardTransitionRepositoryImpl
): KeyguardTransitionRepository
+
+ @Binds
+ fun lightRevealScrimRepository(impl: LightRevealScrimRepositoryImpl): LightRevealScrimRepository
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
index bce7d92..5bb586e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
@@ -116,6 +116,7 @@
KeyguardState.LOCKSCREEN,
0f,
TransitionState.STARTED,
+ KeyguardTransitionRepositoryImpl::class.simpleName!!,
)
)
emitTransition(
@@ -124,6 +125,7 @@
KeyguardState.LOCKSCREEN,
1f,
TransitionState.FINISHED,
+ KeyguardTransitionRepositoryImpl::class.simpleName!!,
)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt
new file mode 100644
index 0000000..a17481a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.data.repository
+
+import android.content.Context
+import android.graphics.Point
+import com.android.systemui.R
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
+import com.android.systemui.keyguard.shared.model.WakeSleepReason
+import com.android.systemui.statusbar.CircleReveal
+import com.android.systemui.statusbar.LiftReveal
+import com.android.systemui.statusbar.LightRevealEffect
+import com.android.systemui.statusbar.PowerButtonReveal
+import javax.inject.Inject
+import kotlin.math.max
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+
+val DEFAULT_REVEAL_EFFECT = LiftReveal
+
+/**
+ * Encapsulates state relevant to the light reveal scrim, the view used to reveal/hide screen
+ * contents during transitions between AOD and lockscreen/unlocked.
+ */
+interface LightRevealScrimRepository {
+
+ /**
+ * The reveal effect that should be used for the next lock/unlock. We switch between either the
+ * biometric unlock effect (if wake and unlocking) or the non-biometric effect, and position it
+ * at the current screen position of the appropriate sensor.
+ */
+ val revealEffect: Flow<LightRevealEffect>
+}
+
+@SysUISingleton
+class LightRevealScrimRepositoryImpl
+@Inject
+constructor(
+ keyguardRepository: KeyguardRepository,
+ val context: Context,
+) : LightRevealScrimRepository {
+
+ /** The reveal effect used if the device was locked/unlocked via the power button. */
+ private val powerButtonReveal =
+ PowerButtonReveal(
+ context.resources
+ .getDimensionPixelSize(R.dimen.physical_power_button_center_screen_location_y)
+ .toFloat()
+ )
+
+ /**
+ * Reveal effect to use for a fingerprint unlock. This is reconstructed if the fingerprint
+ * sensor location on the screen (in pixels) changes due to configuration changes.
+ */
+ private val fingerprintRevealEffect: Flow<LightRevealEffect?> =
+ keyguardRepository.fingerprintSensorLocation.map {
+ it?.let { constructCircleRevealFromPoint(it) }
+ }
+
+ /**
+ * Reveal effect to use for a face unlock. This is reconstructed if the face sensor/front camera
+ * location on the screen (in pixels) changes due to configuration changes.
+ */
+ private val faceRevealEffect: Flow<LightRevealEffect?> =
+ keyguardRepository.faceSensorLocation.map { it?.let { constructCircleRevealFromPoint(it) } }
+
+ /**
+ * The reveal effect we'll use for the next biometric unlock animation. We switch between the
+ * fingerprint/face unlock effect flows depending on the biometric unlock source.
+ */
+ private val biometricRevealEffect: Flow<LightRevealEffect?> =
+ keyguardRepository.biometricUnlockSource.flatMapLatest { source ->
+ when (source) {
+ BiometricUnlockSource.FINGERPRINT_SENSOR -> fingerprintRevealEffect
+ BiometricUnlockSource.FACE_SENSOR -> faceRevealEffect
+ else -> flowOf(null)
+ }
+ }
+
+ /** The reveal effect we'll use for the next non-biometric unlock (tap, power button, etc). */
+ private val nonBiometricRevealEffect: Flow<LightRevealEffect?> =
+ keyguardRepository.wakefulness.map { wakefulnessModel ->
+ val wakingUpFromPowerButton =
+ wakefulnessModel.isWakingUpOrAwake &&
+ wakefulnessModel.lastWakeReason == WakeSleepReason.POWER_BUTTON
+ val sleepingFromPowerButton =
+ !wakefulnessModel.isWakingUpOrAwake &&
+ wakefulnessModel.lastSleepReason == WakeSleepReason.POWER_BUTTON
+
+ if (wakingUpFromPowerButton || sleepingFromPowerButton) {
+ powerButtonReveal
+ } else {
+ LiftReveal
+ }
+ }
+
+ override val revealEffect =
+ combine(
+ keyguardRepository.biometricUnlockState,
+ biometricRevealEffect,
+ nonBiometricRevealEffect
+ ) { biometricUnlockState, biometricReveal, nonBiometricReveal ->
+
+ // Use the biometric reveal for any flavor of wake and unlocking.
+ when (biometricUnlockState) {
+ BiometricUnlockModel.WAKE_AND_UNLOCK,
+ BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING,
+ BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM -> biometricReveal
+ else -> nonBiometricReveal
+ }
+ ?: DEFAULT_REVEAL_EFFECT
+ }
+ .distinctUntilChanged()
+
+ private fun constructCircleRevealFromPoint(point: Point): LightRevealEffect {
+ return with(point) {
+ CircleReveal(
+ x,
+ y,
+ startRadius = 0,
+ endRadius =
+ max(max(x, context.display.width - x), max(y, context.display.height - y)),
+ )
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt
index 2dbacd5..f3d2905 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt
@@ -27,7 +27,6 @@
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
@SysUISingleton
@@ -42,17 +41,14 @@
override fun start() {
listenForTransitionToAodFromLockscreen()
- listenForTransitionToLockscreenFromAod()
+ listenForTransitionToLockscreenFromDozeStates()
}
private fun listenForTransitionToAodFromLockscreen() {
scope.launch {
keyguardInteractor
.dozeTransitionTo(DozeStateModel.DOZE_AOD)
- .sample(
- keyguardTransitionInteractor.startedKeyguardTransitionStep,
- { a, b -> Pair(a, b) }
- )
+ .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
.collect { pair ->
val (dozeToAod, lastStartedStep) = pair
if (lastStartedStep.to == KeyguardState.LOCKSCREEN) {
@@ -69,21 +65,19 @@
}
}
- private fun listenForTransitionToLockscreenFromAod() {
+ private fun listenForTransitionToLockscreenFromDozeStates() {
+ val canGoToLockscreen = setOf(KeyguardState.AOD, KeyguardState.DOZING)
scope.launch {
keyguardInteractor
.dozeTransitionTo(DozeStateModel.FINISH)
- .sample(
- keyguardTransitionInteractor.startedKeyguardTransitionStep,
- { a, b -> Pair(a, b) }
- )
+ .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
.collect { pair ->
val (dozeToAod, lastStartedStep) = pair
- if (lastStartedStep.to == KeyguardState.AOD) {
+ if (canGoToLockscreen.contains(lastStartedStep.to)) {
keyguardTransitionRepository.startTransition(
TransitionInfo(
name,
- KeyguardState.AOD,
+ lastStartedStep.to,
KeyguardState.LOCKSCREEN,
getAnimator(),
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodToGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodToGoneTransitionInteractor.kt
index 2a220fc..dad166f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodToGoneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodToGoneTransitionInteractor.kt
@@ -21,9 +21,7 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.WAKE_AND_UNLOCK
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
-import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING
+import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.Companion.isWakeAndUnlock
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.util.kotlin.sample
@@ -42,9 +40,6 @@
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
) : TransitionInteractor(AodToGoneTransitionInteractor::class.simpleName!!) {
- private val wakeAndUnlockModes =
- setOf(WAKE_AND_UNLOCK, WAKE_AND_UNLOCK_FROM_DREAM, WAKE_AND_UNLOCK_PULSING)
-
override fun start() {
scope.launch {
keyguardInteractor.biometricUnlockState
@@ -52,8 +47,7 @@
.collect { pair ->
val (biometricUnlockState, keyguardState) = pair
if (
- keyguardState == KeyguardState.AOD &&
- wakeAndUnlockModes.contains(biometricUnlockState)
+ keyguardState == KeyguardState.AOD && isWakeAndUnlock(biometricUnlockState)
) {
keyguardTransitionRepository.startTransition(
TransitionInfo(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingLockscreenTransitionInteractor.kt
deleted file mode 100644
index 9cbf9ea..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingLockscreenTransitionInteractor.kt
+++ /dev/null
@@ -1,94 +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
- */
-
-package com.android.systemui.keyguard.domain.interactor
-
-import android.animation.ValueAnimator
-import com.android.systemui.animation.Interpolators
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.DozeStateModel
-import com.android.systemui.keyguard.shared.model.KeyguardState
-import com.android.systemui.keyguard.shared.model.TransitionInfo
-import com.android.systemui.util.kotlin.sample
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.collect
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.launch
-
-@SysUISingleton
-class DreamingLockscreenTransitionInteractor
-@Inject
-constructor(
- @Application private val scope: CoroutineScope,
- private val keyguardInteractor: KeyguardInteractor,
- private val keyguardTransitionRepository: KeyguardTransitionRepository,
- private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
-) : TransitionInteractor(DreamingLockscreenTransitionInteractor::class.simpleName!!) {
-
- override fun start() {
- scope.launch {
- keyguardInteractor.isDreaming
- .sample(
- combine(
- keyguardInteractor.dozeTransitionModel,
- keyguardTransitionInteractor.finishedKeyguardState
- ) { a, b -> Pair(a, b) },
- { a, bc -> Triple(a, bc.first, bc.second) }
- )
- .collect { triple ->
- val (isDreaming, dozeTransitionModel, keyguardState) = triple
- // Dozing/AOD and dreaming have overlapping events. If the state remains in
- // FINISH, it means that doze mode is not running and DREAMING is ok to
- // commence.
- if (dozeTransitionModel.to == DozeStateModel.FINISH) {
- if (isDreaming && keyguardState == KeyguardState.LOCKSCREEN) {
- keyguardTransitionRepository.startTransition(
- TransitionInfo(
- name,
- KeyguardState.LOCKSCREEN,
- KeyguardState.DREAMING,
- getAnimator(),
- )
- )
- } else if (!isDreaming && keyguardState == KeyguardState.DREAMING) {
- keyguardTransitionRepository.startTransition(
- TransitionInfo(
- name,
- KeyguardState.DREAMING,
- KeyguardState.LOCKSCREEN,
- getAnimator(),
- )
- )
- }
- }
- }
- }
- }
-
- private fun getAnimator(): ValueAnimator {
- return ValueAnimator().apply {
- setInterpolator(Interpolators.LINEAR)
- setDuration(TRANSITION_DURATION_MS)
- }
- }
-
- companion object {
- private const val TRANSITION_DURATION_MS = 500L
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingToAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingToAodTransitionInteractor.kt
deleted file mode 100644
index 9e2b724..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingToAodTransitionInteractor.kt
+++ /dev/null
@@ -1,76 +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
- */
-
-package com.android.systemui.keyguard.domain.interactor
-
-import android.animation.ValueAnimator
-import com.android.systemui.animation.Interpolators
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.KeyguardState
-import com.android.systemui.keyguard.shared.model.TransitionInfo
-import com.android.systemui.keyguard.shared.model.WakefulnessModel.Companion.isSleepingOrStartingToSleep
-import com.android.systemui.util.kotlin.sample
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.collect
-import kotlinx.coroutines.launch
-
-@SysUISingleton
-class DreamingToAodTransitionInteractor
-@Inject
-constructor(
- @Application private val scope: CoroutineScope,
- private val keyguardInteractor: KeyguardInteractor,
- private val keyguardTransitionRepository: KeyguardTransitionRepository,
- private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
-) : TransitionInteractor("DREAMING->AOD") {
-
- override fun start() {
- scope.launch {
- keyguardInteractor.wakefulnessState
- .sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
- .collect { pair ->
- val (wakefulnessState, keyguardState) = pair
- if (
- isSleepingOrStartingToSleep(wakefulnessState) &&
- keyguardState == KeyguardState.DREAMING
- ) {
- keyguardTransitionRepository.startTransition(
- TransitionInfo(
- name,
- KeyguardState.DREAMING,
- KeyguardState.AOD,
- getAnimator(),
- )
- )
- }
- }
- }
- }
-
- private fun getAnimator(): ValueAnimator {
- return ValueAnimator().apply {
- setInterpolator(Interpolators.LINEAR)
- setDuration(TRANSITION_DURATION_MS)
- }
- }
-
- companion object {
- private const val TRANSITION_DURATION_MS = 300L
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingTransitionInteractor.kt
new file mode 100644
index 0000000..b73ce9e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingTransitionInteractor.kt
@@ -0,0 +1,180 @@
+/*
+ * 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 com.android.systemui.keyguard.domain.interactor
+
+import android.animation.ValueAnimator
+import com.android.systemui.animation.Interpolators
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.Companion.isWakeAndUnlock
+import com.android.systemui.keyguard.shared.model.DozeStateModel
+import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionInfo
+import com.android.systemui.util.kotlin.sample
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.launch
+
+@SysUISingleton
+class DreamingTransitionInteractor
+@Inject
+constructor(
+ @Application private val scope: CoroutineScope,
+ private val keyguardInteractor: KeyguardInteractor,
+ private val keyguardTransitionRepository: KeyguardTransitionRepository,
+ private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+) : TransitionInteractor(DreamingTransitionInteractor::class.simpleName!!) {
+
+ private val canDreamFrom =
+ setOf(KeyguardState.LOCKSCREEN, KeyguardState.GONE, KeyguardState.DOZING)
+
+ override fun start() {
+ listenForEntryToDreaming()
+ listenForDreamingToLockscreen()
+ listenForDreamingToGone()
+ listenForDreamingToDozing()
+ }
+
+ private fun listenForEntryToDreaming() {
+ scope.launch {
+ keyguardInteractor.isDreaming
+ .sample(
+ combine(
+ keyguardInteractor.dozeTransitionModel,
+ keyguardTransitionInteractor.finishedKeyguardState,
+ ::Pair
+ ),
+ ::toTriple
+ )
+ .collect { triple ->
+ val (isDreaming, dozeTransitionModel, keyguardState) = triple
+ // Dozing/AOD and dreaming have overlapping events. If the state remains in
+ // FINISH, it means that doze mode is not running and DREAMING is ok to
+ // commence.
+ if (
+ isDozeOff(dozeTransitionModel.to) &&
+ isDreaming &&
+ canDreamFrom.contains(keyguardState)
+ ) {
+ keyguardTransitionRepository.startTransition(
+ TransitionInfo(
+ name,
+ keyguardState,
+ KeyguardState.DREAMING,
+ getAnimator(),
+ )
+ )
+ }
+ }
+ }
+ }
+
+ private fun listenForDreamingToLockscreen() {
+ scope.launch {
+ keyguardInteractor.isDreaming
+ .sample(
+ combine(
+ keyguardInteractor.dozeTransitionModel,
+ keyguardTransitionInteractor.startedKeyguardTransitionStep,
+ ::Pair,
+ ),
+ ::toTriple
+ )
+ .collect { triple ->
+ val (isDreaming, dozeTransitionModel, lastStartedTransition) = triple
+ if (
+ isDozeOff(dozeTransitionModel.to) &&
+ !isDreaming &&
+ lastStartedTransition.to == KeyguardState.DREAMING
+ ) {
+ keyguardTransitionRepository.startTransition(
+ TransitionInfo(
+ name,
+ KeyguardState.DREAMING,
+ KeyguardState.LOCKSCREEN,
+ getAnimator(),
+ )
+ )
+ }
+ }
+ }
+ }
+
+ private fun listenForDreamingToGone() {
+ scope.launch {
+ keyguardInteractor.biometricUnlockState
+ .sample(keyguardTransitionInteractor.finishedKeyguardState, ::Pair)
+ .collect { pair ->
+ val (biometricUnlockState, keyguardState) = pair
+ if (
+ keyguardState == KeyguardState.DREAMING &&
+ isWakeAndUnlock(biometricUnlockState)
+ ) {
+ keyguardTransitionRepository.startTransition(
+ TransitionInfo(
+ name,
+ KeyguardState.DREAMING,
+ KeyguardState.GONE,
+ getAnimator(),
+ )
+ )
+ }
+ }
+ }
+ }
+
+ private fun listenForDreamingToDozing() {
+ scope.launch {
+ combine(
+ keyguardInteractor.dozeTransitionModel,
+ keyguardTransitionInteractor.finishedKeyguardState,
+ ::Pair
+ )
+ .collect { pair ->
+ val (dozeTransitionModel, keyguardState) = pair
+ if (
+ dozeTransitionModel.to == DozeStateModel.DOZE &&
+ keyguardState == KeyguardState.DREAMING
+ ) {
+ keyguardTransitionRepository.startTransition(
+ TransitionInfo(
+ name,
+ KeyguardState.DREAMING,
+ KeyguardState.DOZING,
+ getAnimator(),
+ )
+ )
+ }
+ }
+ }
+ }
+
+ private fun getAnimator(): ValueAnimator {
+ return ValueAnimator().apply {
+ setInterpolator(Interpolators.LINEAR)
+ setDuration(TRANSITION_DURATION_MS)
+ }
+ }
+
+ companion object {
+ private const val TRANSITION_DURATION_MS = 500L
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GoneAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GoneAodTransitionInteractor.kt
index 0e2a54c..a50e759 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GoneAodTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GoneAodTransitionInteractor.kt
@@ -23,11 +23,10 @@
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
-import com.android.systemui.keyguard.shared.model.WakefulnessModel
+import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
@SysUISingleton
@@ -38,17 +37,17 @@
private val keyguardInteractor: KeyguardInteractor,
private val keyguardTransitionRepository: KeyguardTransitionRepository,
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
-) : TransitionInteractor("GONE->AOD") {
+) : TransitionInteractor(GoneAodTransitionInteractor::class.simpleName!!) {
override fun start() {
scope.launch {
- keyguardInteractor.wakefulnessState
+ keyguardInteractor.wakefulnessModel
.sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
.collect { pair ->
val (wakefulnessState, keyguardState) = pair
if (
keyguardState == KeyguardState.GONE &&
- wakefulnessState == WakefulnessModel.STARTING_TO_SLEEP
+ wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP
) {
keyguardTransitionRepository.startTransition(
TransitionInfo(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 7cfd117..6912e1d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
+import android.graphics.Point
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
@@ -41,7 +42,7 @@
* The amount of doze the system is in, where `1.0` is fully dozing and `0.0` is not dozing at
* all.
*/
- val dozeAmount: Flow<Float> = repository.dozeAmount
+ val dozeAmount: Flow<Float> = repository.linearDozeAmount
/** Whether the system is in doze mode. */
val isDozing: Flow<Boolean> = repository.isDozing
/** Doze transition information. */
@@ -58,7 +59,7 @@
/** Whether the bouncer is showing or not. */
val isBouncerShowing: Flow<Boolean> = repository.isBouncerShowing
/** The device wake/sleep state */
- val wakefulnessState: Flow<WakefulnessModel> = repository.wakefulnessState
+ val wakefulnessModel: Flow<WakefulnessModel> = repository.wakefulness
/** Observable for the [StatusBarState] */
val statusBarState: Flow<StatusBarState> = repository.statusBarState
/**
@@ -67,10 +68,15 @@
*/
val biometricUnlockState: Flow<BiometricUnlockModel> = repository.biometricUnlockState
+ /** The approximate location on the screen of the fingerprint sensor, if one is available. */
+ val fingerprintSensorLocation: Flow<Point?> = repository.fingerprintSensorLocation
+
+ /** The approximate location on the screen of the face unlock sensor, if one is available. */
+ val faceSensorLocation: Flow<Point?> = repository.faceSensorLocation
+
fun dozeTransitionTo(state: DozeStateModel): Flow<DozeTransitionModel> {
return dozeTransitionModel.filter { it.to == state }
}
-
fun isKeyguardShowing(): Boolean {
return repository.isKeyguardShowing()
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
index 58a8093..a2661d7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
@@ -37,7 +37,7 @@
fun start() {
scope.launch {
- keyguardInteractor.wakefulnessState.collect { logger.v("WakefulnessState", it) }
+ keyguardInteractor.wakefulnessModel.collect { logger.v("WakefulnessModel", it) }
}
scope.launch {
@@ -46,6 +46,8 @@
scope.launch { keyguardInteractor.isDozing.collect { logger.v("isDozing", it) } }
+ scope.launch { keyguardInteractor.isDreaming.collect { logger.v("isDreaming", it) } }
+
scope.launch {
interactor.finishedKeyguardTransitionStep.collect {
logger.i("Finished transition", it)
@@ -61,5 +63,9 @@
scope.launch {
interactor.startedKeyguardTransitionStep.collect { logger.i("Started transition", it) }
}
+
+ scope.launch {
+ keyguardInteractor.dozeTransitionModel.collect { logger.i("Doze transition", it) }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
index 43dd358e..bb8b79a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
@@ -43,8 +43,7 @@
is LockscreenGoneTransitionInteractor -> Log.d(TAG, "Started $it")
is AodToGoneTransitionInteractor -> Log.d(TAG, "Started $it")
is BouncerToGoneTransitionInteractor -> Log.d(TAG, "Started $it")
- is DreamingLockscreenTransitionInteractor -> Log.d(TAG, "Started $it")
- is DreamingToAodTransitionInteractor -> Log.d(TAG, "Started $it")
+ is DreamingTransitionInteractor -> Log.d(TAG, "Started $it")
}
it.start()
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
new file mode 100644
index 0000000..6e25200
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
@@ -0,0 +1,95 @@
+/*
+ * 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 com.android.systemui.keyguard.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
+import com.android.systemui.keyguard.data.repository.LightRevealScrimRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.statusbar.LightRevealEffect
+import com.android.systemui.util.kotlin.sample
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.map
+
+@ExperimentalCoroutinesApi
+@SysUISingleton
+class LightRevealScrimInteractor
+@Inject
+constructor(
+ transitionRepository: KeyguardTransitionRepository,
+ transitionInteractor: KeyguardTransitionInteractor,
+ lightRevealScrimRepository: LightRevealScrimRepository,
+) {
+
+ /**
+ * Whenever a keyguard transition starts, sample the latest reveal effect from the repository
+ * and use that for the starting transition.
+ *
+ * We can't simply use the nextRevealEffect since the effect may change midway through a
+ * transition, but we don't want to change effects part way through. For example, if we're using
+ * a CircleReveal to animate a biometric unlock, but the biometric unlock mode changes to NONE
+ * from WAKE_AND_UNLOCK before the unlock animation ends, we don't want to end up switching to a
+ * LiftReveal.
+ */
+ val lightRevealEffect: Flow<LightRevealEffect> =
+ transitionInteractor.startedKeyguardTransitionStep.sample(
+ lightRevealScrimRepository.revealEffect
+ )
+
+ /**
+ * The reveal amount to use for the light reveal scrim, which is derived from the keyguard
+ * transition steps.
+ */
+ val revealAmount: Flow<Float> =
+ transitionRepository.transitions
+ // Only listen to transitions that change the reveal amount.
+ .filter { willTransitionAffectRevealAmount(it) }
+ // Use the transition amount as the reveal amount, inverting it if we're transitioning
+ // to a non-revealed (hidden) state.
+ .map { step -> if (willBeRevealedInState(step.to)) step.value else 1f - step.value }
+
+ companion object {
+
+ /**
+ * Whether the transition requires a change in the reveal amount of the light reveal scrim.
+ * If not, we don't care about the transition and don't need to listen to it.
+ */
+ fun willTransitionAffectRevealAmount(transition: TransitionStep): Boolean {
+ return willBeRevealedInState(transition.from) != willBeRevealedInState(transition.to)
+ }
+
+ /**
+ * Whether the light reveal scrim will be fully revealed (revealAmount = 1.0f) in the given
+ * state after the transition is complete. If false, scrim will be fully hidden.
+ */
+ fun willBeRevealedInState(state: KeyguardState): Boolean {
+ return when (state) {
+ KeyguardState.OFF -> false
+ KeyguardState.DOZING -> false
+ KeyguardState.AOD -> false
+ KeyguardState.DREAMING -> true
+ KeyguardState.BOUNCER -> true
+ KeyguardState.LOCKSCREEN -> true
+ KeyguardState.GONE -> true
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt
index 3bb8241..3218f96 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt
@@ -25,7 +25,7 @@
import com.android.systemui.keyguard.shared.model.StatusBarState.SHADE_LOCKED
import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.keyguard.shared.model.TransitionState
-import com.android.systemui.keyguard.shared.model.WakefulnessModel
+import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.util.kotlin.sample
import java.util.UUID
@@ -58,22 +58,26 @@
keyguardInteractor.isBouncerShowing
.sample(
combine(
- keyguardInteractor.wakefulnessState,
+ keyguardInteractor.wakefulnessModel,
keyguardTransitionInteractor.startedKeyguardTransitionStep,
- ) { a, b ->
- Pair(a, b)
- },
- { a, bc -> Triple(a, bc.first, bc.second) }
- )
- .collect { triple ->
- val (isBouncerShowing, wakefulnessState, lastStartedTransitionStep) = triple
+ ) { wakefulnessModel, transitionStep ->
+ Pair(wakefulnessModel, transitionStep)
+ }
+ ) { bouncerShowing, wakefulnessAndTransition ->
+ Triple(
+ bouncerShowing,
+ wakefulnessAndTransition.first,
+ wakefulnessAndTransition.second
+ )
+ }
+ .collect { (isBouncerShowing, wakefulnessState, lastStartedTransitionStep) ->
if (
!isBouncerShowing && lastStartedTransitionStep.to == KeyguardState.BOUNCER
) {
val to =
if (
- wakefulnessState == WakefulnessModel.STARTING_TO_SLEEP ||
- wakefulnessState == WakefulnessModel.ASLEEP
+ wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP ||
+ wakefulnessState.state == WakefulnessState.ASLEEP
) {
KeyguardState.AOD
} else {
@@ -100,14 +104,17 @@
combine(
keyguardTransitionInteractor.finishedKeyguardState,
keyguardInteractor.statusBarState,
- ) { a, b ->
- Pair(a, b)
- },
- { a, bc -> Triple(a, bc.first, bc.second) }
- )
- .collect { triple ->
- val (shadeModel, keyguardState, statusBarState) = triple
-
+ ) { finishedKeyguardState, statusBarState ->
+ Pair(finishedKeyguardState, statusBarState)
+ }
+ ) { shadeModel, keyguardStateAndStatusBarState ->
+ Triple(
+ shadeModel,
+ keyguardStateAndStatusBarState.first,
+ keyguardStateAndStatusBarState.second
+ )
+ }
+ .collect { (shadeModel, keyguardState, statusBarState) ->
val id = transitionId
if (id != null) {
// An existing `id` means a transition is started, and calls to
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenGoneTransitionInteractor.kt
index 4100f7a..95d9602 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenGoneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenGoneTransitionInteractor.kt
@@ -37,15 +37,15 @@
private val keyguardInteractor: KeyguardInteractor,
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val keyguardTransitionRepository: KeyguardTransitionRepository,
-) : TransitionInteractor("LOCKSCREEN->GONE") {
+) : TransitionInteractor(LockscreenGoneTransitionInteractor::class.simpleName!!) {
override fun start() {
scope.launch {
keyguardInteractor.isKeyguardGoingAway
- .sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
+ .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
.collect { pair ->
- val (isKeyguardGoingAway, keyguardState) = pair
- if (!isKeyguardGoingAway && keyguardState == KeyguardState.LOCKSCREEN) {
+ val (isKeyguardGoingAway, lastStartedStep) = pair
+ if (isKeyguardGoingAway && lastStartedStep.to == KeyguardState.LOCKSCREEN) {
keyguardTransitionRepository.startTransition(
TransitionInfo(
name,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt
index dbffeab..5f63ae7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StartKeyguardTransitionModule.kt
@@ -52,13 +52,5 @@
@IntoSet
abstract fun lockscreenGone(impl: LockscreenGoneTransitionInteractor): TransitionInteractor
- @Binds
- @IntoSet
- abstract fun dreamingLockscreen(
- impl: DreamingLockscreenTransitionInteractor
- ): TransitionInteractor
-
- @Binds
- @IntoSet
- abstract fun dreamingToAod(impl: DreamingToAodTransitionInteractor): TransitionInteractor
+ @Binds @IntoSet abstract fun dreaming(impl: DreamingTransitionInteractor): TransitionInteractor
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
index a2a46d9..08ad3d5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/TransitionInteractor.kt
@@ -29,4 +29,6 @@
sealed class TransitionInteractor(val name: String) {
abstract fun start()
+
+ fun <A, B, C> toTriple(a: A, bc: Pair<B, C>) = Triple(a, bc.first, bc.second)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockModel.kt
index db709b4..8fe6309f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockModel.kt
@@ -46,5 +46,14 @@
/** When bouncer is visible and will be dismissed. */
DISMISS_BOUNCER,
/** Mode in which fingerprint wakes and unlocks the device from a dream. */
- WAKE_AND_UNLOCK_FROM_DREAM,
+ WAKE_AND_UNLOCK_FROM_DREAM;
+
+ companion object {
+ private val wakeAndUnlockModes =
+ setOf(WAKE_AND_UNLOCK, WAKE_AND_UNLOCK_FROM_DREAM, WAKE_AND_UNLOCK_PULSING)
+
+ fun isWakeAndUnlock(model: BiometricUnlockModel): Boolean {
+ return wakeAndUnlockModes.contains(model)
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockSource.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockSource.kt
new file mode 100644
index 0000000..b403416
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockSource.kt
@@ -0,0 +1,39 @@
+/*
+ * 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 com.android.systemui.keyguard.shared.model
+
+import android.hardware.biometrics.BiometricSourceType
+
+/** Biometric unlock sensor sources, which we use to play sensor-specific animations. */
+enum class BiometricUnlockSource {
+ /** The unlock was initiated by a fingerprint sensor authentication. */
+ FINGERPRINT_SENSOR,
+
+ /** The unlock was initiated by the front-facing camera or a nearby sensor. */
+ FACE_SENSOR;
+
+ companion object {
+ fun fromBiometricSourceType(type: BiometricSourceType?): BiometricUnlockSource? {
+ return when (type) {
+ BiometricSourceType.FINGERPRINT -> FINGERPRINT_SENSOR
+ BiometricSourceType.FACE -> FACE_SENSOR
+ BiometricSourceType.IRIS -> FACE_SENSOR
+ else -> null
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DozeStateModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DozeStateModel.kt
index 7039188..65b7cf7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DozeStateModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DozeStateModel.kt
@@ -42,5 +42,11 @@
/** AOD, prox is near, transitions to DOZE_AOD_PAUSED after a timeout. */
DOZE_AOD_PAUSING,
/** Always-on doze. Device is awake, showing docking UI and listening for pulse triggers. */
- DOZE_AOD_DOCKED
+ DOZE_AOD_DOCKED;
+
+ companion object {
+ fun isDozeOff(model: DozeStateModel): Boolean {
+ return model == UNINITIALIZED || model == FINISH
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakeSleepReason.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakeSleepReason.kt
new file mode 100644
index 0000000..b32597d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakeSleepReason.kt
@@ -0,0 +1,44 @@
+/*
+ * 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 com.android.systemui.keyguard.shared.model
+
+import android.os.PowerManager
+
+/** The reason we're waking up or going to sleep, such as pressing the power button. */
+enum class WakeSleepReason {
+ /** The physical power button was pressed to wake up or sleep the device. */
+ POWER_BUTTON,
+
+ /** Something else happened to wake up or sleep the device. */
+ OTHER;
+
+ companion object {
+ fun fromPowerManagerWakeReason(reason: Int): WakeSleepReason {
+ return when (reason) {
+ PowerManager.WAKE_REASON_POWER_BUTTON -> POWER_BUTTON
+ else -> OTHER
+ }
+ }
+
+ fun fromPowerManagerSleepReason(reason: Int): WakeSleepReason {
+ return when (reason) {
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON -> POWER_BUTTON
+ else -> OTHER
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt
index 92040f4..03dee00 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt
@@ -15,24 +15,34 @@
*/
package com.android.systemui.keyguard.shared.model
-/** Model device wakefulness states. */
-enum class WakefulnessModel {
- /** The device is asleep and not interactive. */
- ASLEEP,
- /** Received a signal that the device is beginning to wake up. */
- STARTING_TO_WAKE,
- /** Device is now fully awake and interactive. */
- AWAKE,
- /** Signal that the device is now going to sleep. */
- STARTING_TO_SLEEP;
+import com.android.systemui.keyguard.WakefulnessLifecycle
+/** Model device wakefulness states. */
+data class WakefulnessModel(
+ val state: WakefulnessState,
+ val isWakingUpOrAwake: Boolean,
+ val lastWakeReason: WakeSleepReason,
+ val lastSleepReason: WakeSleepReason,
+) {
companion object {
fun isSleepingOrStartingToSleep(model: WakefulnessModel): Boolean {
- return model == ASLEEP || model == STARTING_TO_SLEEP
+ return model.state == WakefulnessState.ASLEEP ||
+ model.state == WakefulnessState.STARTING_TO_SLEEP
}
fun isWakingOrStartingToWake(model: WakefulnessModel): Boolean {
- return model == AWAKE || model == STARTING_TO_WAKE
+ return model.state == WakefulnessState.AWAKE ||
+ model.state == WakefulnessState.STARTING_TO_WAKE
+ }
+
+ fun fromWakefulnessLifecycle(wakefulnessLifecycle: WakefulnessLifecycle): WakefulnessModel {
+ return WakefulnessModel(
+ WakefulnessState.fromWakefulnessLifecycleInt(wakefulnessLifecycle.wakefulness),
+ wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_WAKING ||
+ wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_AWAKE,
+ WakeSleepReason.fromPowerManagerWakeReason(wakefulnessLifecycle.lastWakeReason),
+ WakeSleepReason.fromPowerManagerSleepReason(wakefulnessLifecycle.lastSleepReason),
+ )
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessState.kt
new file mode 100644
index 0000000..6791d88
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessState.kt
@@ -0,0 +1,44 @@
+/*
+ * 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 com.android.systemui.keyguard.shared.model
+
+import com.android.systemui.keyguard.WakefulnessLifecycle
+
+enum class WakefulnessState {
+ /** The device is asleep and not interactive. */
+ ASLEEP,
+ /** Received a signal that the device is beginning to wake up. */
+ STARTING_TO_WAKE,
+ /** Device is now fully awake and interactive. */
+ AWAKE,
+ /** Signal that the device is now going to sleep. */
+ STARTING_TO_SLEEP;
+
+ companion object {
+ fun fromWakefulnessLifecycleInt(
+ @WakefulnessLifecycle.Wakefulness value: Int
+ ): WakefulnessState {
+ return when (value) {
+ WakefulnessLifecycle.WAKEFULNESS_ASLEEP -> ASLEEP
+ WakefulnessLifecycle.WAKEFULNESS_WAKING -> STARTING_TO_WAKE
+ WakefulnessLifecycle.WAKEFULNESS_AWAKE -> AWAKE
+ WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP -> STARTING_TO_SLEEP
+ else -> throw IllegalArgumentException("Invalid Wakefulness value: $value")
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt
new file mode 100644
index 0000000..f1da882
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt
@@ -0,0 +1,43 @@
+/*
+ * 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 com.android.systemui.keyguard.ui.binder
+
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.statusbar.LightRevealScrim
+import kotlinx.coroutines.launch
+
+object LightRevealScrimViewBinder {
+ @JvmStatic
+ fun bind(revealScrim: LightRevealScrim, viewModel: LightRevealScrimViewModel) {
+ revealScrim.repeatWhenAttached {
+ repeatOnLifecycle(Lifecycle.State.CREATED) {
+ launch {
+ viewModel.revealAmount.collect { amount -> revealScrim.revealAmount = amount }
+ }
+
+ launch {
+ viewModel.lightRevealEffect.collect { effect ->
+ revealScrim.revealEffect = effect
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt
new file mode 100644
index 0000000..a46d441
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt
@@ -0,0 +1,31 @@
+/*
+ * 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 com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.domain.interactor.LightRevealScrimInteractor
+import com.android.systemui.statusbar.LightRevealEffect
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * Models UI state for the light reveal scrim, which is used during screen on and off animations to
+ * draw a gradient that reveals/hides the contents of the screen.
+ */
+class LightRevealScrimViewModel @Inject constructor(interactor: LightRevealScrimInteractor) {
+ val lightRevealEffect: Flow<LightRevealEffect> = interactor.lightRevealEffect
+ val revealAmount: Flow<Float> = interactor.revealAmount
+}
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 8aaee81..1fdbc99 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
@@ -184,6 +184,7 @@
private val configListener =
object : ConfigurationController.ConfigurationListener {
+
override fun onDensityOrFontScaleChanged() {
// System font changes should only happen when UMO is offscreen or a flicker may
// occur
@@ -199,6 +200,7 @@
override fun onConfigChanged(newConfig: Configuration?) {
if (newConfig == null) return
isRtl = newConfig.layoutDirection == View.LAYOUT_DIRECTION_RTL
+ updatePlayers(recreateMedia = true)
}
override fun onUiModeChanged() {
@@ -635,7 +637,7 @@
val existingSmartspaceMediaKey = MediaPlayerData.smartspaceMediaKey()
existingSmartspaceMediaKey?.let {
val removedPlayer =
- MediaPlayerData.removeMediaPlayer(existingSmartspaceMediaKey, true)
+ removePlayer(existingSmartspaceMediaKey, dismissMediaData = false)
removedPlayer?.run {
debugLogger.logPotentialMemoryLeak(existingSmartspaceMediaKey)
}
@@ -685,7 +687,7 @@
key: String,
dismissMediaData: Boolean = true,
dismissRecommendation: Boolean = true
- ) {
+ ): MediaControlPanel? {
if (key == MediaPlayerData.smartspaceMediaKey()) {
MediaPlayerData.smartspaceMediaData?.let {
logger.logRecommendationRemoved(it.packageName, it.instanceId)
@@ -693,7 +695,7 @@
}
val removed =
MediaPlayerData.removeMediaPlayer(key, dismissMediaData || dismissRecommendation)
- removed?.apply {
+ return removed?.apply {
mediaCarouselScrollHandler.onPrePlayerRemoved(removed)
mediaContent.removeView(removed.mediaViewHolder?.player)
mediaContent.removeView(removed.recommendationViewHolder?.recommendations)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
index 21e64e2..827ac78 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
@@ -458,7 +458,9 @@
if (mMediaViewHolder == null) {
return;
}
- Trace.beginSection("MediaControlPanel#bindPlayer<" + key + ">");
+ if (Trace.isEnabled()) {
+ Trace.traceBegin(Trace.TRACE_TAG_APP, "MediaControlPanel#bindPlayer<" + key + ">");
+ }
mKey = key;
mMediaData = data;
MediaSession.Token token = data.getToken();
@@ -1179,8 +1181,10 @@
return;
}
- Trace.beginSection(
- "MediaControlPanel#bindRecommendation<" + data.getPackageName() + ">");
+ if (Trace.isEnabled()) {
+ Trace.traceBegin(Trace.TRACE_TAG_APP,
+ "MediaControlPanel#bindRecommendation<" + data.getPackageName() + ">");
+ }
mRecommendationData = data;
mSmartspaceId = SmallHash.hash(data.getTargetId());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
index bb2b441..3c10778 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
@@ -18,6 +18,9 @@
import android.app.IActivityManager
import android.app.IForegroundServiceObserver
+import android.app.job.IUserVisibleJobObserver
+import android.app.job.JobScheduler
+import android.app.job.UserVisibleJobSummary
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
@@ -47,6 +50,7 @@
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_FOOTER_DOT
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.Dumpable
import com.android.systemui.R
@@ -92,6 +96,8 @@
*/
val showFooterDot: StateFlow<Boolean>
+ val includesUserVisibleJobs: Boolean
+
/**
* Initialize this controller. This should be called once, before this controller is used for
* the first time.
@@ -141,19 +147,21 @@
@Background private val backgroundExecutor: Executor,
private val systemClock: SystemClock,
private val activityManager: IActivityManager,
+ private val jobScheduler: JobScheduler,
private val packageManager: PackageManager,
private val userTracker: UserTracker,
private val deviceConfigProxy: DeviceConfigProxy,
private val dialogLaunchAnimator: DialogLaunchAnimator,
private val broadcastDispatcher: BroadcastDispatcher,
private val dumpManager: DumpManager
-) : IForegroundServiceObserver.Stub(), Dumpable, FgsManagerController {
+) : Dumpable, FgsManagerController {
companion object {
private const val INTERACTION_JANK_TAG = "active_background_apps"
private const val DEFAULT_TASK_MANAGER_ENABLED = true
private const val DEFAULT_TASK_MANAGER_SHOW_FOOTER_DOT = false
private const val DEFAULT_TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS = true
+ private const val DEFAULT_TASK_MANAGER_SHOW_USER_VISIBLE_JOBS = false
}
override var newChangesSinceDialogWasDismissed = false
@@ -167,6 +175,11 @@
private var showStopBtnForUserAllowlistedApps = false
+ private var showUserVisibleJobs = DEFAULT_TASK_MANAGER_SHOW_USER_VISIBLE_JOBS
+
+ override val includesUserVisibleJobs: Boolean
+ get() = showUserVisibleJobs
+
override val numRunningPackages: Int
get() {
synchronized(lock) {
@@ -186,7 +199,7 @@
private var currentProfileIds = mutableSetOf<Int>()
@GuardedBy("lock")
- private val runningServiceTokens = mutableMapOf<UserPackage, StartTimeAndTokens>()
+ private val runningTaskIdentifiers = mutableMapOf<UserPackage, StartTimeAndIdentifiers>()
@GuardedBy("lock")
private var dialog: SystemUIDialog? = null
@@ -210,13 +223,29 @@
}
}
+ private val foregroundServiceObserver = ForegroundServiceObserver()
+
+ private val userVisibleJobObserver = UserVisibleJobObserver()
+
override fun init() {
synchronized(lock) {
if (initialized) {
return
}
+
+ showUserVisibleJobs = deviceConfigProxy.getBoolean(
+ NAMESPACE_SYSTEMUI,
+ TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, DEFAULT_TASK_MANAGER_SHOW_USER_VISIBLE_JOBS)
+
try {
- activityManager.registerForegroundServiceObserver(this)
+ activityManager.registerForegroundServiceObserver(foregroundServiceObserver)
+ // Clumping FGS and user-visible jobs here and showing a single entry and button
+ // for them is the easiest way to get user-visible jobs showing in Task Manager.
+ // Ideally, we would have dedicated UI in task manager for the user-visible jobs.
+ // TODO(255768978): distinguish jobs from FGS and give users more control
+ if (showUserVisibleJobs) {
+ jobScheduler.registerUserVisibleJobObserver(userVisibleJobObserver)
+ }
} catch (e: RemoteException) {
e.rethrowFromSystemServer()
}
@@ -235,6 +264,12 @@
showStopBtnForUserAllowlistedApps = it.getBoolean(
TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
showStopBtnForUserAllowlistedApps)
+ var wasShowingUserVisibleJobs = showUserVisibleJobs
+ showUserVisibleJobs = it.getBoolean(
+ TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, showUserVisibleJobs)
+ if (showUserVisibleJobs != wasShowingUserVisibleJobs) {
+ onShowUserVisibleJobsFlagChanged()
+ }
}
_isAvailable.value = deviceConfigProxy.getBoolean(
@@ -269,32 +304,6 @@
}
}
- override fun onForegroundStateChanged(
- token: IBinder,
- packageName: String,
- userId: Int,
- isForeground: Boolean
- ) {
- synchronized(lock) {
- val userPackageKey = UserPackage(userId, packageName)
- if (isForeground) {
- runningServiceTokens.getOrPut(userPackageKey) { StartTimeAndTokens(systemClock) }
- .addToken(token)
- } else {
- if (runningServiceTokens[userPackageKey]?.also {
- it.removeToken(token)
- }?.isEmpty() == true
- ) {
- runningServiceTokens.remove(userPackageKey)
- }
- }
-
- updateNumberOfVisibleRunningPackagesLocked()
-
- updateAppItemsLocked()
- }
- }
-
@GuardedBy("lock")
private val onNumberOfPackagesChangedListeners =
mutableSetOf<FgsManagerController.OnNumberOfPackagesChangedListener>()
@@ -336,7 +345,7 @@
}
private fun getNumVisiblePackagesLocked(): Int {
- return runningServiceTokens.keys.count {
+ return runningTaskIdentifiers.keys.count {
it.uiControl != UIControl.HIDE_ENTRY && currentProfileIds.contains(it.userId)
}
}
@@ -361,7 +370,7 @@
}
private fun getNumVisibleButtonsLocked(): Int {
- return runningServiceTokens.keys.count {
+ return runningTaskIdentifiers.keys.count {
it.uiControl != UIControl.HIDE_BUTTON && currentProfileIds.contains(it.userId)
}
}
@@ -372,7 +381,7 @@
synchronized(lock) {
if (dialog == null) {
- runningServiceTokens.keys.forEach {
+ runningTaskIdentifiers.keys.forEach {
it.updateUiControl()
}
@@ -434,17 +443,17 @@
return
}
- val addedPackages = runningServiceTokens.keys.filter {
+ val addedPackages = runningTaskIdentifiers.keys.filter {
currentProfileIds.contains(it.userId) &&
it.uiControl != UIControl.HIDE_ENTRY && runningApps[it]?.stopped != true
}
- val removedPackages = runningApps.keys.filter { !runningServiceTokens.containsKey(it) }
+ val removedPackages = runningApps.keys.filter { !runningTaskIdentifiers.containsKey(it) }
addedPackages.forEach {
val ai = packageManager.getApplicationInfoAsUser(it.packageName, 0, it.userId)
runningApps[it] = RunningApp(
it.userId, it.packageName,
- runningServiceTokens[it]!!.startTime, it.uiControl,
+ runningTaskIdentifiers[it]!!.startTime, it.uiControl,
packageManager.getApplicationLabel(ai),
packageManager.getUserBadgedIcon(
packageManager.getApplicationIcon(ai), UserHandle.of(it.userId)
@@ -471,7 +480,41 @@
private fun stopPackage(userId: Int, packageName: String, timeStarted: Long) {
logEvent(stopped = true, packageName, userId, timeStarted)
- activityManager.stopAppForUser(packageName, userId)
+ val userPackageKey = UserPackage(userId, packageName)
+ if (showUserVisibleJobs &&
+ runningTaskIdentifiers[userPackageKey]?.hasRunningJobs() == true) {
+ // TODO(255768978): allow fine-grained job control
+ jobScheduler.stopUserVisibleJobsForUser(packageName, userId)
+ }
+ if (runningTaskIdentifiers[userPackageKey]?.hasFgs() == true) {
+ activityManager.stopAppForUser(packageName, userId)
+ }
+ }
+
+ private fun onShowUserVisibleJobsFlagChanged() {
+ if (showUserVisibleJobs) {
+ jobScheduler.registerUserVisibleJobObserver(userVisibleJobObserver)
+ } else {
+ jobScheduler.unregisterUserVisibleJobObserver(userVisibleJobObserver)
+
+ synchronized(lock) {
+ for ((userPackage, startTimeAndIdentifiers) in runningTaskIdentifiers) {
+ if (startTimeAndIdentifiers.hasFgs()) {
+ // The app still has FGS running, so all we need to do is remove
+ // the job summaries
+ startTimeAndIdentifiers.clearJobSummaries()
+ } else {
+ // The app only has user-visible jobs running, so remove it from
+ // the map altogether
+ runningTaskIdentifiers.remove(userPackage)
+ }
+ }
+
+ updateNumberOfVisibleRunningPackagesLocked()
+
+ updateAppItemsLocked()
+ }
+ }
}
private fun logEvent(stopped: Boolean, packageName: String, userId: Int, timeStarted: Long) {
@@ -564,6 +607,62 @@
}
}
+ private inner class ForegroundServiceObserver : IForegroundServiceObserver.Stub() {
+ override fun onForegroundStateChanged(
+ token: IBinder,
+ packageName: String,
+ userId: Int,
+ isForeground: Boolean
+ ) {
+ synchronized(lock) {
+ val userPackageKey = UserPackage(userId, packageName)
+ if (isForeground) {
+ runningTaskIdentifiers
+ .getOrPut(userPackageKey) { StartTimeAndIdentifiers(systemClock) }
+ .addFgsToken(token)
+ } else {
+ if (runningTaskIdentifiers[userPackageKey]?.also {
+ it.removeFgsToken(token)
+ }?.isEmpty() == true
+ ) {
+ runningTaskIdentifiers.remove(userPackageKey)
+ }
+ }
+
+ updateNumberOfVisibleRunningPackagesLocked()
+
+ updateAppItemsLocked()
+ }
+ }
+ }
+
+ private inner class UserVisibleJobObserver : IUserVisibleJobObserver.Stub() {
+ override fun onUserVisibleJobStateChanged(
+ summary: UserVisibleJobSummary,
+ isRunning: Boolean
+ ) {
+ synchronized(lock) {
+ val userPackageKey = UserPackage(summary.sourceUserId, summary.sourcePackageName)
+ if (isRunning) {
+ runningTaskIdentifiers
+ .getOrPut(userPackageKey) { StartTimeAndIdentifiers(systemClock) }
+ .addJobSummary(summary)
+ } else {
+ if (runningTaskIdentifiers[userPackageKey]?.also {
+ it.removeJobSummary(summary)
+ }?.isEmpty() == true
+ ) {
+ runningTaskIdentifiers.remove(userPackageKey)
+ }
+ }
+
+ updateNumberOfVisibleRunningPackagesLocked()
+
+ updateAppItemsLocked()
+ }
+ }
+ }
+
private inner class UserPackage(
val userId: Int,
val packageName: String
@@ -630,37 +729,64 @@
}
}
- private data class StartTimeAndTokens(
+ private data class StartTimeAndIdentifiers(
val systemClock: SystemClock
) {
val startTime = systemClock.elapsedRealtime()
- val tokens = mutableSetOf<IBinder>()
+ val fgsTokens = mutableSetOf<IBinder>()
+ val jobSummaries = mutableSetOf<UserVisibleJobSummary>()
- fun addToken(token: IBinder) {
- tokens.add(token)
+ fun addJobSummary(summary: UserVisibleJobSummary) {
+ jobSummaries.add(summary)
}
- fun removeToken(token: IBinder) {
- tokens.remove(token)
+ fun clearJobSummaries() {
+ jobSummaries.clear()
+ }
+
+ fun removeJobSummary(summary: UserVisibleJobSummary) {
+ jobSummaries.remove(summary)
+ }
+
+ fun addFgsToken(token: IBinder) {
+ fgsTokens.add(token)
+ }
+
+ fun removeFgsToken(token: IBinder) {
+ fgsTokens.remove(token)
+ }
+
+ fun hasFgs(): Boolean {
+ return !fgsTokens.isEmpty()
+ }
+
+ fun hasRunningJobs(): Boolean {
+ return !jobSummaries.isEmpty()
}
fun isEmpty(): Boolean {
- return tokens.isEmpty()
+ return fgsTokens.isEmpty() && jobSummaries.isEmpty()
}
fun dump(pw: PrintWriter) {
- pw.println("StartTimeAndTokens: [")
+ pw.println("StartTimeAndIdentifiers: [")
pw.indentIfPossible {
pw.println(
"startTime=$startTime (time running =" +
" ${systemClock.elapsedRealtime() - startTime}ms)"
)
- pw.println("tokens: [")
+ pw.println("fgs tokens: [")
pw.indentIfPossible {
- for (token in tokens) {
+ for (token in fgsTokens) {
pw.println("$token")
}
}
+ pw.println("job summaries: [")
+ pw.indentIfPossible {
+ for (summary in jobSummaries) {
+ pw.println("$summary")
+ }
+ }
pw.println("]")
}
pw.println("]")
@@ -724,13 +850,13 @@
synchronized(lock) {
pw.println("current user profiles = $currentProfileIds")
pw.println("newChangesSinceDialogWasShown=$newChangesSinceDialogWasDismissed")
- pw.println("Running service tokens: [")
+ pw.println("Running task identifiers: [")
pw.indentIfPossible {
- runningServiceTokens.forEach { (userPackage, startTimeAndTokens) ->
+ runningTaskIdentifiers.forEach { (userPackage, startTimeAndIdentifiers) ->
pw.println("{")
pw.indentIfPossible {
userPackage.dump(pw)
- startTimeAndTokens.dump(pw)
+ startTimeAndIdentifiers.dump(pw)
}
pw.println("}")
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index ae2d2e0..6f71b72 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -200,7 +200,6 @@
import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
-import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -4587,55 +4586,6 @@
return new TouchHandler();
}
- private final PhoneStatusBarView.TouchEventHandler mStatusBarViewTouchEventHandler =
- new PhoneStatusBarView.TouchEventHandler() {
- @Override
- public void onInterceptTouchEvent(MotionEvent event) {
- mCentralSurfaces.onTouchEvent(event);
- }
-
- @Override
- public boolean handleTouchEvent(MotionEvent event) {
- mCentralSurfaces.onTouchEvent(event);
-
- // TODO(b/202981994): Move the touch debugging in this method to a central
- // location. (Right now, it's split between CentralSurfaces and here.)
-
- // If panels aren't enabled, ignore the gesture and don't pass it down to the
- // panel view.
- if (!mCommandQueue.panelsEnabled()) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- Log.v(
- TAG,
- String.format(
- "onTouchForwardedFromStatusBar: "
- + "panel disabled, ignoring touch at (%d,%d)",
- (int) event.getX(),
- (int) event.getY()
- )
- );
- }
- return false;
- }
-
- // If the view that would receive the touch is disabled, just have status bar
- // eat the gesture.
- if (event.getAction() == MotionEvent.ACTION_DOWN && !mView.isEnabled()) {
- Log.v(TAG,
- String.format(
- "onTouchForwardedFromStatusBar: "
- + "panel view disabled, eating touch at (%d,%d)",
- (int) event.getX(),
- (int) event.getY()
- )
- );
- return true;
- }
-
- return mView.dispatchTouchEvent(event);
- }
- };
-
public NotificationStackScrollLayoutController getNotificationStackScrollLayoutController() {
return mNotificationStackScrollLayoutController;
}
@@ -5238,6 +5188,11 @@
}
/** */
+ public boolean sendTouchEventToView(MotionEvent event) {
+ return mView.dispatchTouchEvent(event);
+ }
+
+ /** */
public void requestLayoutOnView() {
mView.requestLayout();
}
@@ -5247,6 +5202,11 @@
ViewGroupFadeHelper.reset(mView);
}
+ /** */
+ public boolean isViewEnabled() {
+ return mView.isEnabled();
+ }
+
private void beginJankMonitoring() {
if (mInteractionJankMonitor == null) {
return;
@@ -5796,11 +5756,6 @@
mCurrentPanelState = state;
}
- /** Returns the handler that the status bar should forward touches to. */
- public PhoneStatusBarView.TouchEventHandler getStatusBarTouchEventHandler() {
- return mStatusBarViewTouchEventHandler;
- }
-
@VisibleForTesting
StatusBarStateController getStatusBarStateController() {
return mStatusBarStateController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
index 3d161d9..24c66eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
@@ -17,9 +17,12 @@
package com.android.systemui.statusbar;
import android.annotation.ColorInt;
+import android.annotation.DrawableRes;
import android.annotation.StringRes;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.content.res.Configuration;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
@@ -33,16 +36,30 @@
public class EmptyShadeView extends StackScrollerDecorView {
private TextView mEmptyText;
+ private TextView mEmptyFooterText;
+
private @StringRes int mText = R.string.empty_shade_text;
+ private @DrawableRes int mFooterIcon = R.drawable.ic_friction_lock_closed;
+ private @StringRes int mFooterText = R.string.unlock_to_see_notif_text;
+ private @Visibility int mFooterVisibility = View.GONE;
+ private int mSize;
+
public EmptyShadeView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mSize = getResources().getDimensionPixelSize(
+ R.dimen.notifications_unseen_footer_icon_size);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
+ mSize = getResources().getDimensionPixelSize(
+ R.dimen.notifications_unseen_footer_icon_size);
mEmptyText.setText(mText);
+ mEmptyFooterText.setVisibility(mFooterVisibility);
+ setFooterText(mFooterText);
+ setFooterIcon(mFooterIcon);
}
@Override
@@ -52,11 +69,13 @@
@Override
protected View findSecondaryView() {
- return null;
+ return findViewById(R.id.no_notifications_footer);
}
public void setTextColor(@ColorInt int color) {
mEmptyText.setTextColor(color);
+ mEmptyFooterText.setTextColor(color);
+ mEmptyFooterText.setCompoundDrawableTintList(ColorStateList.valueOf(color));
}
public void setText(@StringRes int text) {
@@ -64,14 +83,53 @@
mEmptyText.setText(mText);
}
+ public void setFooterVisibility(@Visibility int visibility) {
+ mFooterVisibility = visibility;
+ setSecondaryVisible(visibility == View.VISIBLE, false);
+ }
+
+ public void setFooterText(@StringRes int text) {
+ mFooterText = text;
+ if (text != 0) {
+ mEmptyFooterText.setText(mFooterText);
+ } else {
+ mEmptyFooterText.setText(null);
+ }
+ }
+
+ public void setFooterIcon(@DrawableRes int icon) {
+ mFooterIcon = icon;
+ Drawable drawable;
+ if (icon == 0) {
+ drawable = null;
+ } else {
+ drawable = getResources().getDrawable(icon);
+ drawable.setBounds(0, 0, mSize, mSize);
+ }
+ mEmptyFooterText.setCompoundDrawablesRelative(drawable, null, null, null);
+ }
+
+ @StringRes
public int getTextResource() {
return mText;
}
+ @StringRes
+ public int getFooterTextResource() {
+ return mFooterText;
+ }
+
+ @DrawableRes
+ public int getFooterIconResource() {
+ return mFooterIcon;
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mEmptyText = (TextView) findContentView();
+ mEmptyFooterText = (TextView) findSecondaryView();
+ mEmptyFooterText.setCompoundDrawableTintList(mEmptyFooterText.getTextColors());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
index 6e5fceb..9da94ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt
@@ -28,6 +28,7 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider
+import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProviderImpl
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
@@ -49,6 +50,7 @@
private val notifPipelineFlags: NotifPipelineFlags,
@Application private val scope: CoroutineScope,
private val sectionHeaderVisibilityProvider: SectionHeaderVisibilityProvider,
+ private val seenNotifsProvider: SeenNotificationsProviderImpl,
private val statusBarStateController: StatusBarStateController,
) : Coordinator {
@@ -105,6 +107,9 @@
@VisibleForTesting
internal val unseenNotifFilter =
object : NotifFilter("$TAG-unseen") {
+
+ var hasFilteredAnyNotifs = false
+
override fun shouldFilterOut(entry: NotificationEntry, now: Long): Boolean =
when {
// Don't apply filter if the keyguard isn't currently showing
@@ -115,7 +120,12 @@
// - summary will be pruned if necessary, depending on if children are filtered
entry.parent?.summary == entry -> false
else -> true
- }
+ }.also { hasFiltered -> hasFilteredAnyNotifs = hasFilteredAnyNotifs || hasFiltered }
+
+ override fun onCleanup() {
+ seenNotifsProvider.hasFilteredOutSeenNotifications = hasFilteredAnyNotifs
+ hasFilteredAnyNotifs = false
+ }
}
private val notifFilter: NotifFilter =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
index 966ab4c..afdadeb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
@@ -51,7 +51,9 @@
*/
public final void invalidateList(@Nullable String reason) {
if (mListener != null) {
- Trace.beginSection("Pluggable<" + mName + ">.invalidateList");
+ if (Trace.isEnabled()) {
+ Trace.traceBegin(Trace.TRACE_TAG_APP, "Pluggable<" + mName + ">.invalidateList");
+ }
mListener.onPluggableInvalidated((This) this, reason);
Trace.endSection();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SeenNotificationsProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SeenNotificationsProvider.kt
new file mode 100644
index 0000000..cff47e2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SeenNotificationsProvider.kt
@@ -0,0 +1,41 @@
+/*
+ * 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 com.android.systemui.statusbar.notification.collection.provider
+
+import com.android.systemui.dagger.SysUISingleton
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
+
+/** Keeps track of whether "seen" notification content has been filtered out of the shade. */
+interface SeenNotificationsProvider {
+ /** Are any already-seen notifications currently filtered out of the shade? */
+ val hasFilteredOutSeenNotifications: Boolean
+}
+
+@Module
+interface SeenNotificationsProviderModule {
+ @Binds
+ fun bindSeenNotificationsProvider(
+ impl: SeenNotificationsProviderImpl
+ ): SeenNotificationsProvider
+}
+
+@SysUISingleton
+class SeenNotificationsProviderImpl @Inject constructor() : SeenNotificationsProvider {
+ override var hasFilteredOutSeenNotifications: Boolean = false
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index a7b7a23..808638a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -52,6 +52,7 @@
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.collection.provider.NotificationVisibilityProviderImpl;
+import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProviderModule;
import com.android.systemui.statusbar.notification.collection.provider.VisibilityLocationProviderDelegator;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl;
@@ -96,6 +97,7 @@
@Module(includes = {
CoordinatorsModule.class,
KeyguardNotificationVisibilityProviderModule.class,
+ SeenNotificationsProviderModule.class,
ShadeEventsModule.class,
NotifPipelineChoreographerModule.class,
NotificationSectionHeadersModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 1eccc98..d7d5ac9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -19,6 +19,7 @@
import static android.app.Notification.Action.SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY;
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
+import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.PARENT_DISMISSED;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
import android.animation.Animator;
@@ -1404,6 +1405,11 @@
mKeepInParentForDismissAnimation = keepInParent;
}
+ /** @return true if the User has dismissed this notif's parent */
+ public boolean isParentDismissed() {
+ return getEntry().getDismissState() == PARENT_DISMISSED;
+ }
+
@Override
public boolean isRemoved() {
return mRemoved;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index f9e9a2d..8a400d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -359,10 +359,15 @@
@Override
public boolean offerToKeepInParentForAnimation() {
- if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_DISMISSAL_ANIMATION)) {
+ //If the User dismissed the notification's parent, we want to keep it attached until the
+ //dismiss animation is ongoing. Therefore we don't want to remove it in the ShadeViewDiffer.
+ if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_DISMISSAL_ANIMATION)
+ && mView.isParentDismissed()) {
mView.setKeepInParentForDismissAnimation(true);
return true;
}
+
+ //Otherwise the view system doesn't do the removal, so we rely on the ShadeViewDiffer
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index b519aef..7c3e52c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -32,10 +32,12 @@
import android.animation.TimeAnimator;
import android.animation.ValueAnimator;
import android.annotation.ColorInt;
+import android.annotation.DrawableRes;
import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
@@ -4556,7 +4558,7 @@
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- void setEmptyShadeView(EmptyShadeView emptyShadeView) {
+ public void setEmptyShadeView(EmptyShadeView emptyShadeView) {
int index = -1;
if (mEmptyShadeView != null) {
index = indexOfChild(mEmptyShadeView);
@@ -4567,15 +4569,43 @@
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- void updateEmptyShadeView(boolean visible, boolean areNotificationsHiddenInShade) {
+ void updateEmptyShadeView(
+ boolean visible, boolean areNotificationsHiddenInShade, boolean areSeenNotifsFiltered) {
mEmptyShadeView.setVisible(visible, mIsExpanded && mAnimationsEnabled);
+ if (areNotificationsHiddenInShade) {
+ updateEmptyShadeView(R.string.dnd_suppressing_shade_text, 0, 0);
+ } else if (areSeenNotifsFiltered) {
+ updateEmptyShadeView(
+ R.string.no_unseen_notif_text,
+ R.string.unlock_to_see_notif_text,
+ R.drawable.ic_friction_lock_closed);
+ } else {
+ updateEmptyShadeView(R.string.empty_shade_text, 0, 0);
+ }
+ }
+
+ private void updateEmptyShadeView(
+ @StringRes int newTextRes,
+ @StringRes int newFooterTextRes,
+ @DrawableRes int newFooterIconRes) {
int oldTextRes = mEmptyShadeView.getTextResource();
- int newTextRes = areNotificationsHiddenInShade
- ? R.string.dnd_suppressing_shade_text : R.string.empty_shade_text;
if (oldTextRes != newTextRes) {
mEmptyShadeView.setText(newTextRes);
}
+ int oldFooterTextRes = mEmptyShadeView.getFooterTextResource();
+ if (oldFooterTextRes != newFooterTextRes) {
+ mEmptyShadeView.setFooterText(newFooterTextRes);
+ }
+ int oldFooterIconRes = mEmptyShadeView.getFooterIconResource();
+ if (oldFooterIconRes != newFooterIconRes) {
+ mEmptyShadeView.setFooterIcon(newFooterIconRes);
+ }
+ if (newFooterIconRes != 0 || newFooterTextRes != 0) {
+ mEmptyShadeView.setFooterVisibility(View.VISIBLE);
+ } else {
+ mEmptyShadeView.setFooterVisibility(View.GONE);
+ }
}
public boolean isEmptyShadeViewVisible() {
@@ -5348,9 +5378,9 @@
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
private void inflateEmptyShadeView() {
+ EmptyShadeView oldView = mEmptyShadeView;
EmptyShadeView view = (EmptyShadeView) LayoutInflater.from(mContext).inflate(
R.layout.status_bar_no_notifications, this, false);
- view.setText(R.string.empty_shade_text);
view.setOnClickListener(v -> {
final boolean showHistory = mController.isHistoryEnabled();
Intent intent = showHistory
@@ -5359,6 +5389,10 @@
mCentralSurfaces.startActivity(intent, true, true, Intent.FLAG_ACTIVITY_SINGLE_TOP);
});
setEmptyShadeView(view);
+ updateEmptyShadeView(
+ oldView == null ? R.string.empty_shade_text : oldView.getTextResource(),
+ oldView == null ? 0 : oldView.getFooterTextResource(),
+ oldView == null ? 0 : oldView.getFooterIconResource());
}
/**
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 ad4501a..e3336b2 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
@@ -81,6 +81,7 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -89,6 +90,7 @@
import com.android.systemui.statusbar.notification.collection.PipelineDumper;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProvider;
import com.android.systemui.statusbar.notification.collection.provider.VisibilityLocationProviderDelegator;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
@@ -174,6 +176,8 @@
private final StackStateLogger mStackStateLogger;
private final NotificationStackScrollLogger mLogger;
private final GroupExpansionManager mGroupExpansionManager;
+ private final NotifPipelineFlags mNotifPipelineFlags;
+ private final SeenNotificationsProvider mSeenNotificationsProvider;
private NotificationStackScrollLayout mView;
private boolean mFadeNotificationsOnDismiss;
@@ -639,12 +643,14 @@
GroupExpansionManager groupManager,
@SilentHeader SectionHeaderController silentHeaderController,
NotifPipeline notifPipeline,
+ NotifPipelineFlags notifPipelineFlags,
NotifCollection notifCollection,
LockscreenShadeTransitionController lockscreenShadeTransitionController,
ShadeTransitionController shadeTransitionController,
UiEventLogger uiEventLogger,
NotificationRemoteInputManager remoteInputManager,
VisibilityLocationProviderDelegator visibilityLocationProviderDelegator,
+ SeenNotificationsProvider seenNotificationsProvider,
ShadeController shadeController,
InteractionJankMonitor jankMonitor,
StackStateLogger stackLogger,
@@ -683,10 +689,12 @@
mGroupExpansionManager = groupManager;
mSilentHeaderController = silentHeaderController;
mNotifPipeline = notifPipeline;
+ mNotifPipelineFlags = notifPipelineFlags;
mNotifCollection = notifCollection;
mUiEventLogger = uiEventLogger;
mRemoteInputManager = remoteInputManager;
mVisibilityLocationProviderDelegator = visibilityLocationProviderDelegator;
+ mSeenNotificationsProvider = seenNotificationsProvider;
mShadeController = shadeController;
mFeatureFlags = featureFlags;
mNotificationTargetsHelper = notificationTargetsHelper;
@@ -1212,7 +1220,11 @@
// For more details, see: b/228790482
&& !isInTransitionToKeyguard();
- mView.updateEmptyShadeView(shouldShow, mZenModeController.areNotificationsHiddenInShade());
+ mView.updateEmptyShadeView(
+ shouldShow,
+ mZenModeController.areNotificationsHiddenInShade(),
+ mNotifPipelineFlags.getShouldFilterUnseenNotifsOnKeyguard()
+ && mSeenNotificationsProvider.getHasFilteredOutSeenNotifications());
Trace.endSection();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 34e62ce..03057a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -496,7 +496,7 @@
&& mPendingAuthenticated.userId == KeyguardUpdateMonitor.getCurrentUser();
}
- public int getMode() {
+ public @WakeAndUnlockMode int getMode() {
return mMode;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index e068f87..c7c6441 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -28,7 +28,6 @@
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.view.KeyEvent;
-import android.view.MotionEvent;
import android.view.RemoteAnimationAdapter;
import android.view.View;
import android.view.ViewGroup;
@@ -285,7 +284,11 @@
void animateCollapseQuickSettings();
- void onTouchEvent(MotionEvent event);
+ /** */
+ boolean getCommandQueuePanelsEnabled();
+
+ /** */
+ int getStatusBarWindowState();
BiometricUnlockController getBiometricUnlockController();
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 1611257..b394535 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -93,7 +93,6 @@
import android.view.IRemoteAnimationRunner;
import android.view.IWindowManager;
import android.view.KeyEvent;
-import android.view.MotionEvent;
import android.view.ThreadedRenderer;
import android.view.View;
import android.view.ViewGroup;
@@ -158,6 +157,8 @@
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.keyguard.ui.binder.LightRevealScrimViewBinder;
+import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.plugins.DarkIconDispatcher;
@@ -474,6 +475,7 @@
private final OngoingCallController mOngoingCallController;
private final StatusBarSignalPolicy mStatusBarSignalPolicy;
private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
+ private final Lazy<LightRevealScrimViewModel> mLightRevealScrimViewModelLazy;
/** Controller for the Shade. */
@VisibleForTesting
@@ -740,7 +742,8 @@
DeviceStateManager deviceStateManager,
WiredChargingRippleController wiredChargingRippleController,
IDreamManager dreamManager,
- Lazy<CameraLauncher> cameraLauncherLazy) {
+ Lazy<CameraLauncher> cameraLauncherLazy,
+ Lazy<LightRevealScrimViewModel> lightRevealScrimViewModelLazy) {
mContext = context;
mNotificationsController = notificationsController;
mFragmentService = fragmentService;
@@ -854,6 +857,8 @@
deviceStateManager.registerCallback(mMainExecutor,
new FoldStateListener(mContext, this::onFoldedStateChanged));
wiredChargingRippleController.registerCallbacks();
+
+ mLightRevealScrimViewModelLazy = lightRevealScrimViewModelLazy;
}
@Override
@@ -983,6 +988,12 @@
@Override
public void onKeyguardGoingAwayChanged() {
+ if (mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) {
+ // This code path is not used if the KeyguardTransitionRepository is managing
+ // the lightreveal scrim.
+ return;
+ }
+
// The light reveal scrim should always be fully revealed by the time the keyguard
// is done going away. Double check that this is true.
if (!mKeyguardStateController.isKeyguardGoingAway()) {
@@ -1219,6 +1230,12 @@
mScrimController.attachViews(scrimBehind, notificationsScrim, scrimInFront);
mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim);
+
+ if (mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) {
+ LightRevealScrimViewBinder.bind(
+ mLightRevealScrim, mLightRevealScrimViewModelLazy.get());
+ }
+
mLightRevealScrim.setScrimOpaqueChangedListener((opaque) -> {
Runnable updateOpaqueness = () -> {
mNotificationShadeWindowController.setLightRevealScrimOpaque(
@@ -1993,43 +2010,14 @@
}
}
- /** Called when a touch event occurred on {@link PhoneStatusBarView}. */
@Override
- public void onTouchEvent(MotionEvent event) {
- // TODO(b/202981994): Move this touch debugging to a central location. (Right now, it's
- // split between NotificationPanelViewController and here.)
- if (DEBUG_GESTURES) {
- if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
- EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH,
- event.getActionMasked(), (int) event.getX(), (int) event.getY(),
- mDisabled1, mDisabled2);
- }
+ public boolean getCommandQueuePanelsEnabled() {
+ return mCommandQueue.panelsEnabled();
+ }
- }
-
- if (SPEW) {
- Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled1="
- + mDisabled1 + " mDisabled2=" + mDisabled2);
- } else if (CHATTY) {
- if (event.getAction() != MotionEvent.ACTION_MOVE) {
- Log.d(TAG, String.format(
- "panel: %s at (%f, %f) mDisabled1=0x%08x mDisabled2=0x%08x",
- MotionEvent.actionToString(event.getAction()),
- event.getRawX(), event.getRawY(), mDisabled1, mDisabled2));
- }
- }
-
- if (DEBUG_GESTURES) {
- mGestureRec.add(event);
- }
-
- if (mStatusBarWindowState == WINDOW_STATE_SHOWING) {
- final boolean upOrCancel =
- event.getAction() == MotionEvent.ACTION_UP ||
- event.getAction() == MotionEvent.ACTION_CANCEL;
- setInteracting(StatusBarManager.WINDOW_STATUS_BAR,
- !upOrCancel || mShadeController.isExpandedVisible());
- }
+ @Override
+ public int getStatusBarWindowState() {
+ return mStatusBarWindowState;
}
@Override
@@ -3289,6 +3277,10 @@
return;
}
+ if (mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) {
+ return;
+ }
+
final boolean wakingUpFromPowerButton = wakingUp
&& !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)
&& mWakefulnessLifecycle.getLastWakeReason()
@@ -4053,7 +4045,9 @@
return;
}
- mLightRevealScrim.setAlpha(mScrimController.getState().getMaxLightRevealScrimAlpha());
+ if (!mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) {
+ mLightRevealScrim.setAlpha(mScrimController.getState().getMaxLightRevealScrimAlpha());
+ }
}
@Override
@@ -4234,6 +4228,7 @@
@Override
public void onDozeAmountChanged(float linear, float eased) {
if (mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS)
+ && !mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)
&& !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
mLightRevealScrim.setRevealAmount(1f - linear);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index a6c2b2c..11bc490 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -15,14 +15,20 @@
*/
package com.android.systemui.statusbar.phone
+import android.app.StatusBarManager.WINDOW_STATE_SHOWING
+import android.app.StatusBarManager.WINDOW_STATUS_BAR
import android.content.res.Configuration
import android.graphics.Point
+import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import com.android.systemui.R
+import com.android.systemui.shade.ShadeController
+import com.android.systemui.shade.ShadeLogger
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
+import com.android.systemui.statusbar.phone.PhoneStatusBarView.TouchEventHandler
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.unfold.SysUIUnfoldComponent
import com.android.systemui.unfold.UNFOLD_STATUS_BAR
@@ -35,14 +41,18 @@
import javax.inject.Inject
import javax.inject.Named
+private const val TAG = "PhoneStatusBarViewController"
+
/** Controller for [PhoneStatusBarView]. */
class PhoneStatusBarViewController private constructor(
view: PhoneStatusBarView,
@Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider?,
+ private val centralSurfaces: CentralSurfaces,
+ private val shadeController: ShadeController,
+ private val shadeLogger: ShadeLogger,
private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
private val userChipViewModel: StatusBarUserChipViewModel,
private val viewUtil: ViewUtil,
- touchEventHandler: PhoneStatusBarView.TouchEventHandler,
private val configurationController: ConfigurationController
) : ViewController<PhoneStatusBarView>(view) {
@@ -90,7 +100,7 @@
}
init {
- mView.setTouchEventHandler(touchEventHandler)
+ mView.setTouchEventHandler(PhoneStatusBarViewTouchHandler())
mView.init(userChipViewModel)
}
@@ -120,6 +130,54 @@
return viewUtil.touchIsWithinView(mView, x, y)
}
+ /** Called when a touch event occurred on {@link PhoneStatusBarView}. */
+ fun onTouchEvent(event: MotionEvent) {
+ if (centralSurfaces.statusBarWindowState == WINDOW_STATE_SHOWING) {
+ val upOrCancel =
+ event.action == MotionEvent.ACTION_UP ||
+ event.action == MotionEvent.ACTION_CANCEL
+ centralSurfaces.setInteracting(WINDOW_STATUS_BAR,
+ !upOrCancel || shadeController.isExpandedVisible)
+ }
+ }
+
+ inner class PhoneStatusBarViewTouchHandler : TouchEventHandler {
+ override fun onInterceptTouchEvent(event: MotionEvent) {
+ onTouchEvent(event)
+ }
+
+ override fun handleTouchEvent(event: MotionEvent): Boolean {
+ onTouchEvent(event)
+
+ // If panels aren't enabled, ignore the gesture and don't pass it down to the
+ // panel view.
+ if (!centralSurfaces.commandQueuePanelsEnabled) {
+ if (event.action == MotionEvent.ACTION_DOWN) {
+ Log.v(TAG, String.format("onTouchForwardedFromStatusBar: panel disabled, " +
+ "ignoring touch at (${event.x.toInt()},${event.y.toInt()})"))
+ }
+ return false
+ }
+
+ if (event.action == MotionEvent.ACTION_DOWN) {
+ // If the view that would receive the touch is disabled, just have status
+ // bar eat the gesture.
+ if (!centralSurfaces.notificationPanelViewController.isViewEnabled) {
+ shadeLogger.logMotionEvent(event,
+ "onTouchForwardedFromStatusBar: panel view disabled")
+ return true
+ }
+ if (centralSurfaces.notificationPanelViewController.isFullyCollapsed &&
+ event.y < 1f) {
+ // b/235889526 Eat events on the top edge of the phone when collapsed
+ shadeLogger.logMotionEvent(event, "top edge touch ignored")
+ return true
+ }
+ }
+ return centralSurfaces.notificationPanelViewController.sendTouchEventToView(event)
+ }
+ }
+
class StatusBarViewsCenterProvider : UnfoldMoveFromCenterAnimator.ViewCenterProvider {
override fun getViewCenter(view: View, outPoint: Point) =
when (view.id) {
@@ -157,20 +215,24 @@
@Named(UNFOLD_STATUS_BAR)
private val progressProvider: Optional<ScopedUnfoldTransitionProgressProvider>,
private val userChipViewModel: StatusBarUserChipViewModel,
+ private val centralSurfaces: CentralSurfaces,
+ private val shadeController: ShadeController,
+ private val shadeLogger: ShadeLogger,
private val viewUtil: ViewUtil,
private val configurationController: ConfigurationController,
) {
fun create(
- view: PhoneStatusBarView,
- touchEventHandler: PhoneStatusBarView.TouchEventHandler
+ view: PhoneStatusBarView
) =
PhoneStatusBarViewController(
view,
progressProvider.getOrNull(),
+ centralSurfaces,
+ shadeController,
+ shadeLogger,
unfoldComponent.getOrNull()?.getStatusBarMoveFromCenterAnimationController(),
userChipViewModel,
viewUtil,
- touchEventHandler,
configurationController
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index f9d316b..aafcddd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -19,9 +19,6 @@
import static android.view.WindowInsets.Type.navigationBars;
import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
-import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_DISMISS_BOUNCER;
-import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_SHOW_BOUNCER;
-import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_UNLOCK_COLLAPSING;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
@@ -140,6 +137,10 @@
private final BouncerView mPrimaryBouncerView;
private final Lazy<com.android.systemui.shade.ShadeController> mShadeController;
+ // Local cache of expansion events, to avoid duplicates
+ private float mFraction = -1f;
+ private boolean mTracking = false;
+
private final PrimaryBouncerExpansionCallback mExpansionCallback =
new PrimaryBouncerExpansionCallback() {
private boolean mPrimaryBouncerAnimating;
@@ -440,80 +441,68 @@
hideBouncer(true /* destroyView */);
}
- @Override
- public void onPanelExpansionChanged(ShadeExpansionChangeEvent event) {
- float fraction = event.getFraction();
- boolean tracking = event.getTracking();
+ private boolean beginShowingBouncer(ShadeExpansionChangeEvent event) {
// Avoid having the shade and the bouncer open at the same time over a dream.
final boolean hideBouncerOverDream =
mDreamOverlayStateController.isOverlayActive()
&& (mNotificationPanelViewController.isExpanded()
|| mNotificationPanelViewController.isExpanding());
- // We don't want to translate the bounce when:
- // • device is dozing and not pulsing
- // • Keyguard is occluded, because we're in a FLAG_SHOW_WHEN_LOCKED activity and need to
- // conserve the original animation.
- // • The user quickly taps on the display and we show "swipe up to unlock."
- // • Keyguard will be dismissed by an action. a.k.a: FLAG_DISMISS_KEYGUARD_ACTIVITY
- // • Full-screen user switcher is displayed.
- if (mDozing && !mPulsing) {
+ final boolean isUserTrackingStarted =
+ event.getFraction() != KeyguardBouncer.EXPANSION_HIDDEN && event.getTracking();
+
+ return mKeyguardStateController.isShowing()
+ && !primaryBouncerIsOrWillBeShowing()
+ && isUserTrackingStarted
+ && !hideBouncerOverDream
+ && !mKeyguardStateController.isOccluded()
+ && !mKeyguardStateController.canDismissLockScreen()
+ && !bouncerIsAnimatingAway()
+ && !mNotificationPanelViewController.isUnlockHintRunning()
+ && !(mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED);
+ }
+
+ @Override
+ public void onPanelExpansionChanged(ShadeExpansionChangeEvent event) {
+ float fraction = event.getFraction();
+ boolean tracking = event.getTracking();
+
+ if (mFraction == fraction && mTracking == tracking) {
+ // Ignore duplicate events, as they will cause confusion with bouncer expansion
return;
- } else if (mNotificationPanelViewController.isUnlockHintRunning()) {
+ }
+ mFraction = fraction;
+ mTracking = tracking;
+
+ /*
+ * The bouncer may have received a call to show(), or the following will infer it from
+ * device state and touch handling. The bouncer MUST have been notified that it is about to
+ * show if any subsequent events are to be handled.
+ */
+ if (beginShowingBouncer(event)) {
+ if (mPrimaryBouncer != null) {
+ mPrimaryBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */);
+ } else {
+ mPrimaryBouncerInteractor.show(/* isScrimmed= */false);
+ }
+ }
+
+ if (!primaryBouncerIsOrWillBeShowing()) {
+ return;
+ }
+
+ if (mKeyguardStateController.isShowing()) {
+ if (mPrimaryBouncer != null) {
+ mPrimaryBouncer.setExpansion(fraction);
+ } else {
+ mPrimaryBouncerInteractor.setPanelExpansion(fraction);
+ }
+ } else {
if (mPrimaryBouncer != null) {
mPrimaryBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
} else {
mPrimaryBouncerInteractor.setPanelExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
}
- } else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED) {
- // Don't expand to the bouncer. Instead transition back to the lock screen (see
- // CentralSurfaces#showBouncerOrLockScreenIfKeyguard)
- return;
- } else if (mKeyguardStateController.isOccluded()
- && !mDreamOverlayStateController.isOverlayActive()) {
- return;
- } else if (needsFullscreenBouncer()) {
- if (mPrimaryBouncer != null) {
- mPrimaryBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
- } else {
- mPrimaryBouncerInteractor.setPanelExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
- }
- } else if (mKeyguardStateController.isShowing() && !hideBouncerOverDream) {
- if (!isWakeAndUnlocking()
- && !(mBiometricUnlockController.getMode() == MODE_DISMISS_BOUNCER)
- && !(mBiometricUnlockController.getMode() == MODE_SHOW_BOUNCER)
- && !isUnlockCollapsing()) {
- if (mPrimaryBouncer != null) {
- mPrimaryBouncer.setExpansion(fraction);
- } else {
- mPrimaryBouncerInteractor.setPanelExpansion(fraction);
- }
- }
- if (fraction != KeyguardBouncer.EXPANSION_HIDDEN && tracking
- && !mKeyguardStateController.canDismissLockScreen()
- && !primaryBouncerIsShowing()
- && !bouncerIsAnimatingAway()) {
- if (mPrimaryBouncer != null) {
- mPrimaryBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */);
- } else {
- mPrimaryBouncerInteractor.show(/* isScrimmed= */false);
- }
- }
- } else if (!mKeyguardStateController.isShowing() && isPrimaryBouncerInTransit()) {
- // Keyguard is not visible anymore, but expansion animation was still running.
- // We need to hide the bouncer, otherwise it will be stuck in transit.
- if (mPrimaryBouncer != null) {
- mPrimaryBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
- } else {
- mPrimaryBouncerInteractor.setPanelExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
- }
- } else if (mPulsing && fraction == KeyguardBouncer.EXPANSION_VISIBLE) {
- // Panel expanded while pulsing but didn't translate the bouncer (because we are
- // unlocked.) Let's simply wake-up to dismiss the lock screen.
- mCentralSurfaces.wakeUpIfDozing(
- SystemClock.uptimeMillis(),
- mCentralSurfaces.getBouncerContainer(),
- "BOUNCER_VISIBLE");
}
}
@@ -704,11 +693,6 @@
return mode == MODE_WAKE_AND_UNLOCK || mode == MODE_WAKE_AND_UNLOCK_PULSING;
}
- private boolean isUnlockCollapsing() {
- int mode = mBiometricUnlockController.getMode();
- return mode == MODE_UNLOCK_COLLAPSING;
- }
-
/**
* Adds a {@param runnable} to be executed after Keyguard is gone.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
index efec270..730ecde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
@@ -21,7 +21,6 @@
import com.android.systemui.R;
import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.dagger.qualifiers.RootView;
-import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.statusbar.HeadsUpStatusBarView;
import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions;
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
@@ -127,11 +126,9 @@
@StatusBarFragmentScope
static PhoneStatusBarViewController providePhoneStatusBarViewController(
PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory,
- @RootView PhoneStatusBarView phoneStatusBarView,
- NotificationPanelViewController notificationPanelViewController) {
+ @RootView PhoneStatusBarView phoneStatusBarView) {
return phoneStatusBarViewControllerFactory.create(
- phoneStatusBarView,
- notificationPanelViewController.getStatusBarTouchEventHandler());
+ phoneStatusBarView);
}
/** */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
index fe30c01..4a5342e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
@@ -36,16 +36,20 @@
* [com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository] for
* more details.
*/
+interface AirplaneModeViewModel {
+ /** True if the airplane mode icon is currently visible in the status bar. */
+ val isAirplaneModeIconVisible: StateFlow<Boolean>
+}
+
@SysUISingleton
-class AirplaneModeViewModel
+class AirplaneModeViewModelImpl
@Inject
constructor(
interactor: AirplaneModeInteractor,
logger: ConnectivityPipelineLogger,
@Application private val scope: CoroutineScope,
-) {
- /** True if the airplane mode icon is currently visible in the status bar. */
- val isAirplaneModeIconVisible: StateFlow<Boolean> =
+) : AirplaneModeViewModel {
+ override val isAirplaneModeIconVisible: StateFlow<Boolean> =
combine(interactor.isAirplaneMode, interactor.isForceHidden) {
isAirplaneMode,
isAirplaneIconForceHidden ->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
index c961422..fb67f1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
@@ -21,6 +21,8 @@
import com.android.systemui.log.table.TableLogBufferFactory
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepositoryImpl
+import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
+import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepositoryImpl
import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository
@@ -33,6 +35,8 @@
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositoryImpl
+import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
+import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl
import dagger.Binds
import dagger.Module
import dagger.Provides
@@ -43,12 +47,18 @@
abstract fun airplaneModeRepository(impl: AirplaneModeRepositoryImpl): AirplaneModeRepository
@Binds
+ abstract fun airplaneModeViewModel(impl: AirplaneModeViewModelImpl): AirplaneModeViewModel
+
+ @Binds
abstract fun connectivityRepository(impl: ConnectivityRepositoryImpl): ConnectivityRepository
@Binds
abstract fun wifiRepository(impl: WifiRepositoryImpl): WifiRepository
@Binds
+ abstract fun wifiInteractor(impl: WifiInteractorImpl): WifiInteractor
+
+ @Binds
abstract fun mobileConnectionsRepository(
impl: MobileConnectionsRepositoryImpl
): MobileConnectionsRepository
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
index a663536..0c9c1cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
@@ -43,6 +43,7 @@
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
+import com.android.systemui.statusbar.pipeline.wifi.shared.model.ACTIVITY_PREFIX
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiActivityModel
import java.util.concurrent.Executor
import javax.inject.Inject
@@ -109,7 +110,12 @@
merge(wifiNetworkChangeEvents, wifiStateChangeEvents)
.mapLatest { wifiManager.isWifiEnabled }
.distinctUntilChanged()
- .logInputChange(logger, "enabled")
+ .logDiffsForTable(
+ wifiTableLogBuffer,
+ columnPrefix = "",
+ columnName = "isWifiEnabled",
+ initialValue = wifiManager.isWifiEnabled,
+ )
.stateIn(
scope = scope,
started = SharingStarted.WhileSubscribed(),
@@ -143,7 +149,12 @@
awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
}
.distinctUntilChanged()
- .logInputChange(logger, "isWifiDefault")
+ .logDiffsForTable(
+ wifiTableLogBuffer,
+ columnPrefix = "",
+ columnName = "isWifiDefault",
+ initialValue = false,
+ )
.stateIn(
scope,
started = SharingStarted.WhileSubscribed(),
@@ -233,6 +244,11 @@
awaitClose { wifiManager.unregisterTrafficStateCallback(callback) }
}
}
+ .logDiffsForTable(
+ wifiTableLogBuffer,
+ columnPrefix = ACTIVITY_PREFIX,
+ initialValue = ACTIVITY_DEFAULT,
+ )
.stateIn(
scope,
started = SharingStarted.WhileSubscribed(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
index 3a3e611..ec935fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
@@ -34,16 +34,36 @@
* This interactor processes information from our data layer into information that the UI layer can
* use.
*/
-@SysUISingleton
-class WifiInteractor @Inject constructor(
- connectivityRepository: ConnectivityRepository,
- wifiRepository: WifiRepository,
-) {
+interface WifiInteractor {
/**
* The SSID (service set identifier) of the wifi network. Null if we don't have a network, or
* have a network but no valid SSID.
*/
- val ssid: Flow<String?> = wifiRepository.wifiNetwork.map { info ->
+ val ssid: Flow<String?>
+
+ /** Our current enabled status. */
+ val isEnabled: Flow<Boolean>
+
+ /** Our current default status. */
+ val isDefault: Flow<Boolean>
+
+ /** Our current wifi network. See [WifiNetworkModel]. */
+ val wifiNetwork: Flow<WifiNetworkModel>
+
+ /** Our current wifi activity. See [WifiActivityModel]. */
+ val activity: StateFlow<WifiActivityModel>
+
+ /** True if we're configured to force-hide the wifi icon and false otherwise. */
+ val isForceHidden: Flow<Boolean>
+}
+
+@SysUISingleton
+class WifiInteractorImpl @Inject constructor(
+ connectivityRepository: ConnectivityRepository,
+ wifiRepository: WifiRepository,
+) : WifiInteractor {
+
+ override val ssid: Flow<String?> = wifiRepository.wifiNetwork.map { info ->
when (info) {
is WifiNetworkModel.Inactive -> null
is WifiNetworkModel.CarrierMerged -> null
@@ -56,20 +76,15 @@
}
}
- /** Our current enabled status. */
- val isEnabled: Flow<Boolean> = wifiRepository.isWifiEnabled
+ override val isEnabled: Flow<Boolean> = wifiRepository.isWifiEnabled
- /** Our current default status. */
- val isDefault: Flow<Boolean> = wifiRepository.isWifiDefault
+ override val isDefault: Flow<Boolean> = wifiRepository.isWifiDefault
- /** Our current wifi network. See [WifiNetworkModel]. */
- val wifiNetwork: Flow<WifiNetworkModel> = wifiRepository.wifiNetwork
+ override val wifiNetwork: Flow<WifiNetworkModel> = wifiRepository.wifiNetwork
- /** Our current wifi activity. See [WifiActivityModel]. */
- val activity: StateFlow<WifiActivityModel> = wifiRepository.wifiActivity
+ override val activity: StateFlow<WifiActivityModel> = wifiRepository.wifiActivity
- /** True if we're configured to force-hide the wifi icon and false otherwise. */
- val isForceHidden: Flow<Boolean> = connectivityRepository.forceHiddenSlots.map {
+ override val isForceHidden: Flow<Boolean> = connectivityRepository.forceHiddenSlots.map {
it.contains(ConnectivitySlot.WIFI)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiActivityModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiActivityModel.kt
index 5746106..a4ca41c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiActivityModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiActivityModel.kt
@@ -16,10 +16,32 @@
package com.android.systemui.statusbar.pipeline.wifi.shared.model
+import com.android.systemui.log.table.Diffable
+import com.android.systemui.log.table.TableRowLogger
+
/** Provides information on the current wifi activity. */
data class WifiActivityModel(
/** True if the wifi has activity in (download). */
val hasActivityIn: Boolean,
/** True if the wifi has activity out (upload). */
val hasActivityOut: Boolean,
-)
+) : Diffable<WifiActivityModel> {
+
+ override fun logDiffs(prevVal: WifiActivityModel, row: TableRowLogger) {
+ if (prevVal.hasActivityIn != hasActivityIn) {
+ row.logChange(COL_ACTIVITY_IN, hasActivityIn)
+ }
+ if (prevVal.hasActivityOut != hasActivityOut) {
+ row.logChange(COL_ACTIVITY_OUT, hasActivityOut)
+ }
+ }
+
+ override fun logFull(row: TableRowLogger) {
+ row.logChange(COL_ACTIVITY_IN, hasActivityIn)
+ row.logChange(COL_ACTIVITY_OUT, hasActivityOut)
+ }
+}
+
+const val ACTIVITY_PREFIX = "wifiActivity"
+private const val COL_ACTIVITY_IN = "in"
+private const val COL_ACTIVITY_OUT = "out"
diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt
index 0910ea3..37115ad 100644
--- a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt
@@ -19,6 +19,8 @@
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
+import com.android.systemui.R
+import com.android.systemui.common.shared.model.Text
import com.android.systemui.common.ui.drawable.CircularDrawable
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.user.domain.interactor.GuestUserInteractor
@@ -144,7 +146,12 @@
): UserViewModel {
return UserViewModel(
viewKey = model.id,
- name = model.name,
+ name =
+ if (model.isGuest && model.isSelected) {
+ Text.Resource(R.string.guest_exit_quick_settings_button)
+ } else {
+ model.name
+ },
image = CircularDrawable(model.image),
isSelectionMarkerVisible = model.isSelected,
alpha =
diff --git a/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt b/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt
index 5b16ae9..b311318 100644
--- a/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt
@@ -22,11 +22,22 @@
* Run a block within a [Trace] section.
* Calls [Trace.beginSection] before and [Trace.endSection] after the passed block.
*/
-inline fun <T> traceSection(tag: String, block: () -> T): T {
- Trace.beginSection(tag)
- try {
- return block()
- } finally {
- Trace.endSection()
+inline fun <T> traceSection(tag: String, block: () -> T): T =
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_APP)) {
+ Trace.traceBegin(Trace.TRACE_TAG_APP, tag)
+ try {
+ block()
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_APP)
+ }
+ } else {
+ block()
+ }
+
+class TraceUtils {
+ companion object {
+ inline fun traceRunnable(tag: String, crossinline block: () -> Unit): Runnable {
+ return Runnable { traceSection(tag) { block() } }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
index afd582a..fa8c8982 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
@@ -87,17 +87,17 @@
biometricSettingEnabledForUser = false,
bouncerFullyShown = false,
faceAndFpNotAuthenticated = false,
+ faceAuthAllowed = true,
faceDisabled = false,
faceLockedOut = false,
- fpLockedOut = false,
goingToSleep = false,
keyguardAwake = false,
keyguardGoingAway = false,
listeningForFaceAssistant = false,
occludingAppRequestingFaceAuth = false,
primaryUser = false,
- scanningAllowedByStrongAuth = false,
secureCameraLaunched = false,
+ supportsDetect = true,
switchingUser = false,
udfpsBouncerShowing = false,
udfpsFingerDown = false,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 4e358dd..002da55 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -27,6 +27,7 @@
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING;
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
@@ -101,6 +102,8 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.annotation.NonNull;
+
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.InstanceId;
@@ -267,21 +270,9 @@
// IBiometricsFace@1.0 does not support detection, only authentication.
when(mFaceSensorProperties.isEmpty()).thenReturn(false);
+ when(mFaceSensorProperties.get(anyInt())).thenReturn(
+ createFaceSensorProperties(/* supportsFaceDetection = */ false));
- final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
- componentInfo.add(new ComponentInfoInternal("faceSensor" /* componentId */,
- "vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */,
- "00000001" /* serialNumber */, "" /* softwareVersion */));
- componentInfo.add(new ComponentInfoInternal("matchingAlgorithm" /* componentId */,
- "" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */,
- "vendor/version/revision" /* softwareVersion */));
-
- when(mFaceSensorProperties.get(anyInt())).thenReturn(new FaceSensorPropertiesInternal(
- 0 /* id */,
- FaceSensorProperties.STRENGTH_STRONG, 1 /* maxTemplatesAllowed */,
- componentInfo, FaceSensorProperties.TYPE_UNKNOWN,
- false /* supportsFaceDetection */, true /* supportsSelfIllumination */,
- false /* resetLockoutRequiresChallenge */));
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(List.of(
@@ -354,6 +345,28 @@
when(mAuthController.areAllFingerprintAuthenticatorsRegistered()).thenReturn(true);
}
+ @NonNull
+ private FaceSensorPropertiesInternal createFaceSensorProperties(boolean supportsFaceDetection) {
+ final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
+ componentInfo.add(new ComponentInfoInternal("faceSensor" /* componentId */,
+ "vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */,
+ "00000001" /* serialNumber */, "" /* softwareVersion */));
+ componentInfo.add(new ComponentInfoInternal("matchingAlgorithm" /* componentId */,
+ "" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */,
+ "vendor/version/revision" /* softwareVersion */));
+
+
+ return new FaceSensorPropertiesInternal(
+ 0 /* id */,
+ FaceSensorProperties.STRENGTH_STRONG,
+ 1 /* maxTemplatesAllowed */,
+ componentInfo,
+ FaceSensorProperties.TYPE_UNKNOWN,
+ supportsFaceDetection /* supportsFaceDetection */,
+ true /* supportsSelfIllumination */,
+ false /* resetLockoutRequiresChallenge */);
+ }
+
@After
public void tearDown() {
if (mMockitoSession != null) {
@@ -611,7 +624,7 @@
@Test
public void testUnlockingWithFaceAllowed_strongAuthTrackerUnlockingWithBiometricAllowed() {
// GIVEN unlocking with biometric is allowed
- when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
+ strongAuthNotRequired();
// THEN unlocking with face and fp is allowed
Assert.assertTrue(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
@@ -633,7 +646,7 @@
@Test
public void testUnlockingWithFaceAllowed_fingerprintLockout() {
// GIVEN unlocking with biometric is allowed
- when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
+ strongAuthNotRequired();
// WHEN fingerprint is locked out
fingerprintErrorLockedOut();
@@ -656,7 +669,7 @@
@Test
public void testUnlockingWithFpAllowed_fingerprintLockout() {
// GIVEN unlocking with biometric is allowed
- when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
+ strongAuthNotRequired();
// WHEN fingerprint is locked out
fingerprintErrorLockedOut();
@@ -710,10 +723,9 @@
}
@Test
- public void skipsAuthentication_whenEncryptedKeyguard() {
- when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
- STRONG_AUTH_REQUIRED_AFTER_BOOT);
- mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
+ public void skipsAuthentication_whenStrongAuthRequired_nonBypass() {
+ lockscreenBypassIsNotAllowed();
+ when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
@@ -723,15 +735,48 @@
}
@Test
- public void requiresAuthentication_whenEncryptedKeyguard_andBypass() {
- testStrongAuthExceptOnBouncer(
- STRONG_AUTH_REQUIRED_AFTER_BOOT);
+ public void faceDetect_whenStrongAuthRequiredAndBypass() {
+ // GIVEN bypass is enabled, face detection is supported and strong auth is required
+ lockscreenBypassIsAllowed();
+ supportsFaceDetection();
+ strongAuthRequiredEncrypted();
+ keyguardIsVisible();
+
+ // WHEN the device wakes up
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+ mTestableLooper.processAllMessages();
+
+ // FACE detect is triggered, not authenticate
+ verify(mFaceManager).detectFace(any(), any(), anyInt());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
+ anyBoolean());
+
+ // WHEN bouncer becomes visible
+ setKeyguardBouncerVisibility(true);
+ clearInvocations(mFaceManager);
+
+ // THEN face scanning is not run
+ mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
+ anyBoolean());
+ verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
}
@Test
- public void requiresAuthentication_whenTimeoutKeyguard_andBypass() {
- testStrongAuthExceptOnBouncer(
- KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
+ public void noFaceDetect_whenStrongAuthRequiredAndBypass_faceDetectionUnsupported() {
+ // GIVEN bypass is enabled, face detection is NOT supported and strong auth is required
+ lockscreenBypassIsAllowed();
+ strongAuthRequiredEncrypted();
+ keyguardIsVisible();
+
+ // WHEN the device wakes up
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+ mTestableLooper.processAllMessages();
+
+ // FACE detect and authenticate are NOT triggered
+ verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
+ anyBoolean());
}
@Test
@@ -764,24 +809,6 @@
assertThat(didFaceAuthRun).isFalse();
}
- private void testStrongAuthExceptOnBouncer(int strongAuth) {
- when(mKeyguardBypassController.canBypass()).thenReturn(true);
- mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
- when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(strongAuth);
-
- mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
- mTestableLooper.processAllMessages();
- keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
-
- // Stop scanning when bouncer becomes visible
- setKeyguardBouncerVisibility(true);
- clearInvocations(mFaceManager);
- mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
- }
-
@Test
public void testTriesToAuthenticate_whenAssistant() {
mKeyguardUpdateMonitor.setKeyguardShowing(true, true);
@@ -792,10 +819,9 @@
@Test
public void testTriesToAuthenticate_whenTrustOnAgentKeyguard_ifBypass() {
- mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
- when(mKeyguardBypassController.canBypass()).thenReturn(true);
+ lockscreenBypassIsAllowed();
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */,
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */,
new ArrayList<>());
@@ -815,26 +841,26 @@
}
@Test
- public void testIgnoresAuth_whenLockdown() {
- mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
- mTestableLooper.processAllMessages();
- when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
- KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+ public void testNoFaceAuth_whenLockDown() {
+ when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
+ userDeviceLockDown();
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
keyguardIsVisible();
+ mTestableLooper.processAllMessages();
+
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean());
+ verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
}
@Test
- public void testTriesToAuthenticate_whenLockout() {
- mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
- mTestableLooper.processAllMessages();
- when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
- KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT);
+ public void testFingerprintPowerPressed_restartsFingerprintListeningStateImmediately() {
+ mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback
+ .onAuthenticationError(FingerprintManager.BIOMETRIC_ERROR_POWER_PRESSED, "");
- keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
+ anyInt());
}
@Test
@@ -977,8 +1003,6 @@
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
-// resetFaceManager();
-// resetFingerprintManager();
when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), eq(newUser)))
.thenReturn(fingerprintLockoutMode);
@@ -1321,7 +1345,7 @@
mStatusBarStateListener.onStateChanged(StatusBarState.SHADE_LOCKED);
setKeyguardBouncerVisibility(false /* isVisible */);
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
- when(mKeyguardBypassController.canBypass()).thenReturn(true);
+ lockscreenBypassIsAllowed();
keyguardIsVisible();
// WHEN status bar state reports a change to the keyguard that would normally indicate to
@@ -1505,11 +1529,9 @@
userNotCurrentlySwitching();
// This disables face auth
- when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
- .thenReturn(STRONG_AUTH_REQUIRED_AFTER_BOOT);
+ when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
mTestableLooper.processAllMessages();
-
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
}
@@ -1973,6 +1995,109 @@
);
}
+ @Test
+ public void testStrongAuthChange_lockDown_stopsFpAndFaceListeningState() {
+ // GIVEN device is listening for face and fingerprint
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+ mTestableLooper.processAllMessages();
+ keyguardIsVisible();
+
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
+ anyInt());
+
+ final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
+ final CancellationSignal fpCancel = spy(mKeyguardUpdateMonitor.mFingerprintCancelSignal);
+ mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
+ mKeyguardUpdateMonitor.mFingerprintCancelSignal = fpCancel;
+ KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+ mKeyguardUpdateMonitor.registerCallback(callback);
+
+ // WHEN strong auth changes and device is in user lockdown
+ when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
+ userDeviceLockDown();
+ mKeyguardUpdateMonitor.notifyStrongAuthAllowedChanged(getCurrentUser());
+ mTestableLooper.processAllMessages();
+
+ // THEN face and fingerprint listening are cancelled
+ verify(faceCancel).cancel();
+ verify(callback).onBiometricRunningStateChanged(
+ eq(false), eq(BiometricSourceType.FACE));
+ verify(fpCancel).cancel();
+ verify(callback).onBiometricRunningStateChanged(
+ eq(false), eq(BiometricSourceType.FINGERPRINT));
+ }
+
+ @Test
+ public void testNonStrongBiometricAllowedChanged_stopsFaceListeningState() {
+ // GIVEN device is listening for face and fingerprint
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+ mTestableLooper.processAllMessages();
+ keyguardIsVisible();
+
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+
+ final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
+ mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
+ KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
+ mKeyguardUpdateMonitor.registerCallback(callback);
+
+ // WHEN non-strong biometric allowed changes
+ when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
+ mKeyguardUpdateMonitor.notifyNonStrongBiometricAllowedChanged(getCurrentUser());
+ mTestableLooper.processAllMessages();
+
+ // THEN face and fingerprint listening are cancelled
+ verify(faceCancel).cancel();
+ verify(callback).onBiometricRunningStateChanged(
+ eq(false), eq(BiometricSourceType.FACE));
+ }
+
+ @Test
+ public void testShouldListenForFace_withLockedDown_returnsFalse()
+ throws RemoteException {
+ keyguardNotGoingAway();
+ bouncerFullyVisibleAndNotGoingToSleep();
+ currentUserIsPrimary();
+ currentUserDoesNotHaveTrust();
+ biometricsNotDisabledThroughDevicePolicyManager();
+ biometricsEnabledForCurrentUser();
+ userNotCurrentlySwitching();
+ supportsFaceDetection();
+ mTestableLooper.processAllMessages();
+
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
+
+ userDeviceLockDown();
+
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+ }
+
+ private void userDeviceLockDown() {
+ when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
+ when(mStrongAuthTracker.getStrongAuthForUser(mCurrentUserId))
+ .thenReturn(STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+ }
+
+ private void supportsFaceDetection() {
+ when(mFaceSensorProperties.get(anyInt()))
+ .thenReturn(createFaceSensorProperties(
+ /* supportsFaceDetection = */ true));
+ }
+
+ private void lockscreenBypassIsAllowed() {
+ mockCanBypassLockscreen(true);
+ }
+
+ private void mockCanBypassLockscreen(boolean canBypass) {
+ mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
+ when(mKeyguardBypassController.canBypass()).thenReturn(canBypass);
+ }
+
+ private void lockscreenBypassIsNotAllowed() {
+ mockCanBypassLockscreen(false);
+ }
+
private void cleanupKeyguardUpdateMonitor() {
if (mKeyguardUpdateMonitor != null) {
mKeyguardUpdateMonitor.removeCallback(mTestCallback);
@@ -2066,9 +2191,16 @@
);
}
+ private void strongAuthRequiredEncrypted() {
+ when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
+ .thenReturn(STRONG_AUTH_REQUIRED_AFTER_BOOT);
+ when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
+ }
+
private void strongAuthNotRequired() {
when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
.thenReturn(0);
+ when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
}
private void currentUserDoesNotHaveTrust() {
@@ -2109,6 +2241,10 @@
setKeyguardBouncerVisibility(true);
}
+ private void bouncerNotVisible() {
+ setKeyguardBouncerVisibility(false);
+ }
+
private void setKeyguardBouncerVisibility(boolean isVisible) {
mKeyguardUpdateMonitor.sendPrimaryBouncerChanged(isVisible, isVisible);
mTestableLooper.processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index 57ca9c0..9d39a8c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -34,7 +34,6 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -88,6 +87,8 @@
import com.android.systemui.util.leak.ReferenceTestUtils;
import com.android.systemui.utils.os.FakeHandler;
+import com.google.common.util.concurrent.AtomicDouble;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -710,7 +711,7 @@
}
@Test
- public void onSingleTap_enabled_scaleIsChanged() {
+ public void onSingleTap_enabled_scaleAnimates() {
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
@@ -721,14 +722,28 @@
});
final View mirrorView = mWindowManager.getAttachedView();
+
final long timeout = SystemClock.uptimeMillis() + 1000;
- while (SystemClock.uptimeMillis() < timeout) {
- SystemClock.sleep(10);
- if (Float.compare(1.0f, mirrorView.getScaleX()) < 0) {
- return;
+ final AtomicDouble maxScaleX = new AtomicDouble();
+ final Runnable onAnimationFrame = new Runnable() {
+ @Override
+ public void run() {
+ // For some reason the fancy way doesn't compile...
+// maxScaleX.getAndAccumulate(mirrorView.getScaleX(), Math::max);
+ final double oldMax = maxScaleX.get();
+ final double newMax = Math.max(mirrorView.getScaleX(), oldMax);
+ assertTrue(maxScaleX.compareAndSet(oldMax, newMax));
+
+ if (SystemClock.uptimeMillis() < timeout) {
+ mirrorView.postOnAnimation(this);
+ }
}
- }
- fail("MirrorView scale is not changed");
+ };
+ mirrorView.postOnAnimation(onAnimationFrame);
+
+ waitForIdleSync();
+
+ ReferenceTestUtils.waitForCondition(() -> maxScaleX.get() > 1.0);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
index eb8c823..b765ab3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
@@ -26,6 +26,7 @@
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FeatureFlags
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.LightRevealScrim
@@ -77,6 +78,7 @@
@Mock private lateinit var udfpsControllerProvider: Provider<UdfpsController>
@Mock private lateinit var udfpsController: UdfpsController
@Mock private lateinit var statusBarStateController: StatusBarStateController
+ @Mock private lateinit var featureFlags: FeatureFlags
@Mock private lateinit var lightRevealScrim: LightRevealScrim
@Mock private lateinit var fpSensorProp: FingerprintSensorPropertiesInternal
@@ -106,6 +108,7 @@
biometricUnlockController,
udfpsControllerProvider,
statusBarStateController,
+ featureFlags,
rippleView
)
controller.init()
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 e7d5632..3c40835 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -47,6 +47,7 @@
import android.view.WindowManager
import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
+import android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
import android.view.WindowMetrics
import androidx.test.filters.SmallTest
import com.airbnb.lottie.LottieAnimationView
@@ -423,6 +424,21 @@
}
@Test
+ fun testLayoutParams_isKeyguardDialogType() =
+ testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED) {
+ sideFpsController.overlayOffsets = sensorLocation
+ sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
+ overlayController.show(SENSOR_ID, REASON_UNKNOWN)
+ executor.runAllReady()
+
+ verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
+
+ val lpType = overlayViewParamsCaptor.value.type
+
+ assertThat((lpType and TYPE_KEYGUARD_DIALOG) != 0).isTrue()
+ }
+
+ @Test
fun testLayoutParams_hasNoMoveAnimationWindowFlag() =
testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED) {
sideFpsController.overlayOffsets = sensorLocation
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index 13fc9fc..5deac19 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -16,10 +16,13 @@
package com.android.systemui.keyguard.data.repository
+import android.graphics.Point
+import android.hardware.biometrics.BiometricSourceType
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.AuthController
import com.android.systemui.common.shared.model.Position
import com.android.systemui.doze.DozeHost
import com.android.systemui.doze.DozeMachine
@@ -27,9 +30,11 @@
import com.android.systemui.doze.DozeTransitionListener
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.WakefulnessModel
+import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -57,9 +62,10 @@
@Mock private lateinit var dozeHost: DozeHost
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
- @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock private lateinit var biometricUnlockController: BiometricUnlockController
@Mock private lateinit var dozeTransitionListener: DozeTransitionListener
+ @Mock private lateinit var authController: AuthController
+ @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
private lateinit var underTest: KeyguardRepositoryImpl
@@ -76,6 +82,7 @@
keyguardStateController,
keyguardUpdateMonitor,
dozeTransitionListener,
+ authController,
)
}
@@ -198,7 +205,7 @@
fun dozeAmount() =
runTest(UnconfinedTestDispatcher()) {
val values = mutableListOf<Float>()
- val job = underTest.dozeAmount.onEach(values::add).launchIn(this)
+ val job = underTest.linearDozeAmount.onEach(values::add).launchIn(this)
val captor = argumentCaptor<StatusBarStateController.StateListener>()
verify(statusBarStateController).addCallback(captor.capture())
@@ -207,7 +214,7 @@
captor.value.onDozeAmountChanged(0.498f, 0.5f)
captor.value.onDozeAmountChanged(0.661f, 0.65f)
- assertThat(values).isEqualTo(listOf(0f, 0.4f, 0.5f, 0.65f))
+ assertThat(values).isEqualTo(listOf(0f, 0.433f, 0.498f, 0.661f))
job.cancel()
verify(statusBarStateController).removeCallback(captor.value)
@@ -217,25 +224,36 @@
fun wakefulness() =
runTest(UnconfinedTestDispatcher()) {
val values = mutableListOf<WakefulnessModel>()
- val job = underTest.wakefulnessState.onEach(values::add).launchIn(this)
+ val job = underTest.wakefulness.onEach(values::add).launchIn(this)
val captor = argumentCaptor<WakefulnessLifecycle.Observer>()
verify(wakefulnessLifecycle).addObserver(captor.capture())
+ whenever(wakefulnessLifecycle.wakefulness)
+ .thenReturn(WakefulnessLifecycle.WAKEFULNESS_WAKING)
captor.value.onStartedWakingUp()
+
+ whenever(wakefulnessLifecycle.wakefulness)
+ .thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE)
captor.value.onFinishedWakingUp()
+
+ whenever(wakefulnessLifecycle.wakefulness)
+ .thenReturn(WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP)
captor.value.onStartedGoingToSleep()
+
+ whenever(wakefulnessLifecycle.wakefulness)
+ .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP)
captor.value.onFinishedGoingToSleep()
- assertThat(values)
+ assertThat(values.map { it.state })
.isEqualTo(
listOf(
// Initial value will be ASLEEP
- WakefulnessModel.ASLEEP,
- WakefulnessModel.STARTING_TO_WAKE,
- WakefulnessModel.AWAKE,
- WakefulnessModel.STARTING_TO_SLEEP,
- WakefulnessModel.ASLEEP,
+ WakefulnessState.ASLEEP,
+ WakefulnessState.STARTING_TO_WAKE,
+ WakefulnessState.AWAKE,
+ WakefulnessState.STARTING_TO_SLEEP,
+ WakefulnessState.ASLEEP,
)
)
@@ -329,14 +347,20 @@
val captor = argumentCaptor<BiometricUnlockController.BiometricModeListener>()
verify(biometricUnlockController).addBiometricModeListener(captor.capture())
- captor.value.onModeChanged(BiometricUnlockController.MODE_NONE)
- captor.value.onModeChanged(BiometricUnlockController.MODE_WAKE_AND_UNLOCK)
- captor.value.onModeChanged(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING)
- captor.value.onModeChanged(BiometricUnlockController.MODE_SHOW_BOUNCER)
- captor.value.onModeChanged(BiometricUnlockController.MODE_ONLY_WAKE)
- captor.value.onModeChanged(BiometricUnlockController.MODE_UNLOCK_COLLAPSING)
- captor.value.onModeChanged(BiometricUnlockController.MODE_DISMISS_BOUNCER)
- captor.value.onModeChanged(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM)
+ listOf(
+ BiometricUnlockController.MODE_NONE,
+ BiometricUnlockController.MODE_WAKE_AND_UNLOCK,
+ BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING,
+ BiometricUnlockController.MODE_SHOW_BOUNCER,
+ BiometricUnlockController.MODE_ONLY_WAKE,
+ BiometricUnlockController.MODE_UNLOCK_COLLAPSING,
+ BiometricUnlockController.MODE_DISMISS_BOUNCER,
+ BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM,
+ )
+ .forEach {
+ whenever(biometricUnlockController.mode).thenReturn(it)
+ captor.value.onModeChanged(it)
+ }
assertThat(values)
.isEqualTo(
@@ -420,4 +444,104 @@
job.cancel()
verify(dozeTransitionListener).removeCallback(listener)
}
+
+ @Test
+ fun fingerprintSensorLocation() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<Point?>()
+ val job = underTest.fingerprintSensorLocation.onEach(values::add).launchIn(this)
+
+ val captor = argumentCaptor<AuthController.Callback>()
+ verify(authController).addCallback(captor.capture())
+
+ // An initial, null value should be initially emitted so that flows combined with this
+ // one
+ // emit values immediately. The sensor location is expected to be nullable, so anyone
+ // consuming it should handle that properly.
+ assertThat(values).isEqualTo(listOf(null))
+
+ listOf(Point(500, 500), Point(0, 0), null, Point(250, 250))
+ .onEach {
+ whenever(authController.fingerprintSensorLocation).thenReturn(it)
+ captor.value.onFingerprintLocationChanged()
+ }
+ .also { dispatchedSensorLocations ->
+ assertThat(values).isEqualTo(listOf(null) + dispatchedSensorLocations)
+ }
+
+ job.cancel()
+ }
+
+ @Test
+ fun faceSensorLocation() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<Point?>()
+ val job = underTest.faceSensorLocation.onEach(values::add).launchIn(this)
+
+ val captor = argumentCaptor<AuthController.Callback>()
+ verify(authController).addCallback(captor.capture())
+
+ // An initial, null value should be initially emitted so that flows combined with this
+ // one
+ // emit values immediately. The sensor location is expected to be nullable, so anyone
+ // consuming it should handle that properly.
+ assertThat(values).isEqualTo(listOf(null))
+
+ listOf(
+ Point(500, 500),
+ Point(0, 0),
+ null,
+ Point(250, 250),
+ )
+ .onEach {
+ whenever(authController.faceSensorLocation).thenReturn(it)
+ captor.value.onFaceSensorLocationChanged()
+ }
+ .also { dispatchedSensorLocations ->
+ assertThat(values).isEqualTo(listOf(null) + dispatchedSensorLocations)
+ }
+
+ job.cancel()
+ }
+
+ @Test
+ fun biometricUnlockSource() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<BiometricUnlockSource?>()
+ val job = underTest.biometricUnlockSource.onEach(values::add).launchIn(this)
+
+ val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
+ verify(keyguardUpdateMonitor).registerCallback(captor.capture())
+
+ // An initial, null value should be initially emitted so that flows combined with this
+ // one
+ // emit values immediately. The biometric unlock source is expected to be nullable, so
+ // anyone consuming it should handle that properly.
+ assertThat(values).isEqualTo(listOf(null))
+
+ listOf(
+ BiometricSourceType.FINGERPRINT,
+ BiometricSourceType.IRIS,
+ null,
+ BiometricSourceType.FACE,
+ BiometricSourceType.FINGERPRINT,
+ )
+ .onEach { biometricSourceType ->
+ captor.value.onBiometricAuthenticated(0, biometricSourceType, false)
+ }
+
+ assertThat(values)
+ .isEqualTo(
+ listOf(
+ null,
+ BiometricUnlockSource.FINGERPRINT_SENSOR,
+ BiometricUnlockSource.FACE_SENSOR,
+ null,
+ BiometricUnlockSource.FACE_SENSOR,
+ BiometricUnlockSource.FINGERPRINT_SENSOR,
+ )
+ )
+
+ job.cancel()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
index 2b03722..ce9c1da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
@@ -22,6 +22,7 @@
import android.util.Log.TerribleFailure
import android.util.Log.TerribleFailureHandler
import android.view.Choreographer.FrameCallback
+import androidx.test.filters.FlakyTest
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Interpolators
@@ -97,6 +98,7 @@
}
@Test
+ @FlakyTest(bugId = 260213291)
fun `starting second transition will cancel the first transition`() {
runBlocking(IMMEDIATE) {
val (animator, provider) = setupAnimator(this)
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
new file mode 100644
index 0000000..d2db910
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
@@ -0,0 +1,167 @@
+/*
+ * 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 com.android.systemui.keyguard.data.repository
+
+import android.graphics.Point
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
+import com.android.systemui.statusbar.CircleReveal
+import com.android.systemui.statusbar.LightRevealEffect
+import junit.framework.Assert.assertEquals
+import junit.framework.Assert.assertFalse
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.runCurrent
+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.MockitoAnnotations
+
+@SmallTest
+@RunWith(JUnit4::class)
+class LightRevealScrimRepositoryTest : SysuiTestCase() {
+ private lateinit var fakeKeyguardRepository: FakeKeyguardRepository
+ private lateinit var underTest: LightRevealScrimRepositoryImpl
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ fakeKeyguardRepository = FakeKeyguardRepository()
+ underTest = LightRevealScrimRepositoryImpl(fakeKeyguardRepository, context)
+ }
+
+ @Test
+ fun `nextRevealEffect - effect switches between default and biometric with no dupes`() =
+ runTest {
+ val values = mutableListOf<LightRevealEffect>()
+ val job = launch { underTest.revealEffect.collect { values.add(it) } }
+
+ // We should initially emit the default reveal effect.
+ runCurrent()
+ values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT })
+
+ // The source and sensor locations are still null, so we should still be using the
+ // default reveal despite a biometric unlock.
+ fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
+
+ runCurrent()
+ values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+
+ // We got a source but still have no sensor locations, so should be sticking with
+ // the default effect.
+ fakeKeyguardRepository.setBiometricUnlockSource(
+ BiometricUnlockSource.FINGERPRINT_SENSOR
+ )
+
+ runCurrent()
+ 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 },)
+
+ // Now we have fingerprint sensor locations, and wake and unlock via fingerprint.
+ val fingerprintLocation = Point(500, 500)
+ fakeKeyguardRepository.setFingerprintSensorLocation(fingerprintLocation)
+ fakeKeyguardRepository.setBiometricUnlockSource(
+ BiometricUnlockSource.FINGERPRINT_SENSOR
+ )
+ fakeKeyguardRepository.setBiometricUnlockState(
+ BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING
+ )
+
+ // We should now have switched to the circle reveal, at the fingerprint location.
+ runCurrent()
+ values.assertEffectsMatchPredicates(
+ { it == DEFAULT_REVEAL_EFFECT },
+ {
+ it is CircleReveal &&
+ it.centerX == fingerprintLocation.x &&
+ it.centerY == fingerprintLocation.y
+ },
+ )
+
+ // Subsequent wake and unlocks should not emit duplicate, identical CircleReveals.
+ val valuesPrevSize = values.size
+ fakeKeyguardRepository.setBiometricUnlockState(
+ BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING
+ )
+ fakeKeyguardRepository.setBiometricUnlockState(
+ BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
+ )
+ assertEquals(valuesPrevSize, values.size)
+
+ // Non-biometric unlock, we should return to the default reveal.
+ fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.NONE)
+
+ runCurrent()
+ values.assertEffectsMatchPredicates(
+ { it == DEFAULT_REVEAL_EFFECT },
+ {
+ it is CircleReveal &&
+ it.centerX == fingerprintLocation.x &&
+ it.centerY == fingerprintLocation.y
+ },
+ { it == DEFAULT_REVEAL_EFFECT },
+ )
+
+ // We already have a face location, so switching to face source should update the
+ // CircleReveal.
+ fakeKeyguardRepository.setBiometricUnlockSource(BiometricUnlockSource.FACE_SENSOR)
+ runCurrent()
+ fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
+ runCurrent()
+
+ values.assertEffectsMatchPredicates(
+ { it == DEFAULT_REVEAL_EFFECT },
+ {
+ it is CircleReveal &&
+ it.centerX == fingerprintLocation.x &&
+ it.centerY == fingerprintLocation.y
+ },
+ { it == DEFAULT_REVEAL_EFFECT },
+ {
+ it is CircleReveal &&
+ it.centerX == faceLocation.x &&
+ it.centerY == faceLocation.y
+ },
+ )
+
+ job.cancel()
+ }
+
+ /**
+ * Asserts that the list of LightRevealEffects satisfies the list of predicates, in order, with
+ * no leftover elements.
+ */
+ private fun List<LightRevealEffect>.assertEffectsMatchPredicates(
+ vararg predicates: (LightRevealEffect) -> Boolean
+ ) {
+ println(this)
+ assertEquals(predicates.size, this.size)
+
+ assertFalse(
+ zip(predicates) { effect, predicate -> predicate(effect) }.any { matched -> !matched }
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
new file mode 100644
index 0000000..3166214
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt
@@ -0,0 +1,154 @@
+/*
+ * 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 com.android.systemui.keyguard.domain.interactor
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.data.repository.FakeLightRevealScrimRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.statusbar.LightRevealEffect
+import com.android.systemui.statusbar.LightRevealScrim
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(JUnit4::class)
+class LightRevealScrimInteractorTest : SysuiTestCase() {
+ private val fakeKeyguardTransitionRepository = FakeKeyguardTransitionRepository()
+ private val fakeLightRevealScrimRepository = FakeLightRevealScrimRepository()
+
+ private val keyguardTransitionInteractor =
+ KeyguardTransitionInteractor(fakeKeyguardTransitionRepository)
+
+ private lateinit var underTest: LightRevealScrimInteractor
+
+ private val reveal1 =
+ object : LightRevealEffect {
+ override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {}
+ }
+
+ private val reveal2 =
+ object : LightRevealEffect {
+ override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {}
+ }
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ underTest =
+ LightRevealScrimInteractor(
+ fakeKeyguardTransitionRepository,
+ keyguardTransitionInteractor,
+ fakeLightRevealScrimRepository
+ )
+ }
+
+ @Test
+ fun `lightRevealEffect - does not change during keyguard transition`() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<LightRevealEffect>()
+ val job = underTest.lightRevealEffect.onEach(values::add).launchIn(this)
+
+ fakeLightRevealScrimRepository.setRevealEffect(reveal1)
+
+ // The reveal effect shouldn't emit anything until a keyguard transition starts.
+ assertEquals(values.size, 0)
+
+ // Once it starts, it should emit reveal1.
+ fakeKeyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(transitionState = TransitionState.STARTED)
+ )
+ assertEquals(values, listOf(reveal1))
+
+ // Until the next transition starts, reveal2 should not be emitted.
+ fakeLightRevealScrimRepository.setRevealEffect(reveal2)
+ fakeKeyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(transitionState = TransitionState.RUNNING)
+ )
+ fakeKeyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(transitionState = TransitionState.FINISHED)
+ )
+ assertEquals(values, listOf(reveal1))
+ fakeKeyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(transitionState = TransitionState.STARTED)
+ )
+ assertEquals(values, listOf(reveal1, reveal2))
+
+ job.cancel()
+ }
+
+ @Test
+ fun `revealAmount - inverted when appropriate`() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<Float>()
+ val job = underTest.revealAmount.onEach(values::add).launchIn(this)
+
+ fakeKeyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.AOD,
+ to = KeyguardState.LOCKSCREEN,
+ value = 0.3f
+ )
+ )
+
+ assertEquals(values, listOf(0.3f))
+
+ fakeKeyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.AOD,
+ value = 0.3f
+ )
+ )
+
+ assertEquals(values, listOf(0.3f, 0.7f))
+
+ job.cancel()
+ }
+
+ @Test
+ fun `revealAmount - ignores transitions that do not affect reveal amount`() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<Float>()
+ val job = underTest.revealAmount.onEach(values::add).launchIn(this)
+
+ fakeKeyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(from = KeyguardState.DOZING, to = KeyguardState.AOD, value = 0.3f)
+ )
+
+ assertEquals(values, emptyList<Float>())
+
+ fakeKeyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(from = KeyguardState.AOD, to = KeyguardState.DOZING, value = 0.3f)
+ )
+
+ assertEquals(values, emptyList<Float>())
+
+ job.cancel()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java
index 7bae115..17eb6e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java
@@ -18,6 +18,7 @@
import static android.os.PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
@@ -29,6 +30,9 @@
import android.app.IActivityManager;
import android.app.IForegroundServiceObserver;
+import android.app.job.IUserVisibleJobObserver;
+import android.app.job.JobScheduler;
+import android.app.job.UserVisibleJobSummary;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -59,6 +63,7 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@@ -79,6 +84,8 @@
@Mock
IActivityManager mIActivityManager;
@Mock
+ JobScheduler mJobScheduler;
+ @Mock
PackageManager mPackageManager;
@Mock
UserTracker mUserTracker;
@@ -92,8 +99,10 @@
private FgsManagerController mFmc;
private IForegroundServiceObserver mIForegroundServiceObserver;
+ private IUserVisibleJobObserver mIUserVisibleJobObserver;
private UserTracker.Callback mUserTrackerCallback;
private BroadcastReceiver mShowFgsManagerReceiver;
+ private InOrder mJobSchedulerInOrder;
private List<UserInfo> mUserProfiles;
@@ -111,6 +120,8 @@
mUserProfiles = new ArrayList<>();
Mockito.doReturn(mUserProfiles).when(mUserTracker).getUserProfiles();
+ mJobSchedulerInOrder = Mockito.inOrder(mJobScheduler);
+
mFmc = createFgsManagerController();
}
@@ -132,6 +143,52 @@
}
@Test
+ public void testNumPackages_jobs() throws RemoteException {
+ setUserProfiles(0);
+ setShowUserVisibleJobs(true);
+
+ UserVisibleJobSummary j1 = new UserVisibleJobSummary(0, 0, "pkg1", 0);
+ UserVisibleJobSummary j2 = new UserVisibleJobSummary(1, 0, "pkg2", 1);
+ Assert.assertEquals(0, mFmc.getNumRunningPackages());
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, true);
+ Assert.assertEquals(1, mFmc.getNumRunningPackages());
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j2, true);
+ Assert.assertEquals(2, mFmc.getNumRunningPackages());
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, false);
+ Assert.assertEquals(1, mFmc.getNumRunningPackages());
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j2, false);
+ Assert.assertEquals(0, mFmc.getNumRunningPackages());
+ }
+
+ @Test
+ public void testNumPackages_FgsAndJobs() throws RemoteException {
+ setUserProfiles(0);
+ setShowUserVisibleJobs(true);
+
+ Binder b1 = new Binder();
+ Binder b2 = new Binder();
+ UserVisibleJobSummary j1 = new UserVisibleJobSummary(0, 0, "pkg1", 0);
+ UserVisibleJobSummary j3 = new UserVisibleJobSummary(1, 0, "pkg3", 1);
+ Assert.assertEquals(0, mFmc.getNumRunningPackages());
+ mIForegroundServiceObserver.onForegroundStateChanged(b1, "pkg1", 0, true);
+ Assert.assertEquals(1, mFmc.getNumRunningPackages());
+ mIForegroundServiceObserver.onForegroundStateChanged(b2, "pkg2", 0, true);
+ Assert.assertEquals(2, mFmc.getNumRunningPackages());
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, true);
+ Assert.assertEquals(2, mFmc.getNumRunningPackages());
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j3, true);
+ Assert.assertEquals(3, mFmc.getNumRunningPackages());
+ mIForegroundServiceObserver.onForegroundStateChanged(b2, "pkg2", 0, false);
+ Assert.assertEquals(2, mFmc.getNumRunningPackages());
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j3, false);
+ Assert.assertEquals(1, mFmc.getNumRunningPackages());
+ mIForegroundServiceObserver.onForegroundStateChanged(b1, "pkg1", 0, false);
+ Assert.assertEquals(1, mFmc.getNumRunningPackages());
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, false);
+ Assert.assertEquals(0, mFmc.getNumRunningPackages());
+ }
+
+ @Test
public void testNumPackagesDoesNotChangeWhenSecondFgsIsStarted() throws RemoteException {
setUserProfiles(0);
@@ -243,6 +300,91 @@
Assert.assertEquals(0, mFmc.visibleButtonsCount());
}
+ @Test
+ public void testShowUserVisibleJobsOnCreation() {
+ // Test when the default is on.
+ mDeviceConfigProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS,
+ "true", false);
+ FgsManagerController fmc = new FgsManagerControllerImpl(
+ mContext,
+ mMainExecutor,
+ mBackgroundExecutor,
+ mSystemClock,
+ mIActivityManager,
+ mJobScheduler,
+ mPackageManager,
+ mUserTracker,
+ mDeviceConfigProxyFake,
+ mDialogLaunchAnimator,
+ mBroadcastDispatcher,
+ mDumpManager
+ );
+ fmc.init();
+ Assert.assertTrue(fmc.getIncludesUserVisibleJobs());
+ ArgumentCaptor<IUserVisibleJobObserver> iUserVisibleJobObserverArgumentCaptor =
+ ArgumentCaptor.forClass(IUserVisibleJobObserver.class);
+ mJobSchedulerInOrder.verify(mJobScheduler)
+ .registerUserVisibleJobObserver(iUserVisibleJobObserverArgumentCaptor.capture());
+ Assert.assertNotNull(iUserVisibleJobObserverArgumentCaptor.getValue());
+
+ // Test when the default is off.
+ mDeviceConfigProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS,
+ "false", false);
+ fmc = new FgsManagerControllerImpl(
+ mContext,
+ mMainExecutor,
+ mBackgroundExecutor,
+ mSystemClock,
+ mIActivityManager,
+ mJobScheduler,
+ mPackageManager,
+ mUserTracker,
+ mDeviceConfigProxyFake,
+ mDialogLaunchAnimator,
+ mBroadcastDispatcher,
+ mDumpManager
+ );
+ fmc.init();
+ Assert.assertFalse(fmc.getIncludesUserVisibleJobs());
+ mJobSchedulerInOrder.verify(mJobScheduler, never()).registerUserVisibleJobObserver(any());
+ }
+
+ @Test
+ public void testShowUserVisibleJobsToggling() throws Exception {
+ setUserProfiles(0);
+ setShowUserVisibleJobs(true);
+
+ // pkg1 has only job
+ // pkg2 has both job and fgs
+ // pkg3 has only fgs
+ UserVisibleJobSummary j1 = new UserVisibleJobSummary(0, 0, "pkg1", 0);
+ UserVisibleJobSummary j2 = new UserVisibleJobSummary(1, 0, "pkg2", 1);
+ Binder b2 = new Binder();
+ Binder b3 = new Binder();
+
+ Assert.assertEquals(0, mFmc.getNumRunningPackages());
+ mIForegroundServiceObserver.onForegroundStateChanged(b2, "pkg2", 0, true);
+ mIForegroundServiceObserver.onForegroundStateChanged(b3, "pkg3", 0, true);
+ Assert.assertEquals(2, mFmc.getNumRunningPackages());
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, true);
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j2, true);
+ Assert.assertEquals(3, mFmc.getNumRunningPackages());
+
+ // Turn off the flag, confirm the number of packages is updated properly.
+ setShowUserVisibleJobs(false);
+ // Only pkg1 should be removed since the other two have fgs
+ Assert.assertEquals(2, mFmc.getNumRunningPackages());
+
+ setShowUserVisibleJobs(true);
+
+ Assert.assertEquals(2, mFmc.getNumRunningPackages());
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, true);
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j2, true);
+ Assert.assertEquals(3, mFmc.getNumRunningPackages());
+ }
+
private void setShowStopButtonForUserAllowlistedApps(boolean enable) {
mDeviceConfigProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
@@ -251,6 +393,33 @@
mBackgroundExecutor.runAllReady();
}
+ private void setShowUserVisibleJobs(boolean enable) {
+ if (mFmc.getIncludesUserVisibleJobs() == enable) {
+ // No change.
+ return;
+ }
+
+ mDeviceConfigProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS,
+ enable ? "true" : "false", false);
+ mBackgroundExecutor.advanceClockToLast();
+ mBackgroundExecutor.runAllReady();
+
+ ArgumentCaptor<IUserVisibleJobObserver> iUserVisibleJobObserverArgumentCaptor =
+ ArgumentCaptor.forClass(IUserVisibleJobObserver.class);
+ if (enable) {
+ mJobSchedulerInOrder.verify(mJobScheduler).registerUserVisibleJobObserver(
+ iUserVisibleJobObserverArgumentCaptor.capture()
+ );
+ mIUserVisibleJobObserver = iUserVisibleJobObserverArgumentCaptor.getValue();
+ } else {
+ mJobSchedulerInOrder.verify(mJobScheduler).unregisterUserVisibleJobObserver(
+ eq(mIUserVisibleJobObserver)
+ );
+ mIUserVisibleJobObserver = null;
+ }
+ }
+
private void setBackgroundRestrictionExemptionReason(String pkgName, int uid, int reason)
throws Exception {
Mockito.doReturn(uid)
@@ -275,6 +444,7 @@
mBackgroundExecutor,
mSystemClock,
mIActivityManager,
+ mJobScheduler,
mPackageManager,
mUserTracker,
mDeviceConfigProxyFake,
@@ -304,6 +474,15 @@
mUserTrackerCallback = userTrackerCallbackArgumentCaptor.getValue();
mShowFgsManagerReceiver = showFgsManagerReceiverArgumentCaptor.getValue();
+ if (result.getIncludesUserVisibleJobs()) {
+ ArgumentCaptor<IUserVisibleJobObserver> iUserVisibleJobObserverArgumentCaptor =
+ ArgumentCaptor.forClass(IUserVisibleJobObserver.class);
+ mJobSchedulerInOrder.verify(mJobScheduler).registerUserVisibleJobObserver(
+ iUserVisibleJobObserverArgumentCaptor.capture()
+ );
+ mIUserVisibleJobObserver = iUserVisibleJobObserverArgumentCaptor.getValue();
+ }
+
return result;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt
index 645b1cd..23466cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt
@@ -41,6 +41,7 @@
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.nullable
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.TestCoroutineScheduler
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -55,7 +56,7 @@
@Before
fun setUp() {
- utils = FooterActionsTestUtils(context, TestableLooper.get(this))
+ utils = FooterActionsTestUtils(context, TestableLooper.get(this), TestCoroutineScheduler())
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt
index 081a218..47afa70 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt
@@ -29,6 +29,7 @@
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.qs.FakeFgsManagerController
import com.android.systemui.qs.QSSecurityFooterUtils
import com.android.systemui.qs.footer.FooterActionsTestUtils
@@ -44,12 +45,9 @@
import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.TestCoroutineScheduler
import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -62,16 +60,20 @@
@RunWith(AndroidTestingRunner::class)
@RunWithLooper
class FooterActionsViewModelTest : SysuiTestCase() {
+ private val testScope = TestScope()
private lateinit var utils: FooterActionsTestUtils
- private val testDispatcher = UnconfinedTestDispatcher(TestCoroutineScheduler())
@Before
fun setUp() {
- utils = FooterActionsTestUtils(context, TestableLooper.get(this))
+ utils = FooterActionsTestUtils(context, TestableLooper.get(this), testScope.testScheduler)
+ }
+
+ private fun runTest(block: suspend TestScope.() -> Unit) {
+ testScope.runTest(testBody = block)
}
@Test
- fun settingsButton() = runBlockingTest {
+ fun settingsButton() = runTest {
val underTest = utils.footerActionsViewModel(showPowerButton = false)
val settings = underTest.settings
@@ -87,7 +89,7 @@
}
@Test
- fun powerButton() = runBlockingTest {
+ fun powerButton() = runTest {
// Without power button.
val underTestWithoutPower = utils.footerActionsViewModel(showPowerButton = false)
assertThat(underTestWithoutPower.power).isNull()
@@ -114,7 +116,7 @@
}
@Test
- fun userSwitcher() = runBlockingTest {
+ fun userSwitcher() = runTest {
val picture: Drawable = mock()
val userInfoController = FakeUserInfoController(FakeInfo(picture = picture))
val settings = FakeSettings()
@@ -135,7 +137,6 @@
showPowerButton = false,
footerActionsInteractor =
utils.footerActionsInteractor(
- bgDispatcher = testDispatcher,
userSwitcherRepository =
utils.userSwitcherRepository(
userTracker = userTracker,
@@ -143,22 +144,12 @@
userManager = userManager,
userInfoController = userInfoController,
userSwitcherController = userSwitcherControllerWrapper.controller,
- bgDispatcher = testDispatcher,
),
)
)
// Collect the user switcher into currentUserSwitcher.
- var currentUserSwitcher: FooterActionsButtonViewModel? = null
- val job = launch { underTest.userSwitcher.collect { currentUserSwitcher = it } }
- fun currentUserSwitcher(): FooterActionsButtonViewModel? {
- // Make sure we finish collecting the current user switcher. This is necessary because
- // combined flows launch multiple coroutines in the current scope so we need to make
- // sure we process all coroutines triggered by our flow collection before we make
- // assertions on the current buttons.
- advanceUntilIdle()
- return currentUserSwitcher
- }
+ val currentUserSwitcher = collectLastValue(underTest.userSwitcher)
// The user switcher is disabled.
assertThat(currentUserSwitcher()).isNull()
@@ -203,12 +194,10 @@
// in guest mode.
userInfoController.updateInfo { this.picture = mock<UserIconDrawable>() }
assertThat(iconTint()).isNull()
-
- job.cancel()
}
@Test
- fun security() = runBlockingTest {
+ fun security() = runTest {
val securityController = FakeSecurityController()
val qsSecurityFooterUtils = mock<QSSecurityFooterUtils>()
@@ -224,22 +213,15 @@
footerActionsInteractor =
utils.footerActionsInteractor(
qsSecurityFooterUtils = qsSecurityFooterUtils,
- bgDispatcher = testDispatcher,
securityRepository =
utils.securityRepository(
securityController = securityController,
- bgDispatcher = testDispatcher,
),
),
)
// Collect the security model into currentSecurity.
- var currentSecurity: FooterActionsSecurityButtonViewModel? = null
- val job = launch { underTest.security.collect { currentSecurity = it } }
- fun currentSecurity(): FooterActionsSecurityButtonViewModel? {
- advanceUntilIdle()
- return currentSecurity
- }
+ val currentSecurity = collectLastValue(underTest.security)
// By default, we always return a null SecurityButtonConfig.
assertThat(currentSecurity()).isNull()
@@ -270,12 +252,10 @@
security = currentSecurity()
assertThat(security).isNotNull()
assertThat(security!!.onClick).isNull()
-
- job.cancel()
}
@Test
- fun foregroundServices() = runBlockingTest {
+ fun foregroundServices() = runTest {
val securityController = FakeSecurityController()
val fgsManagerController =
FakeFgsManagerController(
@@ -300,21 +280,14 @@
securityRepository =
utils.securityRepository(
securityController,
- bgDispatcher = testDispatcher,
),
foregroundServicesRepository =
utils.foregroundServicesRepository(fgsManagerController),
- bgDispatcher = testDispatcher,
),
)
// Collect the security model into currentSecurity.
- var currentForegroundServices: FooterActionsForegroundServicesButtonViewModel? = null
- val job = launch { underTest.foregroundServices.collect { currentForegroundServices = it } }
- fun currentForegroundServices(): FooterActionsForegroundServicesButtonViewModel? {
- advanceUntilIdle()
- return currentForegroundServices
- }
+ val currentForegroundServices = collectLastValue(underTest.foregroundServices)
// We don't show the foreground services button if the number of running packages is not
// > 1.
@@ -356,12 +329,10 @@
}
securityController.updateState {}
assertThat(currentForegroundServices()?.displayText).isFalse()
-
- job.cancel()
}
@Test
- fun observeDeviceMonitoringDialogRequests() = runBlockingTest {
+ fun observeDeviceMonitoringDialogRequests() = runTest {
val qsSecurityFooterUtils = mock<QSSecurityFooterUtils>()
val broadcastDispatcher = mock<BroadcastDispatcher>()
@@ -390,7 +361,6 @@
utils.footerActionsInteractor(
qsSecurityFooterUtils = qsSecurityFooterUtils,
broadcastDispatcher = broadcastDispatcher,
- bgDispatcher = testDispatcher,
),
)
@@ -415,7 +385,4 @@
underTest.onVisibilityChangeRequested(visible = true)
assertThat(underTest.isVisible.value).isTrue()
}
-
- private fun runBlockingTest(block: suspend TestScope.() -> Unit) =
- runTest(testDispatcher) { block() }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 0d429da..17ba30a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -802,55 +802,6 @@
}
@Test
- public void handleTouchEventFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() {
- when(mCommandQueue.panelsEnabled()).thenReturn(false);
-
- boolean returnVal = mNotificationPanelViewController
- .getStatusBarTouchEventHandler()
- .handleTouchEvent(
- MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0));
-
- assertThat(returnVal).isFalse();
- verify(mView, never()).dispatchTouchEvent(any());
- }
-
- @Test
- public void handleTouchEventFromStatusBar_viewNotEnabled_returnsTrueAndNoViewEvent() {
- when(mCommandQueue.panelsEnabled()).thenReturn(true);
- when(mView.isEnabled()).thenReturn(false);
-
- boolean returnVal = mNotificationPanelViewController
- .getStatusBarTouchEventHandler()
- .handleTouchEvent(
- MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0));
-
- assertThat(returnVal).isTrue();
- verify(mView, never()).dispatchTouchEvent(any());
- }
-
- @Test
- public void handleTouchEventFromStatusBar_viewNotEnabledButIsMoveEvent_viewReceivesEvent() {
- when(mCommandQueue.panelsEnabled()).thenReturn(true);
- when(mView.isEnabled()).thenReturn(false);
- MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0);
-
- mNotificationPanelViewController.getStatusBarTouchEventHandler().handleTouchEvent(event);
-
- verify(mView).dispatchTouchEvent(event);
- }
-
- @Test
- public void handleTouchEventFromStatusBar_panelAndViewEnabled_viewReceivesEvent() {
- when(mCommandQueue.panelsEnabled()).thenReturn(true);
- when(mView.isEnabled()).thenReturn(true);
- MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0);
-
- mNotificationPanelViewController.getStatusBarTouchEventHandler().handleTouchEvent(event);
-
- verify(mView).dispatchTouchEvent(event);
- }
-
- @Test
public void testA11y_initializeNode() {
AccessibilityNodeInfo nodeInfo = new AccessibilityNodeInfo();
mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(mView, nodeInfo);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
index bdedd24..7f73856 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
@@ -30,6 +30,8 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider
+import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProvider
+import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProviderImpl
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
@@ -103,6 +105,31 @@
}
@Test
+ fun unseenFilterUpdatesSeenProviderWhenSuppressing() {
+ whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
+
+ // GIVEN: Keyguard is not showing, and a notification is present
+ keyguardRepository.setKeyguardShowing(false)
+ runKeyguardCoordinatorTest {
+ val fakeEntry = NotificationEntryBuilder().build()
+ collectionListener.onEntryAdded(fakeEntry)
+
+ // WHEN: The keyguard is now showing
+ keyguardRepository.setKeyguardShowing(true)
+ testScheduler.runCurrent()
+
+ // THEN: The notification is recognized as "seen" and is filtered out.
+ assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isTrue()
+
+ // WHEN: The filter is cleaned up
+ unseenFilter.onCleanup()
+
+ // THEN: The SeenNotificationProvider has been updated to reflect the suppression
+ assertThat(seenNotificationsProvider.hasFilteredOutSeenNotifications).isTrue()
+ }
+ }
+
+ @Test
fun unseenFilterAllowsNewNotif() {
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
@@ -204,6 +231,7 @@
testBlock: suspend KeyguardCoordinatorTestScope.() -> Unit
) {
val testScope = TestScope(UnconfinedTestDispatcher())
+ val seenNotificationsProvider = SeenNotificationsProviderImpl()
val keyguardCoordinator =
KeyguardCoordinator(
keyguardNotifVisibilityProvider,
@@ -211,18 +239,20 @@
notifPipelineFlags,
testScope.backgroundScope,
sectionHeaderVisibilityProvider,
+ seenNotificationsProvider,
statusBarStateController,
)
keyguardCoordinator.attach(notifPipeline)
- KeyguardCoordinatorTestScope(keyguardCoordinator, testScope).run {
- testScheduler.advanceUntilIdle()
- testScope.runTest(dispatchTimeoutMs = 1.seconds.inWholeMilliseconds) { testBlock() }
+ testScope.runTest(dispatchTimeoutMs = 1.seconds.inWholeMilliseconds) {
+ KeyguardCoordinatorTestScope(keyguardCoordinator, testScope, seenNotificationsProvider)
+ .testBlock()
}
}
private inner class KeyguardCoordinatorTestScope(
private val keyguardCoordinator: KeyguardCoordinator,
private val scope: TestScope,
+ val seenNotificationsProvider: SeenNotificationsProvider,
) : CoroutineScope by scope {
val testScheduler: TestCoroutineScheduler
get() = scope.testScheduler
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
new file mode 100644
index 0000000..2d23f3c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
@@ -0,0 +1,173 @@
+/*
+ * 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 com.android.systemui.statusbar.notification.row
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.MetricsLogger
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.PluginManager
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.NotificationMediaManager
+import com.android.systemui.statusbar.SmartReplyController
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager
+import com.android.systemui.statusbar.notification.logging.NotificationLogger
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.HeadsUpManager
+import com.android.systemui.statusbar.policy.SmartReplyConstants
+import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.time.SystemClock
+import com.android.systemui.wmshell.BubblesManager
+import java.util.Optional
+import junit.framework.Assert
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.never
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class ExpandableNotificationRowControllerTest : SysuiTestCase() {
+
+ private val appName = "MyApp"
+ private val notifKey = "MyNotifKey"
+
+ private val view: ExpandableNotificationRow = mock()
+ private val activableNotificationViewController: ActivatableNotificationViewController = mock()
+ private val rivSubComponentFactory: RemoteInputViewSubcomponent.Factory = mock()
+ private val metricsLogger: MetricsLogger = mock()
+ private val logBufferLogger: NotificationRowLogger = mock()
+ private val listContainer: NotificationListContainer = mock()
+ private val mediaManager: NotificationMediaManager = mock()
+ private val smartReplyConstants: SmartReplyConstants = mock()
+ private val smartReplyController: SmartReplyController = mock()
+ private val pluginManager: PluginManager = mock()
+ private val systemClock: SystemClock = mock()
+ private val keyguardBypassController: KeyguardBypassController = mock()
+ private val groupMembershipManager: GroupMembershipManager = mock()
+ private val groupExpansionManager: GroupExpansionManager = mock()
+ private val rowContentBindStage: RowContentBindStage = mock()
+ private val notifLogger: NotificationLogger = mock()
+ private val headsUpManager: HeadsUpManager = mock()
+ private val onExpandClickListener: ExpandableNotificationRow.OnExpandClickListener = mock()
+ private val statusBarStateController: StatusBarStateController = mock()
+ private val gutsManager: NotificationGutsManager = mock()
+ private val onUserInteractionCallback: OnUserInteractionCallback = mock()
+ private val falsingManager: FalsingManager = mock()
+ private val falsingCollector: FalsingCollector = mock()
+ private val featureFlags: FeatureFlags = mock()
+ private val peopleNotificationIdentifier: PeopleNotificationIdentifier = mock()
+ private val bubblesManager: BubblesManager = mock()
+ private val dragController: ExpandableNotificationRowDragController = mock()
+ private lateinit var controller: ExpandableNotificationRowController
+
+ @Before
+ fun setUp() {
+ allowTestableLooperAsMainThread()
+ controller =
+ ExpandableNotificationRowController(
+ view,
+ activableNotificationViewController,
+ rivSubComponentFactory,
+ metricsLogger,
+ logBufferLogger,
+ listContainer,
+ mediaManager,
+ smartReplyConstants,
+ smartReplyController,
+ pluginManager,
+ systemClock,
+ appName,
+ notifKey,
+ keyguardBypassController,
+ groupMembershipManager,
+ groupExpansionManager,
+ rowContentBindStage,
+ notifLogger,
+ headsUpManager,
+ onExpandClickListener,
+ statusBarStateController,
+ gutsManager,
+ /*allowLongPress=*/ false,
+ onUserInteractionCallback,
+ falsingManager,
+ falsingCollector,
+ featureFlags,
+ peopleNotificationIdentifier,
+ Optional.of(bubblesManager),
+ dragController
+ )
+ }
+
+ @After
+ fun tearDown() {
+ disallowTestableLooperAsMainThread()
+ }
+
+ @Test
+ fun offerKeepInParent_parentDismissed() {
+ whenever(featureFlags.isEnabled(Flags.NOTIFICATION_GROUP_DISMISSAL_ANIMATION))
+ .thenReturn(true)
+ whenever(view.isParentDismissed).thenReturn(true)
+
+ Assert.assertTrue(controller.offerToKeepInParentForAnimation())
+ Mockito.verify(view).setKeepInParentForDismissAnimation(true)
+ }
+
+ @Test
+ fun offerKeepInParent_parentNotDismissed() {
+ whenever(featureFlags.isEnabled(Flags.NOTIFICATION_GROUP_DISMISSAL_ANIMATION))
+ .thenReturn(true)
+
+ Assert.assertFalse(controller.offerToKeepInParentForAnimation())
+ Mockito.verify(view, never()).setKeepInParentForDismissAnimation(anyBoolean())
+ }
+
+ @Test
+ fun removeFromParent_keptForAnimation() {
+ val parentView: ExpandableNotificationRow = mock()
+ whenever(view.notificationParent).thenReturn(parentView)
+ whenever(view.keepInParentForDismissAnimation()).thenReturn(true)
+
+ Assert.assertTrue(controller.removeFromParentIfKeptForAnimation())
+ Mockito.verify(parentView).removeChildNotification(view)
+ }
+
+ @Test
+ fun removeFromParent_notKeptForAnimation() {
+ val parentView: ExpandableNotificationRow = mock()
+ whenever(view.notificationParent).thenReturn(parentView)
+
+ Assert.assertFalse(controller.removeFromParentIfKeptForAnimation())
+ Mockito.verifyNoMoreInteractions(parentView)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 496bf37..088d165 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -299,7 +299,8 @@
public ExpandableNotificationRow createBubble()
throws Exception {
Notification n = createNotification(false /* isGroupSummary */,
- null /* groupKey */, makeBubbleMetadata(null));
+ null /* groupKey */,
+ makeBubbleMetadata(null /* deleteIntent */, false /* autoExpand */));
n.flags |= FLAG_BUBBLE;
ExpandableNotificationRow row = generateRow(n, PKG, UID, USER_HANDLE,
mDefaultInflationFlags, IMPORTANCE_HIGH);
@@ -332,7 +333,8 @@
public ExpandableNotificationRow createBubbleInGroup()
throws Exception {
Notification n = createNotification(false /* isGroupSummary */,
- GROUP_KEY /* groupKey */, makeBubbleMetadata(null));
+ GROUP_KEY /* groupKey */,
+ makeBubbleMetadata(null /* deleteIntent */, false /* autoExpand */));
n.flags |= FLAG_BUBBLE;
ExpandableNotificationRow row = generateRow(n, PKG, UID, USER_HANDLE,
mDefaultInflationFlags, IMPORTANCE_HIGH);
@@ -348,7 +350,7 @@
* @param deleteIntent the intent to assign to {@link BubbleMetadata#deleteIntent}
*/
public NotificationEntry createBubble(@Nullable PendingIntent deleteIntent) {
- return createBubble(makeBubbleMetadata(deleteIntent), USER_HANDLE);
+ return createBubble(makeBubbleMetadata(deleteIntent, false /* autoExpand */), USER_HANDLE);
}
/**
@@ -357,7 +359,16 @@
* @param handle the user to associate with this bubble.
*/
public NotificationEntry createBubble(UserHandle handle) {
- return createBubble(makeBubbleMetadata(null), handle);
+ return createBubble(makeBubbleMetadata(null /* deleteIntent */, false /* autoExpand */),
+ handle);
+ }
+
+ /**
+ * Returns an {@link NotificationEntry} that should be shown as a auto-expanded bubble.
+ */
+ public NotificationEntry createAutoExpandedBubble() {
+ return createBubble(makeBubbleMetadata(null /* deleteIntent */, true /* autoExpand */),
+ USER_HANDLE);
}
/**
@@ -565,7 +576,7 @@
assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
}
- private BubbleMetadata makeBubbleMetadata(PendingIntent deleteIntent) {
+ private BubbleMetadata makeBubbleMetadata(PendingIntent deleteIntent, boolean autoExpand) {
Intent target = new Intent(mContext, BubblesTestActivity.class);
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target,
PendingIntent.FLAG_MUTABLE);
@@ -574,6 +585,7 @@
Icon.createWithResource(mContext, R.drawable.android))
.setDeleteIntent(deleteIntent)
.setDesiredHeight(314)
+ .setAutoExpandBubble(autoExpand)
.build();
}
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 026c82e..645052f 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
@@ -59,8 +59,10 @@
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProviderImpl;
import com.android.systemui.statusbar.notification.collection.provider.VisibilityLocationProviderDelegator;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
@@ -119,6 +121,7 @@
@Mock private GroupExpansionManager mGroupExpansionManager;
@Mock private SectionHeaderController mSilentHeaderController;
@Mock private NotifPipeline mNotifPipeline;
+ @Mock private NotifPipelineFlags mNotifPipelineFlags;
@Mock private NotifCollection mNotifCollection;
@Mock private UiEventLogger mUiEventLogger;
@Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
@@ -170,12 +173,14 @@
mGroupExpansionManager,
mSilentHeaderController,
mNotifPipeline,
+ mNotifPipelineFlags,
mNotifCollection,
mLockscreenShadeTransitionController,
mShadeTransitionController,
mUiEventLogger,
mRemoteInputManager,
mVisibilityLocationProviderDelegator,
+ new SeenNotificationsProviderImpl(),
mShadeController,
mJankMonitor,
mStackLogger,
@@ -228,14 +233,16 @@
mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
/* visible= */ true,
- /* notifVisibleInShade= */ true);
+ /* notifVisibleInShade= */ true,
+ /* areSeenNotifsFiltered= */false);
setupShowEmptyShadeViewState(false);
reset(mNotificationStackScrollLayout);
mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
/* visible= */ false,
- /* notifVisibleInShade= */ true);
+ /* notifVisibleInShade= */ true,
+ /* areSeenNotifsFiltered= */false);
}
@Test
@@ -248,14 +255,16 @@
mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
/* visible= */ true,
- /* notifVisibleInShade= */ false);
+ /* notifVisibleInShade= */ false,
+ /* areSeenNotifsFiltered= */false);
setupShowEmptyShadeViewState(false);
reset(mNotificationStackScrollLayout);
mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
/* visible= */ false,
- /* notifVisibleInShade= */ false);
+ /* notifVisibleInShade= */ false,
+ /* areSeenNotifsFiltered= */false);
}
@Test
@@ -274,14 +283,16 @@
mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
/* visible= */ true,
- /* notifVisibleInShade= */ false);
+ /* notifVisibleInShade= */ false,
+ /* areSeenNotifsFiltered= */false);
mController.setQsFullScreen(true);
reset(mNotificationStackScrollLayout);
mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
/* visible= */ true,
- /* notifVisibleInShade= */ false);
+ /* notifVisibleInShade= */ false,
+ /* areSeenNotifsFiltered= */false);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index dceb4ff..07ea630 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -324,7 +324,7 @@
public void updateEmptyView_dndSuppressing() {
when(mEmptyShadeView.willBeGone()).thenReturn(true);
- mStackScroller.updateEmptyShadeView(true, true);
+ mStackScroller.updateEmptyShadeView(true, true, false);
verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
}
@@ -334,7 +334,7 @@
mStackScroller.setEmptyShadeView(mEmptyShadeView);
when(mEmptyShadeView.willBeGone()).thenReturn(true);
- mStackScroller.updateEmptyShadeView(true, false);
+ mStackScroller.updateEmptyShadeView(true, false, false);
verify(mEmptyShadeView).setText(R.string.empty_shade_text);
}
@@ -343,10 +343,10 @@
public void updateEmptyView_noNotificationsToDndSuppressing() {
mStackScroller.setEmptyShadeView(mEmptyShadeView);
when(mEmptyShadeView.willBeGone()).thenReturn(true);
- mStackScroller.updateEmptyShadeView(true, false);
+ mStackScroller.updateEmptyShadeView(true, false, false);
verify(mEmptyShadeView).setText(R.string.empty_shade_text);
- mStackScroller.updateEmptyShadeView(true, true);
+ mStackScroller.updateEmptyShadeView(true, true, false);
verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
}
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 ed84e42..521e518 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
@@ -106,6 +106,7 @@
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.PluginDependencyProvider;
@@ -212,6 +213,7 @@
@Mock private NotificationPanelView mNotificationPanelView;
@Mock private IStatusBarService mBarService;
@Mock private IDreamManager mDreamManager;
+ @Mock private LightRevealScrimViewModel mLightRevealScrimViewModel;
@Mock private ScrimController mScrimController;
@Mock private DozeScrimController mDozeScrimController;
@Mock private Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
@@ -497,7 +499,8 @@
mDeviceStateManager,
mWiredChargingRippleController,
mDreamManager,
- mCameraLauncherLazy) {
+ mCameraLauncherLazy,
+ () -> mLightRevealScrimViewModel) {
@Override
protected ViewRootImpl getViewRootImpl() {
return mViewRootImpl;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index e2843a1..14d239a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -27,6 +27,8 @@
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.shade.NotificationPanelViewController
+import com.android.systemui.shade.ShadeControllerImpl
+import com.android.systemui.shade.ShadeLogger
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.unfold.SysUIUnfoldComponent
import com.android.systemui.unfold.config.UnfoldTransitionConfig
@@ -41,6 +43,7 @@
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -49,8 +52,6 @@
@SmallTest
class PhoneStatusBarViewControllerTest : SysuiTestCase() {
- private val touchEventHandler = TestTouchEventHandler()
-
@Mock
private lateinit var notificationPanelViewController: NotificationPanelViewController
@Mock
@@ -66,6 +67,12 @@
@Mock
private lateinit var userChipViewModel: StatusBarUserChipViewModel
@Mock
+ private lateinit var centralSurfacesImpl: CentralSurfacesImpl
+ @Mock
+ private lateinit var shadeControllerImpl: ShadeControllerImpl
+ @Mock
+ private lateinit var shadeLogger: ShadeLogger
+ @Mock
private lateinit var viewUtil: ViewUtil
private lateinit var view: PhoneStatusBarView
@@ -88,18 +95,6 @@
}
@Test
- fun constructor_setsTouchHandlerOnView() {
- val interceptEvent = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 10f, 10f, 0)
- val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
-
- view.onInterceptTouchEvent(interceptEvent)
- view.onTouchEvent(event)
-
- assertThat(touchEventHandler.lastInterceptEvent).isEqualTo(interceptEvent)
- assertThat(touchEventHandler.lastEvent).isEqualTo(event)
- }
-
- @Test
fun onViewAttachedAndDrawn_moveFromCenterAnimationEnabled_moveFromCenterAnimationInitialized() {
val view = createViewMock()
val argumentCaptor = ArgumentCaptor.forClass(OnPreDrawListener::class.java)
@@ -115,6 +110,66 @@
verify(moveFromCenterAnimation).onViewsReady(any())
}
+ @Test
+ fun handleTouchEventFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() {
+ `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(false)
+ val returnVal = view.onTouchEvent(
+ MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
+ assertThat(returnVal).isFalse()
+ verify(notificationPanelViewController, never()).sendTouchEventToView(any())
+ }
+
+ @Test
+ fun handleTouchEventFromStatusBar_viewNotEnabled_returnsTrueAndNoViewEvent() {
+ `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
+ `when`(centralSurfacesImpl.notificationPanelViewController)
+ .thenReturn(notificationPanelViewController)
+ `when`(notificationPanelViewController.isViewEnabled).thenReturn(false)
+ val returnVal = view.onTouchEvent(
+ MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0))
+ assertThat(returnVal).isTrue()
+ verify(notificationPanelViewController, never()).sendTouchEventToView(any())
+ }
+
+ @Test
+ fun handleTouchEventFromStatusBar_viewNotEnabledButIsMoveEvent_viewReceivesEvent() {
+ `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
+ `when`(centralSurfacesImpl.notificationPanelViewController)
+ .thenReturn(notificationPanelViewController)
+ `when`(notificationPanelViewController.isViewEnabled).thenReturn(false)
+ val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
+
+ view.onTouchEvent(event)
+
+ verify(notificationPanelViewController).sendTouchEventToView(event)
+ }
+
+ @Test
+ fun handleTouchEventFromStatusBar_panelAndViewEnabled_viewReceivesEvent() {
+ `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
+ `when`(centralSurfacesImpl.notificationPanelViewController)
+ .thenReturn(notificationPanelViewController)
+ `when`(notificationPanelViewController.isViewEnabled).thenReturn(true)
+ val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0)
+
+ view.onTouchEvent(event)
+
+ verify(notificationPanelViewController).sendTouchEventToView(event)
+ }
+
+ @Test
+ fun handleTouchEventFromStatusBar_topEdgeTouch_viewNeverReceivesEvent() {
+ `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
+ `when`(centralSurfacesImpl.notificationPanelViewController)
+ .thenReturn(notificationPanelViewController)
+ `when`(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
+ val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
+
+ view.onTouchEvent(event)
+
+ verify(notificationPanelViewController, never()).sendTouchEventToView(any())
+ }
+
private fun createViewMock(): PhoneStatusBarView {
val view = spy(view)
val viewTreeObserver = mock(ViewTreeObserver::class.java)
@@ -128,9 +183,12 @@
Optional.of(sysuiUnfoldComponent),
Optional.of(progressProvider),
userChipViewModel,
+ centralSurfacesImpl,
+ shadeControllerImpl,
+ shadeLogger,
viewUtil,
configurationController
- ).create(view, touchEventHandler).also {
+ ).create(view).also {
it.init()
}
}
@@ -140,17 +198,4 @@
override var isHingeAngleEnabled: Boolean = false
override val halfFoldedTimeoutMillis: Int = 0
}
-
- private class TestTouchEventHandler : PhoneStatusBarView.TouchEventHandler {
- var lastEvent: MotionEvent? = null
- var lastInterceptEvent: MotionEvent? = null
-
- override fun onInterceptTouchEvent(event: MotionEvent?) {
- lastInterceptEvent = event
- }
- override fun handleTouchEvent(event: MotionEvent?): Boolean {
- lastEvent = event
- return false
- }
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index e467d93..471f8d3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -222,31 +222,32 @@
}
@Test
- public void onPanelExpansionChanged_neverHidesFullscreenBouncer() {
- when(mPrimaryBouncer.isShowing()).thenReturn(true);
- when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
- KeyguardSecurityModel.SecurityMode.SimPuk);
- mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
- verify(mPrimaryBouncer).setExpansion(eq(KeyguardBouncer.EXPANSION_VISIBLE));
-
- reset(mPrimaryBouncer);
- when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
- KeyguardSecurityModel.SecurityMode.SimPin);
- mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
- verify(mPrimaryBouncer).setExpansion(eq(KeyguardBouncer.EXPANSION_VISIBLE));
- }
-
- @Test
public void onPanelExpansionChanged_neverShowsDuringHintAnimation() {
when(mNotificationPanelView.isUnlockHintRunning()).thenReturn(true);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
- verify(mPrimaryBouncer).setExpansion(eq(KeyguardBouncer.EXPANSION_HIDDEN));
+ verify(mPrimaryBouncer, never()).setExpansion(anyFloat());
}
@Test
- public void onPanelExpansionChanged_propagatesToBouncer() {
+ public void onPanelExpansionChanged_propagatesToBouncerOnlyIfShowing() {
+ mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
+ verify(mPrimaryBouncer, never()).setExpansion(eq(0.5f));
+
+ when(mPrimaryBouncer.isShowing()).thenReturn(true);
+ mStatusBarKeyguardViewManager.onPanelExpansionChanged(
+ expansionEvent(/* fraction= */ 0.6f, /* expanded= */ false, /* tracking= */ true));
+ verify(mPrimaryBouncer).setExpansion(eq(0.6f));
+ }
+
+ @Test
+ public void onPanelExpansionChanged_duplicateEventsAreIgnored() {
+ when(mPrimaryBouncer.isShowing()).thenReturn(true);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
verify(mPrimaryBouncer).setExpansion(eq(0.5f));
+
+ reset(mPrimaryBouncer);
+ mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
+ verify(mPrimaryBouncer, never()).setExpansion(eq(0.5f));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt
similarity index 95%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt
index 76016a1..5a6bb30 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt
@@ -38,9 +38,9 @@
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
-class AirplaneModeViewModelTest : SysuiTestCase() {
+class AirplaneModeViewModelImplTest : SysuiTestCase() {
- private lateinit var underTest: AirplaneModeViewModel
+ private lateinit var underTest: AirplaneModeViewModelImpl
@Mock private lateinit var logger: ConnectivityPipelineLogger
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
@@ -57,7 +57,7 @@
scope = CoroutineScope(IMMEDIATE)
underTest =
- AirplaneModeViewModel(
+ AirplaneModeViewModelImpl(
interactor,
logger,
scope,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
similarity index 97%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
index 71b8bab..b38497a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
@@ -35,8 +35,9 @@
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
+@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
@SmallTest
-class WifiInteractorTest : SysuiTestCase() {
+class WifiInteractorImplTest : SysuiTestCase() {
private lateinit var underTest: WifiInteractor
@@ -47,7 +48,7 @@
fun setUp() {
connectivityRepository = FakeConnectivityRepository()
wifiRepository = FakeWifiRepository()
- underTest = WifiInteractor(connectivityRepository, wifiRepository)
+ underTest = WifiInteractorImpl(connectivityRepository, wifiRepository)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
index 37457b3..5c16e129 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
@@ -32,12 +32,14 @@
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
+import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
+import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl
import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel
@@ -86,9 +88,9 @@
connectivityRepository = FakeConnectivityRepository()
wifiRepository = FakeWifiRepository()
wifiRepository.setIsWifiEnabled(true)
- interactor = WifiInteractor(connectivityRepository, wifiRepository)
+ interactor = WifiInteractorImpl(connectivityRepository, wifiRepository)
scope = CoroutineScope(Dispatchers.Unconfined)
- airplaneModeViewModel = AirplaneModeViewModel(
+ airplaneModeViewModel = AirplaneModeViewModelImpl(
AirplaneModeInteractor(
airplaneModeRepository,
connectivityRepository,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
index a1afcd7..3001b81 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
@@ -30,6 +30,7 @@
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
+import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
@@ -37,6 +38,7 @@
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
+import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl
import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel.Companion.NO_INTERNET
import com.google.common.truth.Truth.assertThat
@@ -81,10 +83,10 @@
connectivityRepository = FakeConnectivityRepository()
wifiRepository = FakeWifiRepository()
wifiRepository.setIsWifiEnabled(true)
- interactor = WifiInteractor(connectivityRepository, wifiRepository)
+ interactor = WifiInteractorImpl(connectivityRepository, wifiRepository)
scope = CoroutineScope(IMMEDIATE)
airplaneModeViewModel =
- AirplaneModeViewModel(
+ AirplaneModeViewModelImpl(
AirplaneModeInteractor(
airplaneModeRepository,
connectivityRepository,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
index 7d2c560..6a6b2a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
@@ -23,6 +23,7 @@
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
+import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
@@ -30,6 +31,7 @@
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
+import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl
import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiActivityModel
import com.google.common.truth.Truth.assertThat
@@ -73,9 +75,9 @@
connectivityRepository = FakeConnectivityRepository()
wifiRepository = FakeWifiRepository()
wifiRepository.setIsWifiEnabled(true)
- interactor = WifiInteractor(connectivityRepository, wifiRepository)
+ interactor = WifiInteractorImpl(connectivityRepository, wifiRepository)
scope = CoroutineScope(IMMEDIATE)
- airplaneModeViewModel = AirplaneModeViewModel(
+ airplaneModeViewModel = AirplaneModeViewModelImpl(
AirplaneModeInteractor(
airplaneModeRepository,
connectivityRepository,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
index 4b6bdac..784a26b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt
@@ -47,18 +47,14 @@
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.TestDispatcher
-import kotlinx.coroutines.test.TestResult
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -89,7 +85,6 @@
private lateinit var testDispatcher: TestDispatcher
private lateinit var testScope: TestScope
- private lateinit var injectedScope: CoroutineScope
@Before
fun setUp() {
@@ -104,7 +99,6 @@
testDispatcher = UnconfinedTestDispatcher()
testScope = TestScope(testDispatcher)
- injectedScope = CoroutineScope(testScope.coroutineContext + SupervisorJob())
userRepository = FakeUserRepository()
runBlocking {
userRepository.setSettings(
@@ -118,14 +112,14 @@
powerRepository = FakePowerRepository()
val refreshUsersScheduler =
RefreshUsersScheduler(
- applicationScope = injectedScope,
+ applicationScope = testScope.backgroundScope,
mainDispatcher = testDispatcher,
repository = userRepository,
)
val guestUserInteractor =
GuestUserInteractor(
applicationContext = context,
- applicationScope = injectedScope,
+ applicationScope = testScope.backgroundScope,
mainDispatcher = testDispatcher,
backgroundDispatcher = testDispatcher,
manager = manager,
@@ -154,7 +148,7 @@
set(Flags.FULL_SCREEN_USER_SWITCHER, false)
},
manager = manager,
- applicationScope = injectedScope,
+ applicationScope = testScope.backgroundScope,
telephonyInteractor =
TelephonyInteractor(
repository = FakeTelephonyRepository(),
@@ -175,7 +169,7 @@
}
@Test
- fun users() = selfCancelingTest {
+ fun users() = testScope.runTest {
val userInfos =
listOf(
UserInfo(
@@ -210,26 +204,26 @@
assertUserViewModel(
viewModel = userViewModels.last()[0],
viewKey = 0,
- name = "zero",
+ name = Text.Loaded("zero"),
isSelectionMarkerVisible = true,
)
assertUserViewModel(
viewModel = userViewModels.last()[1],
viewKey = 1,
- name = "one",
+ name = Text.Loaded("one"),
isSelectionMarkerVisible = false,
)
assertUserViewModel(
viewModel = userViewModels.last()[2],
viewKey = 2,
- name = "two",
+ name = Text.Loaded("two"),
isSelectionMarkerVisible = false,
)
job.cancel()
}
@Test
- fun `maximumUserColumns - few users`() = selfCancelingTest {
+ fun `maximumUserColumns - few users`() = testScope.runTest {
setUsers(count = 2)
val values = mutableListOf<Int>()
val job = launch(testDispatcher) { underTest.maximumUserColumns.toList(values) }
@@ -240,7 +234,7 @@
}
@Test
- fun `maximumUserColumns - many users`() = selfCancelingTest {
+ fun `maximumUserColumns - many users`() = testScope.runTest {
setUsers(count = 5)
val values = mutableListOf<Int>()
val job = launch(testDispatcher) { underTest.maximumUserColumns.toList(values) }
@@ -250,7 +244,7 @@
}
@Test
- fun `isOpenMenuButtonVisible - has actions - true`() = selfCancelingTest {
+ fun `isOpenMenuButtonVisible - has actions - true`() = testScope.runTest {
setUsers(2)
val isVisible = mutableListOf<Boolean>()
@@ -261,7 +255,7 @@
}
@Test
- fun `isOpenMenuButtonVisible - no actions - false`() = selfCancelingTest {
+ fun `isOpenMenuButtonVisible - no actions - false`() = testScope.runTest {
val userInfos = setUsers(2)
userRepository.setSelectedUserInfo(userInfos[1])
keyguardRepository.setKeyguardShowing(true)
@@ -275,7 +269,7 @@
}
@Test
- fun menu() = selfCancelingTest {
+ fun menu() = testScope.runTest {
val isMenuVisible = mutableListOf<Boolean>()
val job = launch(testDispatcher) { underTest.isMenuVisible.toList(isMenuVisible) }
assertThat(isMenuVisible.last()).isFalse()
@@ -290,7 +284,7 @@
}
@Test
- fun `menu actions`() = selfCancelingTest {
+ fun `menu actions`() = testScope.runTest {
setUsers(2)
val actions = mutableListOf<List<UserActionViewModel>>()
val job = launch(testDispatcher) { underTest.menu.toList(actions) }
@@ -309,7 +303,7 @@
}
@Test
- fun `isFinishRequested - finishes when user is switched`() = selfCancelingTest {
+ fun `isFinishRequested - finishes when user is switched`() = testScope.runTest {
val userInfos = setUsers(count = 2)
val isFinishRequested = mutableListOf<Boolean>()
val job = launch(testDispatcher) { underTest.isFinishRequested.toList(isFinishRequested) }
@@ -323,7 +317,7 @@
}
@Test
- fun `isFinishRequested - finishes when the screen turns off`() = selfCancelingTest {
+ fun `isFinishRequested - finishes when the screen turns off`() = testScope.runTest {
setUsers(count = 2)
powerRepository.setInteractive(true)
val isFinishRequested = mutableListOf<Boolean>()
@@ -338,7 +332,7 @@
}
@Test
- fun `isFinishRequested - finishes when cancel button is clicked`() = selfCancelingTest {
+ fun `isFinishRequested - finishes when cancel button is clicked`() = testScope.runTest {
setUsers(count = 2)
powerRepository.setInteractive(true)
val isFinishRequested = mutableListOf<Boolean>()
@@ -356,6 +350,93 @@
job.cancel()
}
+ @Test
+ fun `guest selected -- name is exit guest`() = testScope.runTest {
+ val userInfos =
+ listOf(
+ UserInfo(
+ /* id= */ 0,
+ /* name= */ "zero",
+ /* iconPath= */ "",
+ /* flags= */ UserInfo.FLAG_PRIMARY or UserInfo.FLAG_ADMIN or UserInfo.FLAG_FULL,
+ UserManager.USER_TYPE_FULL_SYSTEM,
+ ),
+ UserInfo(
+ /* id= */ 1,
+ /* name= */ "one",
+ /* iconPath= */ "",
+ /* flags= */ UserInfo.FLAG_FULL,
+ UserManager.USER_TYPE_FULL_GUEST,
+ ),
+ )
+
+ userRepository.setUserInfos(userInfos)
+ userRepository.setSelectedUserInfo(userInfos[1])
+
+ val userViewModels = mutableListOf<List<UserViewModel>>()
+ val job = launch(testDispatcher) { underTest.users.toList(userViewModels) }
+
+ assertThat(userViewModels.last()).hasSize(2)
+ assertUserViewModel(
+ viewModel = userViewModels.last()[0],
+ viewKey = 0,
+ name = Text.Loaded("zero"),
+ isSelectionMarkerVisible = false,
+ )
+ assertUserViewModel(
+ viewModel = userViewModels.last()[1],
+ viewKey = 1,
+ name = Text.Resource(
+ com.android.settingslib.R.string.guest_exit_quick_settings_button
+ ),
+ isSelectionMarkerVisible = true,
+ )
+ job.cancel()
+ }
+
+ @Test
+ fun `guest not selected -- name is guest`() = testScope.runTest {
+ val userInfos =
+ listOf(
+ UserInfo(
+ /* id= */ 0,
+ /* name= */ "zero",
+ /* iconPath= */ "",
+ /* flags= */ UserInfo.FLAG_PRIMARY or UserInfo.FLAG_ADMIN or UserInfo.FLAG_FULL,
+ UserManager.USER_TYPE_FULL_SYSTEM,
+ ),
+ UserInfo(
+ /* id= */ 1,
+ /* name= */ "one",
+ /* iconPath= */ "",
+ /* flags= */ UserInfo.FLAG_FULL,
+ UserManager.USER_TYPE_FULL_GUEST,
+ ),
+ )
+
+ userRepository.setUserInfos(userInfos)
+ userRepository.setSelectedUserInfo(userInfos[0])
+ runCurrent()
+
+ val userViewModels = mutableListOf<List<UserViewModel>>()
+ val job = launch(testDispatcher) { underTest.users.toList(userViewModels) }
+
+ assertThat(userViewModels.last()).hasSize(2)
+ assertUserViewModel(
+ viewModel = userViewModels.last()[0],
+ viewKey = 0,
+ name = Text.Loaded("zero"),
+ isSelectionMarkerVisible = true,
+ )
+ assertUserViewModel(
+ viewModel = userViewModels.last()[1],
+ viewKey = 1,
+ name = Text.Loaded("one"),
+ isSelectionMarkerVisible = false,
+ )
+ job.cancel()
+ }
+
private suspend fun setUsers(count: Int): List<UserInfo> {
val userInfos =
(0 until count).map { index ->
@@ -384,26 +465,18 @@
private fun assertUserViewModel(
viewModel: UserViewModel?,
viewKey: Int,
- name: String,
+ name: Text,
isSelectionMarkerVisible: Boolean,
) {
checkNotNull(viewModel)
assertThat(viewModel.viewKey).isEqualTo(viewKey)
- assertThat(viewModel.name).isEqualTo(Text.Loaded(name))
+ assertThat(viewModel.name).isEqualTo(name)
assertThat(viewModel.isSelectionMarkerVisible).isEqualTo(isSelectionMarkerVisible)
assertThat(viewModel.alpha)
.isEqualTo(LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA)
assertThat(viewModel.onClicked).isNotNull()
}
- private fun selfCancelingTest(
- block: suspend TestScope.() -> Unit,
- ): TestResult =
- testScope.runTest {
- block()
- injectedScope.coroutineContext[Job.Key]?.cancelAndJoin()
- }
-
companion object {
private const val SUPERVISED_USER_CREATION_PACKAGE = "com.some.package"
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index db3b9b5..d31f0bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -1423,13 +1423,43 @@
assertStackCollapsed();
// Post status bar state change update with the same value
mBubbleController.onStatusBarStateChanged(false);
- // Stack should remain collapsedb
+ // Stack should remain collapsed
assertStackCollapsed();
// Post status bar state change which should trigger bubble to expand
mBubbleController.onStatusBarStateChanged(true);
assertStackExpanded();
}
+ /**
+ * Test to verify behavior for the following scenario:
+ * <ol>
+ * <li>device is locked with keyguard on, status bar shade state updates to
+ * <code>false</code></li>
+ * <li>notification entry is marked to be a bubble and it is set to auto-expand</li>
+ * <li>device unlock starts, status bar shade state receives another update to
+ * <code>false</code></li>
+ * <li>device is unlocked and status bar shade state is set to <code>true</code></li>
+ * <li>bubble should be expanded</li>
+ * </ol>
+ */
+ @Test
+ public void testOnStatusBarStateChanged_newAutoExpandedBubbleRemainsExpanded() {
+ // Set device as locked
+ mBubbleController.onStatusBarStateChanged(false);
+
+ // Create a auto-expanded bubble
+ NotificationEntry entry = mNotificationTestHelper.createAutoExpandedBubble();
+ mEntryListener.onEntryAdded(entry);
+
+ // When unlocking, we may receive duplicate updates with shade=false, ensure they don't
+ // clear the expanded state
+ mBubbleController.onStatusBarStateChanged(false);
+ mBubbleController.onStatusBarStateChanged(true);
+
+ // After unlocking, stack should be expanded
+ assertStackExpanded();
+ }
+
@Test
public void testSetShouldAutoExpand_notifiesFlagChanged() {
mBubbleController.updateBubble(mBubbleEntry);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
index fa3cc99..bf2235a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
@@ -136,6 +136,8 @@
InstrumentationRegistry.getArguments());
if (TestableLooper.get(this) != null) {
TestableLooper.get(this).processAllMessages();
+ // Must remove static reference to this test object to prevent leak (b/261039202)
+ TestableLooper.remove(this);
}
disallowTestableLooperAsMainThread();
mContext.cleanUpReceivers(this.getClass().getSimpleName());
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
index 52e0c982..ad086ff 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
@@ -22,12 +22,12 @@
import android.os.Handler
import android.os.Looper
import android.os.UserHandle
-import android.util.ArraySet
import android.util.Log
import com.android.systemui.SysuiTestableContext
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger
import com.android.systemui.dump.DumpManager
import com.android.systemui.settings.UserTracker
+import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.Executor
class FakeBroadcastDispatcher(
@@ -50,7 +50,7 @@
PendingRemovalStore(logger)
) {
- val registeredReceivers = ArraySet<BroadcastReceiver>()
+ val registeredReceivers: MutableSet<BroadcastReceiver> = ConcurrentHashMap.newKeySet()
override fun registerReceiverWithHandler(
receiver: BroadcastReceiver,
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
new file mode 100644
index 0000000..b7a8d2e
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.systemui.coroutines
+
+import kotlin.coroutines.CoroutineContext
+import kotlin.coroutines.EmptyCoroutineContext
+import kotlinx.coroutines.CoroutineStart
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+
+/** Collect [flow] in a new [Job] and return a getter for the last collected value. */
+fun <T> TestScope.collectLastValue(
+ flow: Flow<T>,
+ context: CoroutineContext = EmptyCoroutineContext,
+ start: CoroutineStart = CoroutineStart.DEFAULT,
+): () -> T? {
+ var lastValue: T? = null
+ backgroundScope.launch(context, start) { flow.collect { lastValue = it } }
+ return {
+ runCurrent()
+ lastValue
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 3601667..5c2a915 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -17,11 +17,15 @@
package com.android.systemui.keyguard.data.repository
+import android.graphics.Point
import com.android.systemui.common.shared.model.Position
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.StatusBarState
+import com.android.systemui.keyguard.shared.model.WakeSleepReason
import com.android.systemui.keyguard.shared.model.WakefulnessModel
+import com.android.systemui.keyguard.shared.model.WakefulnessState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -49,7 +53,7 @@
override val isDreaming: Flow<Boolean> = _isDreaming
private val _dozeAmount = MutableStateFlow(0f)
- override val dozeAmount: Flow<Float> = _dozeAmount
+ override val linearDozeAmount: Flow<Float> = _dozeAmount
private val _statusBarState = MutableStateFlow(StatusBarState.SHADE)
override val statusBarState: Flow<StatusBarState> = _statusBarState
@@ -57,8 +61,16 @@
private val _dozeTransitionModel = MutableStateFlow(DozeTransitionModel())
override val dozeTransitionModel: Flow<DozeTransitionModel> = _dozeTransitionModel
- private val _wakefulnessState = MutableStateFlow(WakefulnessModel.ASLEEP)
- override val wakefulnessState: Flow<WakefulnessModel> = _wakefulnessState
+ private val _wakefulnessModel =
+ MutableStateFlow(
+ WakefulnessModel(
+ WakefulnessState.ASLEEP,
+ false,
+ WakeSleepReason.OTHER,
+ WakeSleepReason.OTHER
+ )
+ )
+ override val wakefulness: Flow<WakefulnessModel> = _wakefulnessModel
private val _isUdfpsSupported = MutableStateFlow(false)
@@ -71,6 +83,15 @@
private val _biometricUnlockState = MutableStateFlow(BiometricUnlockModel.NONE)
override val biometricUnlockState: Flow<BiometricUnlockModel> = _biometricUnlockState
+ private val _fingerprintSensorLocation = MutableStateFlow<Point?>(null)
+ override val fingerprintSensorLocation: Flow<Point?> = _fingerprintSensorLocation
+
+ private val _faceSensorLocation = MutableStateFlow<Point?>(null)
+ override val faceSensorLocation: Flow<Point?> = _faceSensorLocation
+
+ private val _biometricUnlockSource = MutableStateFlow<BiometricUnlockSource?>(null)
+ override val biometricUnlockSource: Flow<BiometricUnlockSource?> = _biometricUnlockSource
+
override fun isKeyguardShowing(): Boolean {
return _isKeyguardShowing.value
}
@@ -99,6 +120,22 @@
_dozeAmount.value = dozeAmount
}
+ fun setBiometricUnlockState(state: BiometricUnlockModel) {
+ _biometricUnlockState.tryEmit(state)
+ }
+
+ fun setBiometricUnlockSource(source: BiometricUnlockSource?) {
+ _biometricUnlockSource.tryEmit(source)
+ }
+
+ fun setFaceSensorLocation(location: Point?) {
+ _faceSensorLocation.tryEmit(location)
+ }
+
+ fun setFingerprintSensorLocation(location: Point?) {
+ _fingerprintSensorLocation.tryEmit(location)
+ }
+
override fun isUdfpsSupported(): Boolean {
return _isUdfpsSupported.value
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt
new file mode 100644
index 0000000..7c22604
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt
@@ -0,0 +1,33 @@
+/*
+ * 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 com.android.systemui.keyguard.data.repository
+
+import com.android.systemui.statusbar.LightRevealEffect
+import kotlinx.coroutines.flow.MutableStateFlow
+
+/** Fake implementation of [LightRevealScrimRepository] */
+class FakeLightRevealScrimRepository : LightRevealScrimRepository {
+
+ private val _revealEffect: MutableStateFlow<LightRevealEffect> =
+ MutableStateFlow(DEFAULT_REVEAL_EFFECT)
+ override val revealEffect = _revealEffect
+
+ fun setRevealEffect(effect: LightRevealEffect) {
+ _revealEffect.tryEmit(effect)
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt
index c33ce5d..b31f119 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt
@@ -43,6 +43,9 @@
override val showFooterDot: MutableStateFlow<Boolean> = MutableStateFlow(showFooterDot)
+ override var includesUserVisibleJobs = false
+ private set
+
private val numRunningPackagesListeners = LinkedHashSet<OnNumberOfPackagesChangedListener>()
private val dialogDismissedListeners = LinkedHashSet<OnDialogDismissedListener>()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
index 63448e2..1a893f8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt
@@ -56,7 +56,8 @@
import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.util.settings.GlobalSettings
import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.test.TestCoroutineDispatcher
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestCoroutineScheduler
/**
* Util class to create real implementations of the FooterActions repositories, viewModel and
@@ -65,6 +66,7 @@
class FooterActionsTestUtils(
private val context: Context,
private val testableLooper: TestableLooper,
+ private val scheduler: TestCoroutineScheduler,
) {
/** Enable or disable the user switcher in the settings. */
fun setUserSwitcherEnabled(settings: GlobalSettings, enabled: Boolean, userId: Int) {
@@ -105,7 +107,7 @@
foregroundServicesRepository: ForegroundServicesRepository = foregroundServicesRepository(),
userSwitcherRepository: UserSwitcherRepository = userSwitcherRepository(),
broadcastDispatcher: BroadcastDispatcher = mock(),
- bgDispatcher: CoroutineDispatcher = TestCoroutineDispatcher(),
+ bgDispatcher: CoroutineDispatcher = StandardTestDispatcher(scheduler),
): FooterActionsInteractor {
return FooterActionsInteractorImpl(
activityStarter,
@@ -126,7 +128,7 @@
/** Create a [SecurityRepository] to be used in tests. */
fun securityRepository(
securityController: SecurityController = FakeSecurityController(),
- bgDispatcher: CoroutineDispatcher = TestCoroutineDispatcher(),
+ bgDispatcher: CoroutineDispatcher = StandardTestDispatcher(scheduler),
): SecurityRepository {
return SecurityRepositoryImpl(
securityController,
@@ -145,7 +147,7 @@
fun userSwitcherRepository(
@Application context: Context = this.context.applicationContext,
bgHandler: Handler = Handler(testableLooper.looper),
- bgDispatcher: CoroutineDispatcher = TestCoroutineDispatcher(),
+ bgDispatcher: CoroutineDispatcher = StandardTestDispatcher(scheduler),
userManager: UserManager = mock(),
userTracker: UserTracker = FakeUserTracker(),
userSwitcherController: UserSwitcherController = mock(),
diff --git a/packages/VpnDialogs/res/values-ar/strings.xml b/packages/VpnDialogs/res/values-ar/strings.xml
index 0e0581e..9307a74 100644
--- a/packages/VpnDialogs/res/values-ar/strings.xml
+++ b/packages/VpnDialogs/res/values-ar/strings.xml
@@ -34,8 +34,6 @@
<string name="disconnect" msgid="971412338304200056">"قطع الاتصال"</string>
<string name="open_app" msgid="3717639178595958667">"فتح التطبيق"</string>
<string name="dismiss" msgid="6192859333764711227">"تجاهل"</string>
- <!-- no translation found for sanitized_vpn_label_with_ellipsis (7014327474633422235) -->
- <skip />
- <!-- no translation found for sanitized_vpn_label (1877415015009794766) -->
- <skip />
+ <string name="sanitized_vpn_label_with_ellipsis" msgid="7014327474633422235">"<xliff:g id="SANITIZED_VPN_LABEL_WITH_ELLIPSIS_0">%1$s</xliff:g>… ( <xliff:g id="SANITIZED_VPN_LABEL_WITH_ELLIPSIS_1">%2$s</xliff:g>)"</string>
+ <string name="sanitized_vpn_label" msgid="1877415015009794766">"<xliff:g id="SANITIZED_VPN_LABEL_0">%1$s</xliff:g> ( <xliff:g id="SANITIZED_VPN_LABEL_1">%2$s</xliff:g>)"</string>
</resources>
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 786d407..e92150b 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -74,8 +74,10 @@
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
+import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
+import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowInfo;
@@ -200,6 +202,8 @@
final ComponentName mComponentName;
+ int mGenericMotionEventSources;
+
// the events pending events to be dispatched to this service
final SparseArray<AccessibilityEvent> mPendingEvents = new SparseArray<>();
@@ -362,6 +366,7 @@
}
mNotificationTimeout = info.notificationTimeout;
mIsDefault = (info.flags & DEFAULT) != 0;
+ mGenericMotionEventSources = info.getMotionEventSources();
if (supportsFlagForNotImportantViews(info)) {
if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) {
@@ -1751,6 +1756,11 @@
return mSystemSupport.getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId);
}
+ public boolean wantsGenericMotionEvent(MotionEvent event) {
+ final int eventSourceWithoutClass = event.getSource() & ~InputDevice.SOURCE_CLASS_MASK;
+ return (mGenericMotionEventSources & eventSourceWithoutClass) != 0;
+ }
+
/**
* Called by the invocation handler to notify the service that the
* state of magnification has changed.
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index d80117d..c87d1c8 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -141,6 +141,9 @@
*/
static final int FLAG_SEND_MOTION_EVENTS = 0x00000400;
+ /** Flag for intercepting generic motion events. */
+ static final int FLAG_FEATURE_INTERCEPT_GENERIC_MOTION_EVENTS = 0x00000800;
+
static final int FEATURES_AFFECTING_MOTION_EVENTS =
FLAG_FEATURE_INJECT_MOTION_EVENTS
| FLAG_FEATURE_AUTOCLICK
@@ -149,7 +152,8 @@
| FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER
| FLAG_SERVICE_HANDLES_DOUBLE_TAP
| FLAG_REQUEST_MULTI_FINGER_GESTURES
- | FLAG_REQUEST_2_FINGER_PASSTHROUGH;
+ | FLAG_REQUEST_2_FINGER_PASSTHROUGH
+ | FLAG_FEATURE_INTERCEPT_GENERIC_MOTION_EVENTS;
private final Context mContext;
@@ -182,6 +186,10 @@
private final SparseArray<EventStreamState> mTouchScreenStreamStates = new SparseArray<>(0);
+ // State tracking for generic MotionEvents is display-agnostic so we only need one.
+ private GenericMotionEventStreamState mGenericMotionEventStreamState;
+ private int mCombinedGenericMotionEventSources = 0;
+
private EventStreamState mKeyboardStreamState;
AccessibilityInputFilter(Context context, AccessibilityManagerService service) {
@@ -205,6 +213,7 @@
mInstalled = true;
disableFeatures();
enableFeatures();
+ mAms.onInputFilterInstalled(true);
super.onInstalled();
}
@@ -215,6 +224,7 @@
}
mInstalled = false;
disableFeatures();
+ mAms.onInputFilterInstalled(false);
super.onUninstalled();
}
@@ -296,7 +306,13 @@
private EventStreamState getEventStreamState(InputEvent event) {
if (event instanceof MotionEvent) {
final int displayId = event.getDisplayId();
+ if (mGenericMotionEventStreamState == null) {
+ mGenericMotionEventStreamState = new GenericMotionEventStreamState();
+ }
+ if (mGenericMotionEventStreamState.shouldProcessMotionEvent((MotionEvent) event)) {
+ return mGenericMotionEventStreamState;
+ }
if (event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)) {
EventStreamState touchScreenStreamState = mTouchScreenStreamStates.get(displayId);
if (touchScreenStreamState == null) {
@@ -362,8 +378,11 @@
mPm.userActivity(event.getEventTime(), false);
MotionEvent transformedEvent = MotionEvent.obtain(event);
final int displayId = event.getDisplayId();
- mEventHandler.get(isDisplayIdValid(displayId) ? displayId : Display.DEFAULT_DISPLAY)
- .onMotionEvent(transformedEvent, event, policyFlags);
+ EventStreamTransformation eventStreamTransformation = mEventHandler.get(
+ isDisplayIdValid(displayId) ? displayId : Display.DEFAULT_DISPLAY);
+ if (eventStreamTransformation != null) {
+ eventStreamTransformation.onMotionEvent(transformedEvent, event, policyFlags);
+ }
transformedEvent.recycle();
}
@@ -490,6 +509,19 @@
mTouchExplorer.put(displayId, explorer);
}
+ if ((mEnabledFeatures & FLAG_FEATURE_INTERCEPT_GENERIC_MOTION_EVENTS) != 0) {
+ addFirstEventHandler(displayId, new BaseEventStreamTransformation() {
+ @Override
+ public void onMotionEvent(MotionEvent event, MotionEvent rawEvent,
+ int policyFlags) {
+ if (!anyServiceWantsGenericMotionEvent(rawEvent)
+ || !mAms.sendMotionEventToListeningServices(rawEvent)) {
+ super.onMotionEvent(event, rawEvent, policyFlags);
+ }
+ }
+ });
+ }
+
if ((mEnabledFeatures & FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER) != 0
|| ((mEnabledFeatures & FLAG_FEATURE_SCREEN_MAGNIFIER) != 0)
|| ((mEnabledFeatures & FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER) != 0)) {
@@ -842,6 +874,32 @@
}
}
+ private class GenericMotionEventStreamState extends EventStreamState {
+ @Override
+ public boolean shouldProcessMotionEvent(MotionEvent event) {
+ return anyServiceWantsGenericMotionEvent(event);
+ }
+ @Override
+ public boolean shouldProcessScroll() {
+ return true;
+ }
+ }
+
+ private boolean anyServiceWantsGenericMotionEvent(MotionEvent event) {
+ // Disable SOURCE_TOUCHSCREEN generic event interception if any service is performing
+ // touch exploration.
+ if (event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)
+ && (mEnabledFeatures & FLAG_FEATURE_TOUCH_EXPLORATION) != 0) {
+ return false;
+ }
+ final int eventSourceWithoutClass = event.getSource() & ~InputDevice.SOURCE_CLASS_MASK;
+ return (mCombinedGenericMotionEventSources & eventSourceWithoutClass) != 0;
+ }
+
+ public void setCombinedGenericMotionEventSources(int sources) {
+ mCombinedGenericMotionEventSources = sources;
+ }
+
/**
* Keeps state of streams of events from all keyboard devices.
*/
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 630cd350..3145139 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -106,6 +106,8 @@
import android.util.SparseArray;
import android.view.Display;
import android.view.IWindow;
+import android.view.InputDevice;
+import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
import android.view.MotionEvent;
@@ -147,6 +149,7 @@
import com.android.server.accessibility.magnification.WindowMagnificationManager;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.pm.UserManagerInternal;
+import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -190,7 +193,7 @@
// TODO: Restructure service initialization so services aren't connected before all of
// their capabilities are ready.
- private static final int WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS = 1000;
+ private static final int WAIT_INPUT_FILTER_INSTALL_TIMEOUT_MS = 1000;
// This postpones state changes events when a window doesn't exist with the expectation that
@@ -258,6 +261,8 @@
private boolean mHasInputFilter;
+ private boolean mInputFilterInstalled;
+
private KeyEventDispatcher mKeyEventDispatcher;
private SparseArray<MotionEventInjector> mMotionEventInjectors;
@@ -517,6 +522,16 @@
return mFingerprintGestureDispatcher;
}
+ /**
+ * Called by the {@link AccessibilityInputFilter} when the filter install state changes.
+ */
+ public void onInputFilterInstalled(boolean installed) {
+ synchronized (mLock) {
+ mInputFilterInstalled = installed;
+ mLock.notifyAll();
+ }
+ }
+
private void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) {
@@ -1350,7 +1365,7 @@
}
}
- /** Send a motion event to the service to allow it to perform gesture detection. */
+ /** Send a motion event to the services. */
public boolean sendMotionEventToListeningServices(MotionEvent event) {
boolean result;
event = MotionEvent.obtain(event);
@@ -1453,7 +1468,7 @@
@Override
public @Nullable MotionEventInjector getMotionEventInjectorForDisplayLocked(int displayId) {
- final long endMillis = SystemClock.uptimeMillis() + WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS;
+ final long endMillis = SystemClock.uptimeMillis() + WAIT_INPUT_FILTER_INSTALL_TIMEOUT_MS;
MotionEventInjector motionEventInjector = null;
while ((mMotionEventInjectors == null) && (SystemClock.uptimeMillis() < endMillis)) {
try {
@@ -1707,7 +1722,9 @@
AccessibilityUserState state = getCurrentUserStateLocked();
for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
AccessibilityServiceConnection service = state.mBoundServices.get(i);
- if (service.isServiceDetectsGesturesEnabled(displayId)) {
+ if (service.wantsGenericMotionEvent(event)
+ || (event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)
+ && service.isServiceDetectsGesturesEnabled(displayId))) {
service.notifyMotionEvent(event);
result = true;
}
@@ -2302,6 +2319,13 @@
if (userState.isPerformGesturesEnabledLocked()) {
flags |= AccessibilityInputFilter.FLAG_FEATURE_INJECT_MOTION_EVENTS;
}
+ int combinedGenericMotionEventSources = 0;
+ for (AccessibilityServiceConnection connection : userState.mBoundServices) {
+ combinedGenericMotionEventSources |= connection.mGenericMotionEventSources;
+ }
+ if (combinedGenericMotionEventSources != 0) {
+ flags |= AccessibilityInputFilter.FLAG_FEATURE_INTERCEPT_GENERIC_MOTION_EVENTS;
+ }
if (flags != 0) {
if (!mHasInputFilter) {
mHasInputFilter = true;
@@ -2314,6 +2338,8 @@
setInputFilter = true;
}
mInputFilter.setUserAndEnabledFeatures(userState.mUserId, flags);
+ mInputFilter.setCombinedGenericMotionEventSources(
+ combinedGenericMotionEventSources);
} else {
if (mHasInputFilter) {
mHasInputFilter = false;
@@ -4646,6 +4672,29 @@
}
}
+ @Override
+ public void injectInputEventToInputFilter(InputEvent event) {
+ synchronized (mLock) {
+ final long endMillis =
+ SystemClock.uptimeMillis() + WAIT_INPUT_FILTER_INSTALL_TIMEOUT_MS;
+ while (!mInputFilterInstalled && (SystemClock.uptimeMillis() < endMillis)) {
+ try {
+ mLock.wait(endMillis - SystemClock.uptimeMillis());
+ } catch (InterruptedException ie) {
+ /* ignore */
+ }
+ }
+ }
+
+ if (mInputFilterInstalled && mInputFilter != null) {
+ mInputFilter.onInputEvent(event,
+ WindowManagerPolicy.FLAG_PASS_TO_USER | WindowManagerPolicy.FLAG_INJECTED);
+ } else {
+ Slog.w(LOG_TAG, "Cannot injectInputEventToInputFilter because the "
+ + "AccessibilityInputFilter is not installed.");
+ }
+ }
+
private final class SendWindowStateChangedEventRunnable implements Runnable {
private final AccessibilityEvent mPendingEvent;
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 2814196..f1ba5ff 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -355,10 +355,10 @@
private boolean activityMatchesDisplayCategory(ActivityInfo activityInfo) {
if (mDisplayCategories.isEmpty()) {
- return activityInfo.targetDisplayCategory == null;
+ return activityInfo.requiredDisplayCategory == null;
}
- return activityInfo.targetDisplayCategory != null
- && mDisplayCategories.contains(activityInfo.targetDisplayCategory);
+ return activityInfo.requiredDisplayCategory != null
+ && mDisplayCategories.contains(activityInfo.requiredDisplayCategory);
}
@@ -375,9 +375,9 @@
}
if (!activityMatchesDisplayCategory(activityInfo)) {
Slog.d(TAG, String.format(
- "The activity's target display category: %s is not found on virtual display"
- + " with the following allowed display categories: %s",
- activityInfo.targetDisplayCategory, mDisplayCategories.toString()));
+ "The activity's required display category: %s is not found on virtual display"
+ + " with the following categories: %s",
+ activityInfo.requiredDisplayCategory, mDisplayCategories.toString()));
return false;
}
final UserHandle activityUser =
diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java
index 551ffff..84c033c 100644
--- a/services/core/java/com/android/server/BootReceiver.java
+++ b/services/core/java/com/android/server/BootReceiver.java
@@ -341,7 +341,8 @@
// non-proto tombstones, even though proto tombstones do not support including the counter
// of events dropped since rate limiting activated yet.
DropboxRateLimiter.RateLimitResult rateLimitResult =
- sDropboxRateLimiter.shouldRateLimit(TAG_TOMBSTONE, processName);
+ sDropboxRateLimiter.shouldRateLimit(
+ proto ? TAG_TOMBSTONE_PROTO : TAG_TOMBSTONE, processName);
if (rateLimitResult.shouldRateLimit()) return;
HashMap<String, Long> timestamps = readTimestamps();
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 4539e9e..2a44e30 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -132,6 +132,7 @@
import android.app.usage.UsageEvents;
import android.appwidget.AppWidgetManagerInternal;
import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
import android.compat.annotation.EnabledSince;
import android.compat.annotation.Overridable;
import android.content.ComponentName;
@@ -150,6 +151,7 @@
import android.content.pm.ServiceInfo.ForegroundServiceType;
import android.os.Binder;
import android.os.Build;
+import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.Handler;
@@ -390,6 +392,14 @@
@EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
static final long FGS_START_EXCEPTION_CHANGE_ID = 174041399L;
+ /**
+ * If enabled, the FGS type check against the manifest FSG type will be enabled for
+ * instant apps too. Before U, this check was only done for non-instant apps.
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = VERSION_CODES.TIRAMISU)
+ static final long FGS_TYPE_CHECK_FOR_INSTANT_APPS = 261055255L;
+
final Runnable mLastAnrDumpClearer = new Runnable() {
@Override public void run() {
synchronized (mAm) {
@@ -1818,38 +1828,43 @@
android.Manifest.permission.FOREGROUND_SERVICE,
r.app.getPid(), r.appInfo.uid, "startForeground");
}
+ }
+ final int manifestType = r.serviceInfo.getForegroundServiceType();
+ // If passed in foreground service type is FOREGROUND_SERVICE_TYPE_MANIFEST,
+ // consider it is the same as manifest foreground service type.
+ if (foregroundServiceType == FOREGROUND_SERVICE_TYPE_MANIFEST) {
+ foregroundServiceType = manifestType;
+ }
- // TODO(short-service): This part really should be above the if block,
- // so we'll apply the same check for instant apps too.
- int manifestType = r.serviceInfo.getForegroundServiceType();
- // If passed in foreground service type is FOREGROUND_SERVICE_TYPE_MANIFEST,
- // consider it is the same as manifest foreground service type.
- if (foregroundServiceType == FOREGROUND_SERVICE_TYPE_MANIFEST) {
- foregroundServiceType = manifestType;
- }
-
- // Check the passed in foreground service type flags is a subset of manifest
- // foreground service type flags.
- final String prop = "debug.skip_fgs_manifest_type_check";
- if (((foregroundServiceType & manifestType) != foregroundServiceType)
- // When building a test app on Studio, the SDK may not have all the
- // FGS types yet. This debug flag will allow using FGS types that are
- // not set in the manifest.
- && !SystemProperties.getBoolean(prop, false)) {
- throw new IllegalArgumentException("foregroundServiceType "
+ // Check the passed in foreground service type flags is a subset of manifest
+ // foreground service type flags.
+ final String prop = "debug.skip_fgs_manifest_type_check";
+ if (((foregroundServiceType & manifestType) != foregroundServiceType)
+ // When building a test app on Studio, the SDK may not have all the
+ // FGS types yet. This debug flag will allow using FGS types that are
+ // not set in the manifest.
+ && !SystemProperties.getBoolean(prop, false)) {
+ final String message = "foregroundServiceType "
+ String.format("0x%08X", foregroundServiceType)
+ " is not a subset of foregroundServiceType attribute "
- + String.format("0x%08X", manifestType)
- + " in service element of manifest file");
+ + String.format("0x%08X", manifestType)
+ + " in service element of manifest file";
+ if (!r.appInfo.isInstantApp()
+ || CompatChanges.isChangeEnabled(FGS_TYPE_CHECK_FOR_INSTANT_APPS,
+ r.appInfo.uid)) {
+ throw new IllegalArgumentException(message);
+ } else {
+ Slog.w(TAG, message + "\n"
+ + "This will be an exception once the target SDK level is UDC");
}
- if ((foregroundServiceType & FOREGROUND_SERVICE_TYPE_SHORT_SERVICE) != 0
- && foregroundServiceType != FOREGROUND_SERVICE_TYPE_SHORT_SERVICE) {
- Slog.w(TAG_SERVICE, "startForeground(): FOREGROUND_SERVICE_TYPE_SHORT_SERVICE"
- + " is combined with other types. SHORT_SERVICE will be ignored.");
- // In this case, the service will be handled as a non-short, regular FGS
- // anyway, so we just remove the SHORT_SERVICE type.
- foregroundServiceType &= ~FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
- }
+ }
+ if ((foregroundServiceType & FOREGROUND_SERVICE_TYPE_SHORT_SERVICE) != 0
+ && foregroundServiceType != FOREGROUND_SERVICE_TYPE_SHORT_SERVICE) {
+ Slog.w(TAG_SERVICE, "startForeground(): FOREGROUND_SERVICE_TYPE_SHORT_SERVICE"
+ + " is combined with other types. SHORT_SERVICE will be ignored.");
+ // In this case, the service will be handled as a non-short, regular FGS
+ // anyway, so we just remove the SHORT_SERVICE type.
+ foregroundServiceType &= ~FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
}
boolean alreadyStartedOp = false;
@@ -2981,6 +2996,20 @@
}
}
+ boolean shouldServiceTimeOutLocked(ComponentName className, IBinder token) {
+ final int userId = UserHandle.getCallingUserId();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ ServiceRecord sr = findServiceLocked(className, token, userId);
+ if (sr == null) {
+ return false;
+ }
+ return sr.shouldTriggerShortFgsTimeout();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
void onShortFgsAnrTimeout(ServiceRecord sr) {
final String reason = "A foreground service of FOREGROUND_SERVICE_TYPE_SHORT_SERVICE"
+ " did not stop within a timeout: " + sr.getComponentName();
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c51e14f..7566bab 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -12983,6 +12983,13 @@
}
@Override
+ public boolean shouldServiceTimeOut(ComponentName className, IBinder token) {
+ synchronized (this) {
+ return mServices.shouldServiceTimeOutLocked(className, token);
+ }
+ }
+
+ @Override
public int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
boolean requireFull, String name, String callerPackage) {
return mUserController.handleIncomingUser(callingPid, callingUid, userId, allowAll,
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 7946cb7..0b94798 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -906,7 +906,8 @@
}
}
- // TODO(b/239982558): might need to support --displayId as well
+ // NOTE: current profiles can only be started on default display (even on automotive builds with
+ // passenger displays), so there's no need to pass a display-id
private int runProfile(PrintWriter pw) throws RemoteException {
final PrintWriter err = getErrPrintWriter();
String profileFile = null;
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 937bbc9c..4d559b0 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -4205,7 +4205,7 @@
total - mLruProcessServiceStart);
writeProcessOomListToProto(proto,
ActivityManagerServiceDumpProcessesProto.LruProcesses.LIST, mService,
- mLruProcesses, false, dumpPackage);
+ mLruProcesses, true, dumpPackage);
proto.end(lruToken);
}
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 547c20b..0d1a6d5 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -364,9 +364,6 @@
* Note, we do _not_ check the "start id" here, because the start id increments if the
* app calls startService() or startForegroundService() on the same service,
* but that will _not_ update the ShortFgsInfo, and will not extend the timeout.
- *
- * TODO(short-service): Make sure, calling startService will not extend or remove the
- * timeout, in CTS.
*/
boolean isCurrent() {
return this.mStartForegroundCount == ServiceRecord.this.mStartForegroundCount;
@@ -897,7 +894,9 @@
* has no reason to start again. Note this condition doesn't consider the bindings.
*/
boolean canStopIfKilled(boolean isStartCanceled) {
- // TODO(short-service): If it's a "short FGS", we should stop it if killed.
+ if (isShortFgs()) { // Short-FGS should always stop if killed.
+ return true;
+ }
return startRequested && (stopIfKilled || isStartCanceled) && pendingStarts.isEmpty();
}
@@ -1361,7 +1360,9 @@
// Note if the type contains FOREGROUND_SERVICE_TYPE_SHORT_SERVICE but also other bits
// set, it's _not_ considered be a short service. (because we shouldn't apply
// the short-service restrictions)
- return isForeground
+ // (But we should be preventing mixture of FOREGROUND_SERVICE_TYPE_SHORT_SERVICE
+ // and other types in Service.startForeground().)
+ return startRequested && isForeground
&& (foregroundServiceType == ServiceInfo.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE);
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 2ea49b3..3f8333a 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1073,9 +1073,6 @@
uss.setState(UserState.STATE_STOPPING);
UserManagerInternal userManagerInternal = mInjector.getUserManagerInternal();
userManagerInternal.setUserState(userId, uss.state);
- // TODO(b/239982558): for now we're just updating the user's visibility, but most likely
- // we'll need to remove this call and handle that as part of the user state workflow
- // instead.
userManagerInternal.unassignUserFromDisplayOnStop(userId);
updateStartedUserArrayLU();
@@ -1505,13 +1502,32 @@
return startUserNoChecks(userId, Display.DEFAULT_DISPLAY, foreground, unlockListener);
}
- // TODO(b/239982558): add javadoc (need to wait until the intents / SystemService callbacks are
- // defined
+ /**
+ * Starts a user in background and make it visible in the given display.
+ *
+ * <p>This call will trigger the usual "user started" lifecycle events (i.e., `SystemService`
+ * callbacks and app intents), plus a call to
+ * {@link UserManagerInternal.UserVisibilityListener#onUserVisibilityChanged(int, boolean)} if
+ * the user visibility changed. Notice that the visibility change is independent of the user
+ * workflow state, and they can mismatch in some corner events (for example, if the user was
+ * already running in the background but not associated with a display, this call for that user
+ * would not trigger any lifecycle event but would trigger {@code onUserVisibilityChanged}).
+ *
+ * <p>See {@link ActivityManager#startUserInBackgroundOnSecondaryDisplay(int, int)} for more
+ * semantics.
+ *
+ * @param userId user to be started
+ * @param displayId display where the user will be visible
+ *
+ * @return whether the user was started
+ */
boolean startUserOnSecondaryDisplay(@UserIdInt int userId, int displayId) {
checkCallingHasOneOfThosePermissions("startUserOnSecondaryDisplay",
MANAGE_USERS, INTERACT_ACROSS_USERS);
// DEFAULT_DISPLAY is used for the current foreground user only
+ // TODO(b/245939659): might need to move this check to UserVisibilityMediator to support
+ // passenger-only screens
Preconditions.checkArgument(displayId != Display.DEFAULT_DISPLAY,
"Cannot use DEFAULT_DISPLAY");
@@ -1519,7 +1535,7 @@
return startUserNoChecks(userId, displayId, /* foreground= */ false,
/* unlockListener= */ null);
} catch (RuntimeException e) {
- Slogf.w(TAG, "startUserOnSecondaryDisplay(%d, %d) failed: %s", userId, displayId, e);
+ Slogf.e(TAG, "startUserOnSecondaryDisplay(%d, %d) failed: %s", userId, displayId, e);
return false;
}
}
@@ -1618,7 +1634,6 @@
return false;
}
- // TODO(b/239982558): might need something similar for bg users on secondary display
if (foreground && isUserSwitchUiEnabled()) {
t.traceBegin("startFreezingScreen");
mInjector.getWindowManager().startFreezingScreen(
@@ -1674,9 +1689,9 @@
userSwitchUiEnabled = mUserSwitchUiEnabled;
}
mInjector.updateUserConfiguration();
- // TODO(b/244644281): updateProfileRelatedCaches() is called on both if and else
- // parts, ideally it should be moved outside, but for now it's not as there are many
- // calls to external components here afterwards
+ // NOTE: updateProfileRelatedCaches() is called on both if and else parts, ideally
+ // it should be moved outside, but for now it's not as there are many calls to
+ // external components here afterwards
updateProfileRelatedCaches();
mInjector.getWindowManager().setCurrentUser(userId);
mInjector.reportCurWakefulnessUsageEvent();
@@ -1769,7 +1784,7 @@
if (foreground) {
t.traceBegin("moveUserToForeground");
- moveUserToForeground(uss, oldUserId, userId);
+ moveUserToForeground(uss, userId);
t.traceEnd();
} else {
t.traceBegin("finishUserBoot");
@@ -1983,21 +1998,25 @@
/** Called on handler thread */
@VisibleForTesting
- void dispatchUserSwitchComplete(@UserIdInt int userId) {
+ void dispatchUserSwitchComplete(@UserIdInt int oldUserId, @UserIdInt int newUserId) {
final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
- t.traceBegin("dispatchUserSwitchComplete-" + userId);
+ t.traceBegin("dispatchUserSwitchComplete-" + newUserId);
mInjector.getWindowManager().setSwitchingUser(false);
final int observerCount = mUserSwitchObservers.beginBroadcast();
for (int i = 0; i < observerCount; i++) {
try {
- t.traceBegin("onUserSwitchComplete-" + userId + " #" + i + " "
+ t.traceBegin("onUserSwitchComplete-" + newUserId + " #" + i + " "
+ mUserSwitchObservers.getBroadcastCookie(i));
- mUserSwitchObservers.getBroadcastItem(i).onUserSwitchComplete(userId);
+ mUserSwitchObservers.getBroadcastItem(i).onUserSwitchComplete(newUserId);
t.traceEnd();
} catch (RemoteException e) {
+ // Ignore
}
}
mUserSwitchObservers.finishBroadcast();
+ t.traceBegin("sendUserSwitchBroadcasts-" + oldUserId + "-" + newUserId);
+ sendUserSwitchBroadcasts(oldUserId, newUserId);
+ t.traceEnd();
t.traceEnd();
}
@@ -2159,7 +2178,8 @@
// Do the keyguard dismiss and unfreeze later
mHandler.removeMessages(COMPLETE_USER_SWITCH_MSG);
- mHandler.sendMessage(mHandler.obtainMessage(COMPLETE_USER_SWITCH_MSG, newUserId, 0));
+ mHandler.sendMessage(mHandler.obtainMessage(
+ COMPLETE_USER_SWITCH_MSG, oldUserId, newUserId));
uss.switching = false;
stopGuestOrEphemeralUserIfBackground(oldUserId);
@@ -2169,7 +2189,7 @@
}
@VisibleForTesting
- void completeUserSwitch(int newUserId) {
+ void completeUserSwitch(int oldUserId, int newUserId) {
final boolean isUserSwitchUiEnabled = isUserSwitchUiEnabled();
final Runnable runnable = () -> {
if (isUserSwitchUiEnabled) {
@@ -2177,7 +2197,7 @@
}
mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG);
mHandler.sendMessage(mHandler.obtainMessage(
- REPORT_USER_SWITCH_COMPLETE_MSG, newUserId, 0));
+ REPORT_USER_SWITCH_COMPLETE_MSG, oldUserId, newUserId));
};
// If there is no challenge set, dismiss the keyguard right away
@@ -2202,7 +2222,7 @@
t.traceEnd();
}
- private void moveUserToForeground(UserState uss, int oldUserId, int newUserId) {
+ private void moveUserToForeground(UserState uss, int newUserId) {
boolean homeInFront = mInjector.taskSupervisorSwitchUser(newUserId, uss);
if (homeInFront) {
mInjector.startHomeActivity(newUserId, "moveUserToForeground");
@@ -2210,7 +2230,6 @@
mInjector.taskSupervisorResumeFocusedStackTopActivity();
}
EventLogTags.writeAmSwitchUser(newUserId);
- sendUserSwitchBroadcasts(oldUserId, newUserId);
}
void sendUserSwitchBroadcasts(int oldUserId, int newUserId) {
@@ -3080,9 +3099,8 @@
dispatchForegroundProfileChanged(msg.arg1);
break;
case REPORT_USER_SWITCH_COMPLETE_MSG:
- dispatchUserSwitchComplete(msg.arg1);
-
- logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_SWITCH_USER,
+ dispatchUserSwitchComplete(msg.arg1, msg.arg2);
+ logUserLifecycleEvent(msg.arg2, USER_LIFECYCLE_EVENT_SWITCH_USER,
USER_LIFECYCLE_EVENT_STATE_FINISH);
break;
case REPORT_LOCKED_BOOT_COMPLETE_MSG:
@@ -3100,7 +3118,7 @@
logAndClearSessionId(msg.arg1);
break;
case COMPLETE_USER_SWITCH_MSG:
- completeUserSwitch(msg.arg1);
+ completeUserSwitch(msg.arg1, msg.arg2);
break;
}
return false;
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 2f147c4..cb409fe 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
@@ -278,13 +278,6 @@
return -1;
}
- if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) {
- // If this happens, something in KeyguardUpdateMonitor is wrong. This should only
- // ever be invoked when the user is encrypted or lockdown.
- Slog.e(TAG, "detectFace invoked when user is not encrypted or lockdown");
- return -1;
- }
-
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for detectFace");
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 7b60421..d499d01 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -483,8 +483,7 @@
private static boolean isInteractivePolicy(int policy) {
return policy == DisplayPowerRequest.POLICY_BRIGHT
- || policy == DisplayPowerRequest.POLICY_DIM
- || policy == DisplayPowerRequest.POLICY_VR;
+ || policy == DisplayPowerRequest.POLICY_DIM;
}
private boolean setScreenBrightnessByUser(float brightness) {
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 523a2dc..c1e9526 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -1941,8 +1941,8 @@
}
private void setProxSensorUnspecified() {
- mProximitySensor.name = "";
- mProximitySensor.type = "";
+ mProximitySensor.name = null;
+ mProximitySensor.type = null;
}
private void loadProxSensorFromDdc(DisplayConfiguration config) {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index c5cb08d..1d04f2e 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1573,7 +1573,7 @@
mSyncRoot.notifyAll();
}
- sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
+ sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
Runnable work = updateDisplayStateLocked(device);
if (work != null) {
@@ -1592,7 +1592,7 @@
// We don't bother invalidating the display info caches here because any changes to the
// display info will trigger a cache invalidation inside of LogicalDisplay before we hit
// this point.
- sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+ sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
scheduleTraversalLocked(false);
mPersistentDataStore.saveIfNeeded();
@@ -1622,7 +1622,7 @@
mDisplayStates.delete(displayId);
mDisplayBrightnesses.delete(displayId);
DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
- sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
+ sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
scheduleTraversalLocked(false);
if (mDisplayWindowPolicyControllers.contains(displayId)) {
@@ -1638,23 +1638,13 @@
}
private void handleLogicalDisplaySwappedLocked(@NonNull LogicalDisplay display) {
- final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
- final Runnable work = updateDisplayStateLocked(device);
- if (work != null) {
- mHandler.post(work);
- }
- final int displayId = display.getDisplayIdLocked();
+ handleLogicalDisplayChangedLocked(display);
+ final int displayId = display.getDisplayIdLocked();
if (displayId == Display.DEFAULT_DISPLAY) {
notifyDefaultDisplayDeviceUpdated(display);
}
- DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
- if (dpc != null) {
- dpc.onDisplayChanged();
- }
- mPersistentDataStore.saveIfNeeded();
mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATIONS);
- handleLogicalDisplayChangedLocked(display);
}
private void notifyDefaultDisplayDeviceUpdated(LogicalDisplay display) {
@@ -1666,7 +1656,7 @@
final int displayId = display.getDisplayIdLocked();
final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
- dpc.onDeviceStateTransition();
+ dpc.onDisplayChanged();
}
}
@@ -2366,9 +2356,13 @@
}
}
- private void sendDisplayEventLocked(int displayId, @DisplayEvent int event) {
- Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
- mHandler.sendMessage(msg);
+ private void sendDisplayEventLocked(@NonNull LogicalDisplay display, @DisplayEvent int event) {
+ // Only send updates outside of DisplayManagerService for enabled displays
+ if (display.isEnabledLocked()) {
+ int displayId = display.getDisplayIdLocked();
+ Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
+ mHandler.sendMessage(msg);
+ }
}
private void sendDisplayGroupEvent(int groupId, int event) {
@@ -2653,8 +2647,7 @@
}
private void handleBrightnessChange(LogicalDisplay display) {
- sendDisplayEventLocked(display.getDisplayIdLocked(),
- DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED);
+ sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED);
}
private DisplayDevice getDeviceForDisplayLocked(int displayId) {
@@ -2871,12 +2864,12 @@
* Returns the list of all display ids.
*/
@Override // Binder call
- public int[] getDisplayIds() {
+ public int[] getDisplayIds(boolean includeDisabled) {
final int callingUid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- return mLogicalDisplayMapper.getDisplayIdsLocked(callingUid);
+ return mLogicalDisplayMapper.getDisplayIdsLocked(callingUid, includeDisabled);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -3367,6 +3360,11 @@
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
+ LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(
+ displayId, /* includeDisabled= */ false);
+ if (display == null || !display.isEnabledLocked()) {
+ return null;
+ }
DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
return dpc.getBrightnessInfo();
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 306b8cf..405a2b9 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -16,6 +16,7 @@
package com.android.server.display;
+import static android.hardware.display.DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED;
import static android.hardware.display.DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE;
import static android.os.PowerManager.BRIGHTNESS_INVALID;
@@ -48,7 +49,7 @@
import android.provider.DeviceConfig;
import android.provider.DeviceConfigInterface;
import android.provider.Settings;
-import android.sysprop.DisplayProperties;
+import android.sysprop.SurfaceFlingerProperties;
import android.text.TextUtils;
import android.util.IndentingPrintWriter;
import android.util.Pair;
@@ -137,8 +138,7 @@
private boolean mAlwaysRespectAppRequest;
- // TODO(b/241447632): remove the flag once SF changes are ready
- private final boolean mRenderFrameRateIsPhysicalRefreshRate;
+ private final boolean mSupportsFrameRateOverride;
/**
* The allowed refresh rate switching type. This is used by SurfaceFlinger.
@@ -175,7 +175,7 @@
mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler(),
mDeviceConfigDisplaySettings);
mAlwaysRespectAppRequest = false;
- mRenderFrameRateIsPhysicalRefreshRate = injector.renderFrameRateIsPhysicalRefreshRate();
+ mSupportsFrameRateOverride = injector.supportsFrameRateOverride();
}
/**
@@ -237,21 +237,6 @@
}
}
- if (mRenderFrameRateIsPhysicalRefreshRate) {
- for (int i = 0; i < votes.size(); i++) {
-
- Vote vote = votes.valueAt(i);
- vote.refreshRateRanges.physical.min = Math.max(vote.refreshRateRanges.physical.min,
- vote.refreshRateRanges.render.min);
- vote.refreshRateRanges.physical.max = Math.min(vote.refreshRateRanges.physical.max,
- vote.refreshRateRanges.render.max);
- vote.refreshRateRanges.render.min = Math.max(vote.refreshRateRanges.physical.min,
- vote.refreshRateRanges.render.min);
- vote.refreshRateRanges.render.max = Math.min(vote.refreshRateRanges.physical.max,
- vote.refreshRateRanges.render.max);
- }
- }
-
return votes;
}
@@ -279,6 +264,18 @@
disableRefreshRateSwitching = false;
appRequestBaseModeRefreshRate = 0f;
}
+
+ @Override
+ public String toString() {
+ return "minPhysicalRefreshRate=" + minPhysicalRefreshRate
+ + ", maxPhysicalRefreshRate=" + maxPhysicalRefreshRate
+ + ", minRenderFrameRate=" + minRenderFrameRate
+ + ", maxRenderFrameRate=" + maxRenderFrameRate
+ + ", width=" + width
+ + ", height=" + height
+ + ", disableRefreshRateSwitching=" + disableRefreshRateSwitching
+ + ", appRequestBaseModeRefreshRate=" + appRequestBaseModeRefreshRate;
+ }
}
// VoteSummary is returned as an output param to cut down a bit on the number of temporary
@@ -332,18 +329,8 @@
}
if (mLoggingEnabled) {
- Slog.w(TAG, "Vote summary for priority "
- + Vote.priorityToString(priority)
- + ": width=" + summary.width
- + ", height=" + summary.height
- + ", minPhysicalRefreshRate=" + summary.minPhysicalRefreshRate
- + ", maxPhysicalRefreshRate=" + summary.maxPhysicalRefreshRate
- + ", minRenderFrameRate=" + summary.minRenderFrameRate
- + ", maxRenderFrameRate=" + summary.maxRenderFrameRate
- + ", disableRefreshRateSwitching="
- + summary.disableRefreshRateSwitching
- + ", appRequestBaseModeRefreshRate="
- + summary.appRequestBaseModeRefreshRate);
+ Slog.w(TAG, "Vote summary for priority " + Vote.priorityToString(priority)
+ + ": " + summary);
}
}
}
@@ -377,6 +364,23 @@
return !availableModes.isEmpty() ? availableModes.get(0) : null;
}
+ private void disableModeSwitching(VoteSummary summary, float fps) {
+ summary.minPhysicalRefreshRate = summary.maxPhysicalRefreshRate = fps;
+ summary.maxRenderFrameRate = Math.min(summary.maxRenderFrameRate, fps);
+
+ if (mLoggingEnabled) {
+ Slog.i(TAG, "Disabled mode switching on summary: " + summary);
+ }
+ }
+
+ private void disableRenderRateSwitching(VoteSummary summary) {
+ summary.minRenderFrameRate = summary.maxRenderFrameRate;
+
+ if (mLoggingEnabled) {
+ Slog.i(TAG, "Disabled render rate switching on summary: " + summary);
+ }
+ }
+
/**
* Calculates the refresh rate ranges and display modes that the system is allowed to freely
* switch between based on global and display-specific constraints.
@@ -405,7 +409,7 @@
int highestConsideredPriority = Vote.MAX_PRIORITY;
if (mAlwaysRespectAppRequest) {
- lowestConsideredPriority = Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE;
+ lowestConsideredPriority = Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE;
highestConsideredPriority = Vote.PRIORITY_APP_REQUEST_SIZE;
}
@@ -533,19 +537,15 @@
if (modeSwitchingDisabled || primarySummary.disableRefreshRateSwitching) {
float fps = baseMode.getRefreshRate();
- primarySummary.minPhysicalRefreshRate = primarySummary.maxPhysicalRefreshRate = fps;
+ disableModeSwitching(primarySummary, fps);
if (modeSwitchingDisabled) {
- appRequestSummary.minPhysicalRefreshRate =
- appRequestSummary.maxPhysicalRefreshRate = fps;
- }
- }
+ disableModeSwitching(appRequestSummary, fps);
+ disableRenderRateSwitching(primarySummary);
- if (mModeSwitchingType == DisplayManager.SWITCHING_TYPE_NONE
- || mRenderFrameRateIsPhysicalRefreshRate) {
- primarySummary.minRenderFrameRate = primarySummary.minPhysicalRefreshRate;
- primarySummary.maxRenderFrameRate = primarySummary.maxPhysicalRefreshRate;
- appRequestSummary.minRenderFrameRate = appRequestSummary.minPhysicalRefreshRate;
- appRequestSummary.maxRenderFrameRate = appRequestSummary.maxPhysicalRefreshRate;
+ if (mModeSwitchingType == DisplayManager.SWITCHING_TYPE_NONE) {
+ disableRenderRateSwitching(appRequestSummary);
+ }
+ }
}
boolean allowGroupSwitching =
@@ -611,6 +611,22 @@
continue;
}
+ // The physical refresh rate must be in the render frame rate range, unless
+ // frame rate override is supported.
+ if (!mSupportsFrameRateOverride) {
+ if (physicalRefreshRate < (summary.minRenderFrameRate - FLOAT_TOLERANCE)
+ || physicalRefreshRate > (summary.maxRenderFrameRate + FLOAT_TOLERANCE)) {
+ if (mLoggingEnabled) {
+ Slog.w(TAG, "Discarding mode " + mode.getModeId()
+ + ", outside render rate bounds"
+ + ": minPhysicalRefreshRate=" + summary.minPhysicalRefreshRate
+ + ", maxPhysicalRefreshRate=" + summary.maxPhysicalRefreshRate
+ + ", modeRefreshRate=" + physicalRefreshRate);
+ }
+ continue;
+ }
+ }
+
// Check whether the render frame rate range is achievable by the mode's physical
// refresh rate, meaning that if a divisor of the physical refresh rate is in range
// of the render frame rate.
@@ -1640,7 +1656,7 @@
SparseArray<Display.Mode[]> modes = new SparseArray<>();
SparseArray<Display.Mode> defaultModes = new SparseArray<>();
DisplayInfo info = new DisplayInfo();
- Display[] displays = dm.getDisplays();
+ Display[] displays = dm.getDisplays(DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
for (Display d : displays) {
final int displayId = d.getDisplayId();
d.getDisplayInfo(info);
@@ -2517,7 +2533,8 @@
sensorManager.addProximityActiveListener(BackgroundThread.getExecutor(), this);
synchronized (mSensorObserverLock) {
- for (Display d : mDisplayManager.getDisplays()) {
+ for (Display d : mDisplayManager.getDisplays(
+ DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED)) {
mDozeStateByDisplay.put(d.getDisplayId(), mInjector.isDozeState(d));
}
}
@@ -2528,7 +2545,8 @@
}
private void recalculateVotesLocked() {
- final Display[] displays = mDisplayManager.getDisplays();
+ final Display[] displays = mDisplayManager.getDisplays(
+ DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
for (Display d : displays) {
int displayId = d.getDisplayId();
Vote vote = null;
@@ -2976,7 +2994,7 @@
IThermalService getThermalService();
- boolean renderFrameRateIsPhysicalRefreshRate();
+ boolean supportsFrameRateOverride();
}
@VisibleForTesting
@@ -3031,9 +3049,11 @@
}
@Override
- public boolean renderFrameRateIsPhysicalRefreshRate() {
- return DisplayProperties
- .debug_render_frame_rate_is_physical_refresh_rate().orElse(true);
+ public boolean supportsFrameRateOverride() {
+ return SurfaceFlingerProperties.enable_frame_rate_override().orElse(false)
+ && !SurfaceFlingerProperties.frame_rate_override_for_native_rates()
+ .orElse(true)
+ && SurfaceFlingerProperties.frame_rate_override_global().orElse(false);
}
private DisplayManager getDisplayManager() {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index d6f0fd0..de26abc 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -219,15 +219,6 @@
private final float mScreenBrightnessDefault;
- // The minimum allowed brightness while in VR.
- private final float mScreenBrightnessForVrRangeMinimum;
-
- // The maximum allowed brightness while in VR.
- private final float mScreenBrightnessForVrRangeMaximum;
-
- // The default screen brightness for VR.
- private final float mScreenBrightnessForVrDefault;
-
// True if auto-brightness should be used.
private boolean mUseSoftwareAutoBrightnessConfig;
@@ -450,9 +441,6 @@
// PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary brightness set.
private float mTemporaryScreenBrightness;
- // The current screen brightness while in VR mode.
- private float mScreenBrightnessForVr;
-
// The last auto brightness adjustment that was set by the user and not temporary. Set to
// Float.NaN when an auto-brightness adjustment hasn't been recorded yet.
private float mAutoBrightnessAdjustment;
@@ -497,6 +485,9 @@
private final String mSuspendBlockerIdProxNegative;
private final String mSuspendBlockerIdProxDebounce;
+ private boolean mIsEnabled;
+ private boolean mIsInTransition;
+
/**
* Creates the display power controller.
*/
@@ -520,6 +511,8 @@
mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
mDisplayStatsId = mUniqueDisplayId.hashCode();
+ mIsEnabled = logicalDisplay.isEnabledLocked();
+ mIsInTransition = logicalDisplay.isInTransitionLocked();
mHandler = new DisplayControllerHandler(handler.getLooper());
mLastBrightnessEvent = new BrightnessEvent(mDisplayId);
mTempBrightnessEvent = new BrightnessEvent(mDisplayId);
@@ -558,14 +551,6 @@
mScreenBrightnessDefault = clampAbsoluteBrightness(
mLogicalDisplay.getDisplayInfoLocked().brightnessDefault);
- // VR SETTINGS
- mScreenBrightnessForVrDefault = clampAbsoluteBrightness(
- pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR));
- mScreenBrightnessForVrRangeMaximum = clampAbsoluteBrightness(
- pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR));
- mScreenBrightnessForVrRangeMinimum = clampAbsoluteBrightness(
- pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR));
-
mAllowAutoBrightnessWhileDozingConfig = resources.getBoolean(
com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing);
@@ -638,7 +623,6 @@
loadProximitySensor();
mCurrentScreenBrightnessSetting = getScreenBrightnessSetting();
- mScreenBrightnessForVr = getScreenBrightnessForVrSetting();
mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
@@ -807,29 +791,36 @@
final DisplayDeviceConfig config = device.getDisplayDeviceConfig();
final IBinder token = device.getDisplayTokenLocked();
final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
+ final boolean isEnabled = mLogicalDisplay.isEnabledLocked();
+ final boolean isInTransition = mLogicalDisplay.isInTransitionLocked();
mHandler.post(() -> {
+ boolean changed = false;
if (mDisplayDevice != device) {
+ changed = true;
mDisplayDevice = device;
mUniqueDisplayId = uniqueId;
mDisplayStatsId = mUniqueDisplayId.hashCode();
mDisplayDeviceConfig = config;
loadFromDisplayDeviceConfig(token, info);
+
+ // Since the underlying display-device changed, we really don't know the
+ // last command that was sent to change it's state. Lets assume it is unknown so
+ // that we trigger a change immediately.
+ mPowerState.resetScreenState();
+ }
+ if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) {
+ changed = true;
+ mIsEnabled = isEnabled;
+ mIsInTransition = isInTransition;
+ }
+
+ if (changed) {
updatePowerState();
}
});
}
/**
- * Called when the displays are preparing to transition from one device state to another.
- * This process involves turning off some displays so we need updatePowerState() to run and
- * calculate the new state.
- */
- @Override
- public void onDeviceStateTransition() {
- sendUpdatePowerState();
- }
-
- /**
* Unregisters all listeners and interrupts all running threads; halting future work.
*
* This method should be called when the DisplayPowerController is no longer in use; i.e. when
@@ -937,9 +928,6 @@
mBrightnessSetting.registerListener(mBrightnessSettingListener);
mContext.getContentResolver().registerContentObserver(
- Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT),
- false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
}
@@ -1259,9 +1247,6 @@
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE);
}
break;
- case DisplayPowerRequest.POLICY_VR:
- state = Display.STATE_VR;
- break;
case DisplayPowerRequest.POLICY_DIM:
case DisplayPowerRequest.POLICY_BRIGHT:
default:
@@ -1316,8 +1301,8 @@
mIgnoreProximityUntilChanged = false;
}
- if (!mLogicalDisplay.isEnabled()
- || mLogicalDisplay.getPhase() == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION
+ if (!mIsEnabled
+ || mIsInTransition
|| mScreenOffBecauseOfProximity) {
state = Display.STATE_OFF;
}
@@ -1339,12 +1324,6 @@
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_SCREEN_OFF);
}
- // Always use the VR brightness when in the VR state.
- if (state == Display.STATE_VR) {
- brightnessState = mScreenBrightnessForVr;
- mBrightnessReasonTemp.setReason(BrightnessReason.REASON_VR);
- }
-
if ((Float.isNaN(brightnessState))
&& isValidBrightnessValue(mPowerRequest.screenBrightnessOverride)) {
brightnessState = mPowerRequest.screenBrightnessOverride;
@@ -1563,7 +1542,7 @@
mBrightnessThrottler.getBrightnessMaxReason());
// Animate the screen brightness when the screen is on or dozing.
- // Skip the animation when the screen is off or suspended or transition to/from VR.
+ // Skip the animation when the screen is off.
boolean brightnessAdjusted = false;
final boolean brightnessIsTemporary =
mAppliedTemporaryBrightness || mAppliedTemporaryAutoBrightnessAdjustment;
@@ -1586,8 +1565,6 @@
}
}
- final boolean wasOrWillBeInVr =
- (state == Display.STATE_VR || oldState == Display.STATE_VR);
final boolean initialRampSkip = (state == Display.STATE_ON && mSkipRampState
!= RAMP_STATE_SKIP_NONE) || skipRampBecauseOfProximityChangeToNegative;
// While dozing, sometimes the brightness is split into buckets. Rather than animating
@@ -1629,7 +1606,7 @@
&& (animateValue != currentBrightness
|| sdrAnimateValue != currentSdrBrightness)) {
if (initialRampSkip || hasBrightnessBuckets
- || wasOrWillBeInVr || !isDisplayContentVisible || brightnessIsTemporary) {
+ || !isDisplayContentVisible || brightnessIsTemporary) {
animateScreenBrightness(animateValue, sdrAnimateValue,
SCREEN_ANIMATION_RATE_MINIMUM);
} else {
@@ -2066,12 +2043,6 @@
}
}
- private float clampScreenBrightnessForVr(float value) {
- return MathUtils.constrain(
- value, mScreenBrightnessForVrRangeMinimum,
- mScreenBrightnessForVrRangeMaximum);
- }
-
private float clampScreenBrightness(float value) {
if (Float.isNaN(value)) {
value = PowerManager.BRIGHTNESS_MIN;
@@ -2160,23 +2131,6 @@
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
}
- } else if (target == Display.STATE_VR) {
- // Wait for brightness animation to complete beforehand when entering VR
- // from screen on to prevent a perceptible jump because brightness may operate
- // differently when the display is configured for dozing.
- if (mScreenBrightnessRampAnimator.isAnimating()
- && mPowerState.getScreenState() == Display.STATE_ON) {
- return;
- }
-
- // Set screen state.
- if (!setScreenState(Display.STATE_VR)) {
- return; // screen on blocked
- }
-
- // Dismiss the black surface without fanfare.
- mPowerState.setColorFadeLevel(1.0f);
- mPowerState.dismissColorFade();
} else if (target == Display.STATE_DOZE) {
// Want screen dozing.
// Wait for brightness animation to complete beforehand when entering doze
@@ -2384,9 +2338,6 @@
mAutomaticBrightnessController.resetShortTermModel();
}
}
- // We don't bother with a pending variable for VR screen brightness since we just
- // immediately adapt to it.
- mScreenBrightnessForVr = getScreenBrightnessForVrSetting();
sendUpdatePowerState();
}
@@ -2405,13 +2356,6 @@
return clampAbsoluteBrightness(brightness);
}
- private float getScreenBrightnessForVrSetting() {
- final float brightnessFloat = Settings.System.getFloatForUser(mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT, mScreenBrightnessForVrDefault,
- UserHandle.USER_CURRENT);
- return clampScreenBrightnessForVr(brightnessFloat);
- }
-
@Override
public void setBrightness(float brightnessValue) {
// Update the setting, which will eventually call back into DPC to have us actually update
@@ -2585,9 +2529,6 @@
pw.println(" mScreenBrightnessRangeDefault=" + mScreenBrightnessDefault);
pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
- pw.println(" mScreenBrightnessForVrRangeMinimum=" + mScreenBrightnessForVrRangeMinimum);
- pw.println(" mScreenBrightnessForVrRangeMaximum=" + mScreenBrightnessForVrRangeMaximum);
- pw.println(" mScreenBrightnessForVrDefault=" + mScreenBrightnessForVrDefault);
pw.println(" mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
pw.println(" mAllowAutoBrightnessWhileDozingConfig="
+ mAllowAutoBrightnessWhileDozingConfig);
@@ -2637,7 +2578,6 @@
pw.println(" mBrightnessReason=" + mBrightnessReason);
pw.println(" mTemporaryAutoBrightnessAdjustment=" + mTemporaryAutoBrightnessAdjustment);
pw.println(" mPendingAutoBrightnessAdjustment=" + mPendingAutoBrightnessAdjustment);
- pw.println(" mScreenBrightnessForVrFloat=" + mScreenBrightnessForVr);
pw.println(" mAppliedAutoBrightness=" + mAppliedAutoBrightness);
pw.println(" mAppliedDimming=" + mAppliedDimming);
pw.println(" mAppliedLowPower=" + mAppliedLowPower);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 1f58a1c..1f9df9e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -198,15 +198,6 @@
private final float mScreenBrightnessDefault;
- // The minimum allowed brightness while in VR.
- private final float mScreenBrightnessForVrRangeMinimum;
-
- // The maximum allowed brightness while in VR.
- private final float mScreenBrightnessForVrRangeMaximum;
-
- // The default screen brightness for VR.
- private final float mScreenBrightnessForVrDefault;
-
// True if auto-brightness should be used.
private boolean mUseSoftwareAutoBrightnessConfig;
@@ -394,9 +385,6 @@
// behalf of the user.
private float mCurrentScreenBrightnessSetting;
- // The current screen brightness while in VR mode.
- private float mScreenBrightnessForVr;
-
// The last auto brightness adjustment that was set by the user and not temporary. Set to
// Float.NaN when an auto-brightness adjustment hasn't been recorded yet.
private float mAutoBrightnessAdjustment;
@@ -422,6 +410,8 @@
private DisplayDeviceConfig mDisplayDeviceConfig;
+ private boolean mIsEnabled;
+ private boolean mIsInTransition;
/**
* Creates the display power controller.
*/
@@ -439,6 +429,8 @@
mHandler = new DisplayControllerHandler(handler.getLooper());
mDisplayDeviceConfig = logicalDisplay.getPrimaryDisplayDeviceLocked()
.getDisplayDeviceConfig();
+ mIsEnabled = logicalDisplay.isEnabledLocked();
+ mIsInTransition = logicalDisplay.isInTransitionLocked();
mWakelockController = mInjector.getWakelockController(mDisplayId, callbacks);
mDisplayPowerProximityStateController = mInjector.getDisplayPowerProximityStateController(
mWakelockController, mDisplayDeviceConfig, mHandler.getLooper(),
@@ -484,14 +476,6 @@
mScreenBrightnessDefault = clampAbsoluteBrightness(
mLogicalDisplay.getDisplayInfoLocked().brightnessDefault);
- // VR SETTINGS
- mScreenBrightnessForVrDefault = clampAbsoluteBrightness(
- pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR));
- mScreenBrightnessForVrRangeMaximum = clampAbsoluteBrightness(
- pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR));
- mScreenBrightnessForVrRangeMinimum = clampAbsoluteBrightness(
- pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR));
-
loadBrightnessRampRates();
mSkipScreenOnBrightnessRamp = resources.getBoolean(
R.bool.config_skipScreenOnBrightnessRamp);
@@ -558,7 +542,6 @@
mDisplayBrightnessController =
new DisplayBrightnessController(context, null, mDisplayId);
mCurrentScreenBrightnessSetting = getScreenBrightnessSetting();
- mScreenBrightnessForVr = getScreenBrightnessForVrSetting();
mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
@@ -721,30 +704,37 @@
final DisplayDeviceConfig config = device.getDisplayDeviceConfig();
final IBinder token = device.getDisplayTokenLocked();
final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
+ final boolean isEnabled = mLogicalDisplay.isEnabledLocked();
+ final boolean isInTransition = mLogicalDisplay.isInTransitionLocked();
mHandler.post(() -> {
+ boolean changed = false;
if (mDisplayDevice != device) {
+ changed = true;
mDisplayDevice = device;
mUniqueDisplayId = uniqueId;
mDisplayStatsId = mUniqueDisplayId.hashCode();
mDisplayDeviceConfig = config;
loadFromDisplayDeviceConfig(token, info);
mDisplayPowerProximityStateController.notifyDisplayDeviceChanged(config);
+
+ // Since the underlying display-device changed, we really don't know the
+ // last command that was sent to change it's state. Lets assume it is unknown so
+ // that we trigger a change immediately.
+ mPowerState.resetScreenState();
+ }
+ if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) {
+ changed = true;
+ mIsEnabled = isEnabled;
+ mIsInTransition = isInTransition;
+ }
+
+ if (changed) {
updatePowerState();
}
});
}
/**
- * Called when the displays are preparing to transition from one device state to another.
- * This process involves turning off some displays so we need updatePowerState() to run and
- * calculate the new state.
- */
- @Override
- public void onDeviceStateTransition() {
- sendUpdatePowerState();
- }
-
- /**
* Unregisters all listeners and interrupts all running threads; halting future work.
*
* This method should be called when the DisplayPowerController2 is no longer in use; i.e. when
@@ -851,9 +841,6 @@
mBrightnessSetting.registerListener(mBrightnessSettingListener);
mContext.getContentResolver().registerContentObserver(
- Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT),
- false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
}
@@ -1152,9 +1139,6 @@
state = Display.STATE_DOZE;
}
break;
- case DisplayPowerRequest.POLICY_VR:
- state = Display.STATE_VR;
- break;
case DisplayPowerRequest.POLICY_DIM:
case DisplayPowerRequest.POLICY_BRIGHT:
default:
@@ -1165,8 +1149,8 @@
mDisplayPowerProximityStateController.updateProximityState(mPowerRequest, state);
- if (!mLogicalDisplay.isEnabled()
- || mLogicalDisplay.getPhase() == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION
+ if (!mIsEnabled
+ || mIsInTransition
|| mDisplayPowerProximityStateController.isScreenOffBecauseOfProximity()) {
state = Display.STATE_OFF;
}
@@ -1188,12 +1172,6 @@
float brightnessState = displayBrightnessState.getBrightness();
mBrightnessReasonTemp.set(displayBrightnessState.getBrightnessReason());
- // Always use the VR brightness when in the VR state.
- if (state == Display.STATE_VR) {
- brightnessState = mScreenBrightnessForVr;
- mBrightnessReasonTemp.setReason(BrightnessReason.REASON_VR);
- }
-
final boolean autoBrightnessEnabledInDoze =
mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig()
&& Display.isDozeState(state);
@@ -1394,7 +1372,7 @@
mBrightnessThrottler.getBrightnessMaxReason());
// Animate the screen brightness when the screen is on or dozing.
- // Skip the animation when the screen is off or suspended or transition to/from VR.
+ // Skip the animation when the screen is off or suspended.
boolean brightnessAdjusted = false;
final boolean brightnessIsTemporary =
(mBrightnessReason.getReason() == BrightnessReason.REASON_TEMPORARY)
@@ -1418,8 +1396,6 @@
}
}
- final boolean wasOrWillBeInVr =
- (state == Display.STATE_VR || oldState == Display.STATE_VR);
final boolean initialRampSkip = (state == Display.STATE_ON && mSkipRampState
!= RAMP_STATE_SKIP_NONE) || mDisplayPowerProximityStateController
.shouldSkipRampBecauseOfProximityChangeToNegative();
@@ -1462,7 +1438,7 @@
&& (animateValue != currentBrightness
|| sdrAnimateValue != currentSdrBrightness)) {
if (initialRampSkip || hasBrightnessBuckets
- || wasOrWillBeInVr || !isDisplayContentVisible || brightnessIsTemporary) {
+ || !isDisplayContentVisible || brightnessIsTemporary) {
animateScreenBrightness(animateValue, sdrAnimateValue,
SCREEN_ANIMATION_RATE_MINIMUM);
} else {
@@ -1875,12 +1851,6 @@
fallbackType);
}
- private float clampScreenBrightnessForVr(float value) {
- return MathUtils.constrain(
- value, mScreenBrightnessForVrRangeMinimum,
- mScreenBrightnessForVrRangeMaximum);
- }
-
private float clampScreenBrightness(float value) {
if (Float.isNaN(value)) {
value = PowerManager.BRIGHTNESS_MIN;
@@ -1969,23 +1939,6 @@
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
}
- } else if (target == Display.STATE_VR) {
- // Wait for brightness animation to complete beforehand when entering VR
- // from screen on to prevent a perceptible jump because brightness may operate
- // differently when the display is configured for dozing.
- if (mScreenBrightnessRampAnimator.isAnimating()
- && mPowerState.getScreenState() == Display.STATE_ON) {
- return;
- }
-
- // Set screen state.
- if (!setScreenState(Display.STATE_VR)) {
- return; // screen on blocked
- }
-
- // Dismiss the black surface without fanfare.
- mPowerState.setColorFadeLevel(1.0f);
- mPowerState.dismissColorFade();
} else if (target == Display.STATE_DOZE) {
// Want screen dozing.
// Wait for brightness animation to complete beforehand when entering doze
@@ -2102,9 +2055,6 @@
mAutomaticBrightnessController.resetShortTermModel();
}
}
- // We don't bother with a pending variable for VR screen brightness since we just
- // immediately adapt to it.
- mScreenBrightnessForVr = getScreenBrightnessForVrSetting();
sendUpdatePowerState();
}
@@ -2123,13 +2073,6 @@
return clampAbsoluteBrightness(brightness);
}
- private float getScreenBrightnessForVrSetting() {
- final float brightnessFloat = Settings.System.getFloatForUser(mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT, mScreenBrightnessForVrDefault,
- UserHandle.USER_CURRENT);
- return clampScreenBrightnessForVr(brightnessFloat);
- }
-
@Override
public void setBrightness(float brightnessValue) {
// Update the setting, which will eventually call back into DPC to have us actually update
@@ -2243,9 +2186,6 @@
pw.println(" mScreenBrightnessRangeDefault=" + mScreenBrightnessDefault);
pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
- pw.println(" mScreenBrightnessForVrRangeMinimum=" + mScreenBrightnessForVrRangeMinimum);
- pw.println(" mScreenBrightnessForVrRangeMaximum=" + mScreenBrightnessForVrRangeMaximum);
- pw.println(" mScreenBrightnessForVrDefault=" + mScreenBrightnessForVrDefault);
pw.println(" mUseSoftwareAutoBrightnessConfig=" + mUseSoftwareAutoBrightnessConfig);
pw.println(" mSkipScreenOnBrightnessRamp=" + mSkipScreenOnBrightnessRamp);
pw.println(" mColorFadeFadesConfig=" + mColorFadeFadesConfig);
@@ -2281,7 +2221,6 @@
pw.println(" mBrightnessReason=" + mBrightnessReason);
pw.println(" mTemporaryAutoBrightnessAdjustment=" + mTemporaryAutoBrightnessAdjustment);
pw.println(" mPendingAutoBrightnessAdjustment=" + mPendingAutoBrightnessAdjustment);
- pw.println(" mScreenBrightnessForVrFloat=" + mScreenBrightnessForVr);
pw.println(" mAppliedAutoBrightness=" + mAppliedAutoBrightness);
pw.println(" mAppliedDimming=" + mAppliedDimming);
pw.println(" mAppliedLowPower=" + mAppliedLowPower);
diff --git a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
index 6677f35..46f1343 100644
--- a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
+++ b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
@@ -45,11 +45,6 @@
void stop();
/**
- * Used to manage the displays preparing to transition from one device state to another.
- */
- void onDeviceStateTransition();
-
- /**
* Used to update the display's BrightnessConfiguration
* @param config The new BrightnessConfiguration
*/
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 2f22d33..f650b11 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -145,7 +145,7 @@
public void setScreenState(int state) {
if (mScreenState != state) {
if (DEBUG) {
- Slog.d(TAG, "setScreenState: state=" + state);
+ Slog.w(TAG, "setScreenState: state=" + Display.stateToString(state));
}
mScreenState = state;
@@ -339,6 +339,15 @@
if (mColorFade != null) mColorFade.dump(pw);
}
+ /**
+ * Resets the screen state to unknown. Useful when the underlying display-device changes for the
+ * LogicalDisplay and we do not know the last state that was sent to it.
+ */
+ void resetScreenState() {
+ mScreenState = Display.STATE_UNKNOWN;
+ mScreenReady = false;
+ }
+
private void scheduleScreenUpdate() {
if (!mScreenUpdatePending) {
mScreenUpdatePending = true;
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 4bf1e98..f85b990 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -762,18 +762,8 @@
}
}
- // If the state change was from or to VR, then we need to tell the light
- // so that it can apply appropriate VR brightness settings. Also, update the
- // brightness so the state is propogated to light.
- boolean vrModeChange = false;
- if ((state == Display.STATE_VR || currentState == Display.STATE_VR) &&
- currentState != state) {
- setVrMode(state == Display.STATE_VR);
- vrModeChange = true;
- }
-
// Apply brightness changes given that we are in a non-suspended state.
- if (brightnessChanged || vrModeChange) {
+ if (brightnessChanged) {
setDisplayBrightness(brightnessState, sdrBrightnessState);
mBrightnessState = brightnessState;
mSdrBrightnessState = sdrBrightnessState;
@@ -785,15 +775,6 @@
}
}
- private void setVrMode(boolean isVrEnabled) {
- if (DEBUG) {
- Slog.d(TAG, "setVrMode("
- + "id=" + physicalDisplayId
- + ", state=" + Display.stateToString(state) + ")");
- }
- mBacklightAdapter.setVrMode(isVrEnabled);
- }
-
private void setDisplayState(int state) {
if (DEBUG) {
Slog.d(TAG, "setDisplayState("
@@ -1505,12 +1486,6 @@
}
}
- void setVrMode(boolean isVrModeEnabled) {
- if (mBacklight != null) {
- mBacklight.setVrMode(isVrModeEnabled);
- }
- }
-
void setForceSurfaceControl(boolean forceSurfaceControl) {
mForceSurfaceControl = forceSurfaceControl;
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 28bdce3..8dd169bf 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -18,7 +18,6 @@
import static com.android.server.display.DisplayDeviceInfo.TOUCH_NONE;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Point;
@@ -68,33 +67,6 @@
final class LogicalDisplay {
private static final String TAG = "LogicalDisplay";
- /**
- * Phase indicating the logical display's existence is hidden from the rest of the framework.
- * This can happen if the current layout has specifically requested to keep this display
- * disabled.
- */
- static final int DISPLAY_PHASE_DISABLED = -1;
-
- /**
- * Phase indicating that the logical display is going through a layout transition.
- * When in this phase, other systems can choose to special case power-state handling of a
- * display that might be in a transition.
- */
- static final int DISPLAY_PHASE_LAYOUT_TRANSITION = 0;
-
- /**
- * The display is exposed to the rest of the system and its power state is determined by a
- * power-request from PowerManager.
- */
- static final int DISPLAY_PHASE_ENABLED = 1;
-
- @IntDef(prefix = {"DISPLAY_PHASE" }, value = {
- DISPLAY_PHASE_DISABLED,
- DISPLAY_PHASE_LAYOUT_TRANSITION,
- DISPLAY_PHASE_ENABLED
- })
- @interface DisplayPhase {}
-
// The layer stack we use when the display has been blanked to prevent any
// of its content from appearing.
private static final int BLANK_LAYER_STACK = -1;
@@ -159,14 +131,6 @@
private final Rect mTempDisplayRect = new Rect();
/**
- * Indicates the current phase of the display. Generally, phases supersede any
- * requests from PowerManager in DPC's calculation for the display state. Only when the
- * phase is ENABLED does PowerManager's request for the display take effect.
- */
- @DisplayPhase
- private int mPhase = DISPLAY_PHASE_ENABLED;
-
- /**
* The UID mappings for refresh rate override
*/
private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides;
@@ -181,12 +145,22 @@
*/
private final SparseArray<Float> mTempFrameRateOverride;
+ // Indicates the display is enabled (allowed to be ON).
+ private boolean mIsEnabled;
+
+ // Indicates the display is part of a transition from one device-state ({@link
+ // DeviceStateManager}) to another. Being a "part" of a transition means that either
+ // the {@link mIsEnabled} is changing, or the underlying mPrimiaryDisplayDevice is changing.
+ private boolean mIsInTransition;
+
public LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice) {
mDisplayId = displayId;
mLayerStack = layerStack;
mPrimaryDisplayDevice = primaryDisplayDevice;
mPendingFrameRateOverrideUids = new ArraySet<>();
mTempFrameRateOverride = new SparseArray<>();
+ mIsEnabled = true;
+ mIsInTransition = false;
}
/**
@@ -531,7 +505,7 @@
// Prevent displays that are disabled from receiving input.
// TODO(b/188914255): Remove once input can dispatch against device vs layerstack.
device.setDisplayFlagsLocked(t,
- (isEnabled() && device.getDisplayDeviceInfoLocked().touch != TOUCH_NONE)
+ (isEnabledLocked() && device.getDisplayDeviceInfoLocked().touch != TOUCH_NONE)
? SurfaceControl.DISPLAY_RECEIVES_INPUT
: 0);
@@ -773,32 +747,45 @@
return old;
}
- public void setPhase(@DisplayPhase int phase) {
- mPhase = phase;
- }
-
- /**
- * Returns the currently set phase for this LogicalDisplay. Phases are used when transitioning
- * from one device state to another. {@see LogicalDisplayMapper}.
- */
- @DisplayPhase
- public int getPhase() {
- return mPhase;
- }
-
/**
* @return {@code true} if the LogicalDisplay is enabled or {@code false}
* if disabled indicating that the display should be hidden from the rest of the apps and
* framework.
*/
- public boolean isEnabled() {
- // DISPLAY_PHASE_LAYOUT_TRANSITION is still considered an 'enabled' phase.
- return mPhase == DISPLAY_PHASE_ENABLED || mPhase == DISPLAY_PHASE_LAYOUT_TRANSITION;
+ public boolean isEnabledLocked() {
+ return mIsEnabled;
+ }
+
+ /**
+ * Sets the display as enabled.
+ *
+ * @param enable True if enabled, false otherwise.
+ */
+ public void setEnabledLocked(boolean enabled) {
+ mIsEnabled = enabled;
+ }
+
+ /**
+ * @return {@code true} if the LogicalDisplay is in a transition phase. This is used to indicate
+ * that we are getting ready to swap the underlying display-device and the display should be
+ * rendered appropriately to reduce jank.
+ */
+ public boolean isInTransitionLocked() {
+ return mIsInTransition;
+ }
+
+ /**
+ * Sets the transition phase.
+ * @param isInTransition True if it display is in transition.
+ */
+ public void setIsInTransitionLocked(boolean isInTransition) {
+ mIsInTransition = isInTransition;
}
public void dumpLocked(PrintWriter pw) {
pw.println("mDisplayId=" + mDisplayId);
- pw.println("mPhase=" + mPhase);
+ pw.println("mIsEnabled=" + mIsEnabled);
+ pw.println("mIsInTransition=" + mIsInTransition);
pw.println("mLayerStack=" + mLayerStack);
pw.println("mHasContent=" + mHasContent);
pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}");
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index cb97e28..66073c2 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -40,7 +40,6 @@
import android.view.DisplayInfo;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.display.LogicalDisplay.DisplayPhase;
import com.android.server.display.layout.Layout;
import java.io.PrintWriter;
@@ -180,6 +179,12 @@
LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
@NonNull Handler handler) {
+ this(context, repo, listener, syncRoot, handler, new DeviceStateToLayoutMap());
+ }
+
+ LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
+ @NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
+ @NonNull Handler handler, @NonNull DeviceStateToLayoutMap deviceStateToLayoutMap) {
mSyncRoot = syncRoot;
mPowerManager = context.getSystemService(PowerManager.class);
mInteractive = mPowerManager.isInteractive();
@@ -194,7 +199,7 @@
mDeviceStatesOnWhichToSleep = toSparseBooleanArray(context.getResources().getIntArray(
com.android.internal.R.array.config_deviceStatesOnWhichToSleep));
mDisplayDeviceRepo.addListener(this);
- mDeviceStateToLayoutMap = new DeviceStateToLayoutMap();
+ mDeviceStateToLayoutMap = deviceStateToLayoutMap;
}
@Override
@@ -231,10 +236,22 @@
}
public LogicalDisplay getDisplayLocked(int displayId) {
- return mLogicalDisplays.get(displayId);
+ return getDisplayLocked(displayId, /* includeDisabled= */ true);
+ }
+
+ public LogicalDisplay getDisplayLocked(int displayId, boolean includeDisabled) {
+ LogicalDisplay display = mLogicalDisplays.get(displayId);
+ if (display == null || display.isEnabledLocked() || includeDisabled) {
+ return display;
+ }
+ return null;
}
public LogicalDisplay getDisplayLocked(DisplayDevice device) {
+ return getDisplayLocked(device, /* includeDisabled= */ true);
+ }
+
+ public LogicalDisplay getDisplayLocked(DisplayDevice device, boolean includeDisabled) {
if (device == null) {
return null;
}
@@ -242,21 +259,26 @@
for (int i = 0; i < count; i++) {
final LogicalDisplay display = mLogicalDisplays.valueAt(i);
if (display.getPrimaryDisplayDeviceLocked() == device) {
- return display;
+ if (display.isEnabledLocked() || includeDisabled) {
+ return display;
+ }
+ return null;
}
}
return null;
}
- public int[] getDisplayIdsLocked(int callingUid) {
+ public int[] getDisplayIdsLocked(int callingUid, boolean includeDisabled) {
final int count = mLogicalDisplays.size();
int[] displayIds = new int[count];
int n = 0;
for (int i = 0; i < count; i++) {
LogicalDisplay display = mLogicalDisplays.valueAt(i);
- DisplayInfo info = display.getDisplayInfoLocked();
- if (info.hasAccess(callingUid)) {
- displayIds[n++] = mLogicalDisplays.keyAt(i);
+ if (display.isEnabledLocked() || includeDisabled) {
+ DisplayInfo info = display.getDisplayInfoLocked();
+ if (info.hasAccess(callingUid)) {
+ displayIds[n++] = mLogicalDisplays.keyAt(i);
+ }
}
}
if (n != count) {
@@ -390,14 +412,12 @@
void setDeviceStateLocked(int state, boolean isOverrideActive) {
Slog.i(TAG, "Requesting Transition to state: " + state + ", from state=" + mDeviceState
- + ", interactive=" + mInteractive);
+ + ", interactive=" + mInteractive + ", mBootCompleted=" + mBootCompleted);
// As part of a state transition, we may need to turn off some displays temporarily so that
// the transition is smooth. Plus, on some devices, only one internal displays can be
- // on at a time. We use DISPLAY_PHASE_LAYOUT_TRANSITION to mark a display that needs to be
+ // on at a time. We use LogicalDisplay.setIsInTransition to mark a display that needs to be
// temporarily turned off.
- if (mDeviceState != DeviceStateManager.INVALID_DEVICE_STATE) {
- resetLayoutLocked(mDeviceState, state, LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION);
- }
+ resetLayoutLocked(mDeviceState, state, /* transitionValue= */ true);
mPendingDeviceState = state;
final boolean wakeDevice = shouldDeviceBeWoken(mPendingDeviceState, mDeviceState,
mInteractive, mBootCompleted);
@@ -507,7 +527,7 @@
final int count = mLogicalDisplays.size();
for (int i = 0; i < count; i++) {
final LogicalDisplay display = mLogicalDisplays.valueAt(i);
- if (display.getPhase() != LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION) {
+ if (!display.isInTransitionLocked()) {
continue;
}
@@ -523,7 +543,7 @@
}
private void transitionToPendingStateLocked() {
- resetLayoutLocked(mDeviceState, mPendingDeviceState, LogicalDisplay.DISPLAY_PHASE_ENABLED);
+ resetLayoutLocked(mDeviceState, mPendingDeviceState, /* transitionValue= */ false);
mDeviceState = mPendingDeviceState;
mPendingDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
applyLayoutLocked();
@@ -838,17 +858,17 @@
/**
* Goes through all the displays used in the layouts for the specified {@code fromState} and
- * {@code toState} and applies the specified {@code phase}. When a new layout is requested, we
- * put the displays that will change into a transitional phase so that they can all be turned
- * OFF. Once all are confirmed OFF, then this method gets called again to reset the phase to
- * normal operation. This helps to ensure that all display-OFF requests are made before
+ * {@code toState} and un/marks them for transition. When a new layout is requested, we
+ * mark the displays that will change into a transitional phase so that they can all be turned
+ * OFF. Once all are confirmed OFF, then this method gets called again to reset transition
+ * marker. This helps to ensure that all display-OFF requests are made before
* display-ON which in turn hides any resizing-jank windows might incur when switching displays.
*
* @param fromState The state we are switching from.
* @param toState The state we are switching to.
- * @param phase The new phase to apply to the displays.
+ * @param transitionValue The value to mark the transition state: true == transitioning.
*/
- private void resetLayoutLocked(int fromState, int toState, @DisplayPhase int phase) {
+ private void resetLayoutLocked(int fromState, int toState, boolean transitionValue) {
final Layout fromLayout = mDeviceStateToLayoutMap.get(fromState);
final Layout toLayout = mDeviceStateToLayoutMap.get(toState);
@@ -866,12 +886,16 @@
// new layout.
final DisplayAddress address = device.getDisplayDeviceInfoLocked().address;
- // Virtual displays do not have addresses.
+ // Virtual displays do not have addresses, so account for nulls.
final Layout.Display fromDisplay =
address != null ? fromLayout.getByAddress(address) : null;
final Layout.Display toDisplay =
address != null ? toLayout.getByAddress(address) : null;
+ // If the display is in one of the layouts but not the other, then the content will
+ // change, so in this case we also want to blank the displays to avoid jank.
+ final boolean displayNotInBothLayouts = (fromDisplay == null) != (toDisplay == null);
+
// If a layout doesn't mention a display-device at all, then the display-device defaults
// to enabled. This is why we treat null as "enabled" in the code below.
final boolean wasEnabled = fromDisplay == null || fromDisplay.isEnabled();
@@ -886,16 +910,23 @@
// 3) It's enabled, but it's mapped to a new logical display ID. To the user this
// would look like apps moving from one screen to another since task-stacks stay
// with the logical display [ID].
+ // 4) It's in one layout but not the other, so the content will change.
final boolean isTransitioning =
- (logicalDisplay.getPhase() == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION)
+ logicalDisplay.isInTransitionLocked()
|| (wasEnabled != willBeEnabled)
- || deviceHasNewLogicalDisplayId;
+ || deviceHasNewLogicalDisplayId
+ || displayNotInBothLayouts;
if (isTransitioning) {
- setDisplayPhase(logicalDisplay, phase);
- if (phase == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION) {
- mUpdatedLogicalDisplays.put(displayId, UPDATE_STATE_TRANSITION);
+ if (transitionValue != logicalDisplay.isInTransitionLocked()) {
+ Slog.i(TAG, "Set isInTransition on display " + displayId + ": "
+ + transitionValue);
}
+ // This will either mark the display as "transitioning" if we are starting to change
+ // the device state, or remove the transitioning marker if the state change is
+ // ending.
+ logicalDisplay.setIsInTransitionLocked(transitionValue);
+ mUpdatedLogicalDisplays.put(displayId, UPDATE_STATE_TRANSITION);
}
}
}
@@ -940,9 +971,7 @@
newDisplay.swapDisplaysLocked(oldDisplay);
}
- if (!displayLayout.isEnabled()) {
- setDisplayPhase(newDisplay, LogicalDisplay.DISPLAY_PHASE_DISABLED);
- }
+ setEnabledLocked(newDisplay, displayLayout.isEnabled());
}
}
@@ -961,23 +990,25 @@
final LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
display.updateLocked(mDisplayDeviceRepo);
mLogicalDisplays.put(displayId, display);
- setDisplayPhase(display, LogicalDisplay.DISPLAY_PHASE_ENABLED);
return display;
}
- private void setDisplayPhase(LogicalDisplay display, @DisplayPhase int phase) {
+ private void setEnabledLocked(LogicalDisplay display, boolean isEnabled) {
final int displayId = display.getDisplayIdLocked();
final DisplayInfo info = display.getDisplayInfoLocked();
final boolean disallowSecondaryDisplay = mSingleDisplayDemoMode
&& (info.type != Display.TYPE_INTERNAL);
- if (phase != LogicalDisplay.DISPLAY_PHASE_DISABLED && disallowSecondaryDisplay) {
+ if (isEnabled && disallowSecondaryDisplay) {
Slog.i(TAG, "Not creating a logical display for a secondary display because single"
+ " display demo mode is enabled: " + display.getDisplayInfoLocked());
- phase = LogicalDisplay.DISPLAY_PHASE_DISABLED;
+ isEnabled = false;
}
- display.setPhase(phase);
+ if (display.isEnabledLocked() != isEnabled) {
+ Slog.i(TAG, "SetEnabled on display " + displayId + ": " + isEnabled);
+ display.setEnabledLocked(isEnabled);
+ }
}
private int assignDisplayGroupIdLocked(
diff --git a/services/core/java/com/android/server/display/brightness/BrightnessReason.java b/services/core/java/com/android/server/display/brightness/BrightnessReason.java
index d8eacd9..b6be713 100644
--- a/services/core/java/com/android/server/display/brightness/BrightnessReason.java
+++ b/services/core/java/com/android/server/display/brightness/BrightnessReason.java
@@ -34,10 +34,9 @@
public static final int REASON_DOZE_DEFAULT = 3;
public static final int REASON_AUTOMATIC = 4;
public static final int REASON_SCREEN_OFF = 5;
- public static final int REASON_VR = 6;
- public static final int REASON_OVERRIDE = 7;
- public static final int REASON_TEMPORARY = 8;
- public static final int REASON_BOOST = 9;
+ public static final int REASON_OVERRIDE = 6;
+ public static final int REASON_TEMPORARY = 7;
+ public static final int REASON_BOOST = 8;
public static final int REASON_MAX = REASON_BOOST;
public static final int MODIFIER_DIMMED = 0x1;
@@ -185,8 +184,6 @@
return "automatic";
case REASON_SCREEN_OFF:
return "screen_off";
- case REASON_VR:
- return "vr";
case REASON_OVERRIDE:
return "override";
case REASON_TEMPORARY:
diff --git a/services/core/java/com/android/server/display/utils/SensorUtils.java b/services/core/java/com/android/server/display/utils/SensorUtils.java
index cb40b40..4924ad5 100644
--- a/services/core/java/com/android/server/display/utils/SensorUtils.java
+++ b/services/core/java/com/android/server/display/utils/SensorUtils.java
@@ -33,6 +33,9 @@
*/
public static Sensor findSensor(SensorManager sensorManager, String sensorType,
String sensorName, int fallbackType) {
+ if ("".equals(sensorName) && "".equals(sensorType)) {
+ return null;
+ }
final boolean isNameSpecified = !TextUtils.isEmpty(sensorName);
final boolean isTypeSpecified = !TextUtils.isEmpty(sensorType);
if (isNameSpecified || isTypeSpecified) {
diff --git a/services/core/java/com/android/server/input/KeyboardLayoutManager.java b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
index fac001e..c2157a6 100644
--- a/services/core/java/com/android/server/input/KeyboardLayoutManager.java
+++ b/services/core/java/com/android/server/input/KeyboardLayoutManager.java
@@ -79,9 +79,10 @@
// (requires restart)
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 1;
- private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 2;
- private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 3;
+ private static final int MSG_UPDATE_EXISTING_DEVICES = 1;
+ private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 2;
+ private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 3;
+ private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4;
private final Context mContext;
private final NativeInputManagerService mNative;
@@ -121,10 +122,10 @@
InputManager inputManager = Objects.requireNonNull(
mContext.getSystemService(InputManager.class));
inputManager.registerInputDeviceListener(this, mHandler);
- // Circle through all the already added input devices
- for (int deviceId : inputManager.getInputDeviceIds()) {
- onInputDeviceAdded(deviceId);
- }
+
+ Message msg = Message.obtain(mHandler, MSG_UPDATE_EXISTING_DEVICES,
+ inputManager.getInputDeviceIds());
+ mHandler.sendMessage(msg);
}
@Override
@@ -682,6 +683,13 @@
private boolean handleMessage(Message msg) {
switch (msg.what) {
+ case MSG_UPDATE_EXISTING_DEVICES:
+ // Circle through all the already added input devices
+ // Need to do it on handler thread and not block IMS thread
+ for (int deviceId : (int[]) msg.obj) {
+ onInputDeviceAdded(deviceId);
+ }
+ return true;
case MSG_SWITCH_KEYBOARD_LAYOUT:
handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
return true;
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 90245b5e..7f6c2d6 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -73,6 +73,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
@@ -147,7 +148,6 @@
private final ScheduledThreadPoolExecutor mDailyMetricTimer =
new ScheduledThreadPoolExecutor(1);
-
// The period of the recurring time
private static final int PERIOD_METRIC_QUERY_DAYS = 1;
@@ -363,11 +363,13 @@
*/
private void initDefaultClientMap() {
HashMap<Integer, IContextHubClient> defaultClientMap = new HashMap<>();
- for (int contextHubId : mContextHubIdToInfoMap.keySet()) {
+ for (Map.Entry<Integer, ContextHubInfo> entry: mContextHubIdToInfoMap.entrySet()) {
+ int contextHubId = entry.getKey();
+ ContextHubInfo contextHubInfo = entry.getValue();
+
mLastRestartTimestampMap.put(contextHubId,
new AtomicLong(SystemClock.elapsedRealtimeNanos()));
- ContextHubInfo contextHubInfo = mContextHubIdToInfoMap.get(contextHubId);
IContextHubClient client = mClientManager.registerClient(
contextHubInfo, createDefaultClientCallback(contextHubId),
/* attributionTag= */ null, mTransactionManager, mContext.getPackageName());
@@ -1133,6 +1135,26 @@
mTransactionManager.addTransaction(transaction);
}
+ @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
+ /**
+ * Queries for a list of preloaded nanoapp IDs from the specified Context Hub.
+ *
+ * @param hubInfo The Context Hub to query a list of nanoapps from.
+ * @return The list of 64-bit IDs of the preloaded nanoapps.
+ * @throws NullPointerException if hubInfo is null
+ */
+ @Override
+ public long[] getPreloadedNanoAppIds(ContextHubInfo hubInfo) throws RemoteException {
+ super.getPreloadedNanoAppIds_enforcePermission();
+ Objects.requireNonNull(hubInfo, "hubInfo cannot be null");
+
+ long[] nanoappIds = mContextHubWrapper.getPreloadedNanoappIds();
+ if (nanoappIds == null) {
+ return new long[0];
+ }
+ return nanoappIds;
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -1160,6 +1182,10 @@
mNanoAppStateManager.foreachNanoAppInstanceInfo((info) -> pw.println(info));
pw.println("");
+ pw.println("=================== PRELOADED NANOAPPS ====================");
+ dumpPreloadedNanoapps(pw);
+
+ pw.println("");
pw.println("=================== CLIENTS ====================");
pw.println(mClientManager);
@@ -1201,6 +1227,21 @@
proto.flush();
}
+ /**
+ * Dumps preloaded nanoapps to the console
+ */
+ private void dumpPreloadedNanoapps(PrintWriter pw) {
+ if (mContextHubWrapper == null) {
+ return;
+ }
+
+ long[] preloadedNanoappIds = mContextHubWrapper.getPreloadedNanoappIds();
+ for (long preloadedNanoappId: preloadedNanoappIds) {
+ pw.print("ID: 0x");
+ pw.println(Long.toHexString(preloadedNanoappId));
+ }
+ }
+
private void checkPermissions() {
ContextHubServiceUtil.checkPermissions(mContext);
}
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 48152b4..f55ae6e 100644
--- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
@@ -359,6 +359,14 @@
public abstract int queryNanoapps(int contextHubId) throws RemoteException;
/**
+ * Provides the list of preloaded nanoapp IDs on the system. The output of this API must
+ * not change.
+ *
+ * @return The list of preloaded nanoapp IDs
+ */
+ public abstract long[] getPreloadedNanoappIds();
+
+ /**
* Registers a callback with the Context Hub.
*
* @param contextHubId The ID of the Context Hub to register the callback with.
@@ -683,6 +691,20 @@
}
}
+ public long[] getPreloadedNanoappIds() {
+ android.hardware.contexthub.IContextHub hub = getHub();
+ if (hub == null) {
+ return null;
+ }
+
+ try {
+ return hub.getPreloadedNanoappIds();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception while getting preloaded nanoapp IDs: " + e.getMessage());
+ return null;
+ }
+ }
+
public void registerExistingCallback(int contextHubId) {
android.hardware.contexthub.IContextHub hub = getHub();
if (hub == null) {
@@ -863,6 +885,10 @@
mHub.queryApps(contextHubId));
}
+ public long[] getPreloadedNanoappIds() {
+ return new long[0];
+ }
+
public void registerCallback(int contextHubId, ICallback callback) throws RemoteException {
mHidlCallbackMap.put(contextHubId,
new ContextHubWrapperHidlCallback(contextHubId, callback));
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 5d01aeb..7553370 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -2259,20 +2259,26 @@
incrementalStorages.add(storage);
}
- try {
- if (!VerityUtils.hasFsverity(pkg.getBaseApkPath())) {
- VerityUtils.setUpFsverity(pkg.getBaseApkPath(), (byte[]) null);
- }
- for (String path : pkg.getSplitCodePaths()) {
- if (!VerityUtils.hasFsverity(path)) {
- VerityUtils.setUpFsverity(path, (byte[]) null);
- }
- }
- } catch (IOException e) {
- // There's nothing we can do if the setup failed. Since fs-verity is
- // optional, just ignore the error for now.
- Slog.e(TAG, "Failed to fully enable fs-verity to " + packageName);
+ // Enabling fs-verity is a blocking operation. To reduce the impact to the install time,
+ // run in a background thread.
+ final ArrayList<String> apkPaths = new ArrayList<>();
+ apkPaths.add(pkg.getBaseApkPath());
+ if (pkg.getSplitCodePaths() != null) {
+ Collections.addAll(apkPaths, pkg.getSplitCodePaths());
}
+ mInjector.getBackgroundHandler().post(() -> {
+ try {
+ for (String path : apkPaths) {
+ if (!VerityUtils.hasFsverity(path)) {
+ VerityUtils.setUpFsverity(path, (byte[]) null);
+ }
+ }
+ } catch (IOException e) {
+ // There's nothing we can do if the setup failed. Since fs-verity is
+ // optional, just ignore the error for now.
+ Slog.e(TAG, "Failed to fully enable fs-verity to " + packageName);
+ }
+ });
// Hardcode previousAppId to 0 to disable any data migration (http://b/221088088)
mAppDataHelper.prepareAppDataPostCommitLIF(pkg, 0);
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index 558202b..a3fa25d 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -533,7 +533,7 @@
ai.metaData = null;
}
ai.applicationInfo = applicationInfo;
- ai.targetDisplayCategory = a.getTargetDisplayCategory();
+ ai.requiredDisplayCategory = a.getRequiredDisplayCategory();
ai.setKnownActivityEmbeddingCerts(a.getKnownActivityEmbeddingCerts());
assignFieldsComponentInfoParsedMainComponent(ai, a, pkgSetting, userId);
return ai;
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedActivity.java b/services/core/java/com/android/server/pm/pkg/component/ParsedActivity.java
index e019215..1826f7a 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedActivity.java
+++ b/services/core/java/com/android/server/pm/pkg/component/ParsedActivity.java
@@ -98,8 +98,8 @@
boolean isSupportsSizeChanges();
/**
- * Gets the category of the target display this activity is supposed to run on.
+ * Gets the required category of the display this activity is supposed to run on.
*/
@Nullable
- String getTargetDisplayCategory();
+ String getRequiredDisplayCategory();
}
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedActivityImpl.java b/services/core/java/com/android/server/pm/pkg/component/ParsedActivityImpl.java
index 278e547..68d5428 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedActivityImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/component/ParsedActivityImpl.java
@@ -97,7 +97,7 @@
private ActivityInfo.WindowLayout windowLayout;
@Nullable
- private String mTargetDisplayCategory;
+ private String mRequiredDisplayCategory;
public ParsedActivityImpl(ParsedActivityImpl other) {
super(other);
@@ -125,7 +125,7 @@
this.colorMode = other.colorMode;
this.windowLayout = other.windowLayout;
this.mKnownActivityEmbeddingCerts = other.mKnownActivityEmbeddingCerts;
- this.mTargetDisplayCategory = other.mTargetDisplayCategory;
+ this.mRequiredDisplayCategory = other.mRequiredDisplayCategory;
}
/**
@@ -193,7 +193,7 @@
alias.requestedVrComponent = target.getRequestedVrComponent();
alias.setDirectBootAware(target.isDirectBootAware());
alias.setProcessName(target.getProcessName());
- alias.setTargetDisplayCategory(target.getTargetDisplayCategory());
+ alias.setRequiredDisplayCategory(target.getRequiredDisplayCategory());
return alias;
// Not all attributes from the target ParsedActivity are copied to the alias.
@@ -321,7 +321,7 @@
dest.writeBoolean(false);
}
sForStringSet.parcel(this.mKnownActivityEmbeddingCerts, dest, flags);
- dest.writeString8(this.mTargetDisplayCategory);
+ dest.writeString8(this.mRequiredDisplayCategory);
}
public ParsedActivityImpl() {
@@ -356,7 +356,7 @@
windowLayout = new ActivityInfo.WindowLayout(in);
}
this.mKnownActivityEmbeddingCerts = sForStringSet.unparcel(in);
- this.mTargetDisplayCategory = in.readString8();
+ this.mRequiredDisplayCategory = in.readString8();
}
@NonNull
@@ -414,7 +414,7 @@
int rotationAnimation,
int colorMode,
@Nullable ActivityInfo.WindowLayout windowLayout,
- @Nullable String targetDisplayCategory) {
+ @Nullable String requiredDisplayCategory) {
this.theme = theme;
this.uiOptions = uiOptions;
this.targetActivity = targetActivity;
@@ -439,7 +439,7 @@
this.rotationAnimation = rotationAnimation;
this.colorMode = colorMode;
this.windowLayout = windowLayout;
- this.mTargetDisplayCategory = targetDisplayCategory;
+ this.mRequiredDisplayCategory = requiredDisplayCategory;
// onConstructed(); // You can define this method to get a callback
}
@@ -560,8 +560,8 @@
}
@DataClass.Generated.Member
- public @Nullable String getTargetDisplayCategory() {
- return mTargetDisplayCategory;
+ public @Nullable String getRequiredDisplayCategory() {
+ return mRequiredDisplayCategory;
}
@DataClass.Generated.Member
@@ -691,16 +691,16 @@
}
@DataClass.Generated.Member
- public @NonNull ParsedActivityImpl setTargetDisplayCategory(@NonNull String value) {
- mTargetDisplayCategory = value;
+ public @NonNull ParsedActivityImpl setRequiredDisplayCategory(@NonNull String value) {
+ mRequiredDisplayCategory = value;
return this;
}
@DataClass.Generated(
- time = 1664805688714L,
+ time = 1669437519576L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/component/ParsedActivityImpl.java",
- inputSignatures = "private int theme\nprivate int uiOptions\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String targetActivity\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String parentActivityName\nprivate @android.annotation.Nullable java.lang.String taskAffinity\nprivate int privateFlags\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String permission\nprivate @android.annotation.Nullable java.util.Set<java.lang.String> mKnownActivityEmbeddingCerts\nprivate int launchMode\nprivate int documentLaunchMode\nprivate int maxRecents\nprivate int configChanges\nprivate int softInputMode\nprivate int persistableMode\nprivate int lockTaskLaunchMode\nprivate int screenOrientation\nprivate int resizeMode\nprivate float maxAspectRatio\nprivate float minAspectRatio\nprivate boolean supportsSizeChanges\nprivate @android.annotation.Nullable java.lang.String requestedVrComponent\nprivate int rotationAnimation\nprivate int colorMode\nprivate @android.annotation.Nullable android.content.pm.ActivityInfo.WindowLayout windowLayout\nprivate @android.annotation.Nullable java.lang.String mTargetDisplayCategory\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<com.android.server.pm.pkg.component.ParsedActivityImpl> CREATOR\nstatic @android.annotation.NonNull com.android.server.pm.pkg.component.ParsedActivityImpl makeAppDetailsActivity(java.lang.String,java.lang.String,int,java.lang.String,boolean)\nstatic @android.annotation.NonNull com.android.server.pm.pkg.component.ParsedActivityImpl makeAlias(java.lang.String,com.android.server.pm.pkg.component.ParsedActivity)\npublic com.android.server.pm.pkg.component.ParsedActivityImpl setMaxAspectRatio(int,float)\npublic com.android.server.pm.pkg.component.ParsedActivityImpl setMinAspectRatio(int,float)\npublic com.android.server.pm.pkg.component.ParsedActivityImpl setTargetActivity(java.lang.String)\npublic com.android.server.pm.pkg.component.ParsedActivityImpl setPermission(java.lang.String)\npublic @android.annotation.NonNull @java.lang.Override java.util.Set<java.lang.String> getKnownActivityEmbeddingCerts()\npublic void setKnownActivityEmbeddingCerts(java.util.Set<java.lang.String>)\npublic java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedActivityImpl extends com.android.server.pm.pkg.component.ParsedMainComponentImpl implements [com.android.server.pm.pkg.component.ParsedActivity, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=false)")
+ inputSignatures = "private int theme\nprivate int uiOptions\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String targetActivity\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String parentActivityName\nprivate @android.annotation.Nullable java.lang.String taskAffinity\nprivate int privateFlags\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String permission\nprivate @android.annotation.Nullable java.util.Set<java.lang.String> mKnownActivityEmbeddingCerts\nprivate int launchMode\nprivate int documentLaunchMode\nprivate int maxRecents\nprivate int configChanges\nprivate int softInputMode\nprivate int persistableMode\nprivate int lockTaskLaunchMode\nprivate int screenOrientation\nprivate int resizeMode\nprivate float maxAspectRatio\nprivate float minAspectRatio\nprivate boolean supportsSizeChanges\nprivate @android.annotation.Nullable java.lang.String requestedVrComponent\nprivate int rotationAnimation\nprivate int colorMode\nprivate @android.annotation.Nullable android.content.pm.ActivityInfo.WindowLayout windowLayout\nprivate @android.annotation.Nullable java.lang.String mRequiredDisplayCategory\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<com.android.server.pm.pkg.component.ParsedActivityImpl> CREATOR\nstatic @android.annotation.NonNull com.android.server.pm.pkg.component.ParsedActivityImpl makeAppDetailsActivity(java.lang.String,java.lang.String,int,java.lang.String,boolean)\nstatic @android.annotation.NonNull com.android.server.pm.pkg.component.ParsedActivityImpl makeAlias(java.lang.String,com.android.server.pm.pkg.component.ParsedActivity)\npublic com.android.server.pm.pkg.component.ParsedActivityImpl setMaxAspectRatio(int,float)\npublic com.android.server.pm.pkg.component.ParsedActivityImpl setMinAspectRatio(int,float)\npublic com.android.server.pm.pkg.component.ParsedActivityImpl setTargetActivity(java.lang.String)\npublic com.android.server.pm.pkg.component.ParsedActivityImpl setPermission(java.lang.String)\npublic @android.annotation.NonNull @java.lang.Override java.util.Set<java.lang.String> getKnownActivityEmbeddingCerts()\npublic void setKnownActivityEmbeddingCerts(java.util.Set<java.lang.String>)\npublic java.lang.String toString()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass ParsedActivityImpl extends com.android.server.pm.pkg.component.ParsedMainComponentImpl implements [com.android.server.pm.pkg.component.ParsedActivity, android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genParcelable=false)")
@Deprecated
private void __metadata() {}
diff --git a/services/core/java/com/android/server/pm/pkg/component/ParsedActivityUtils.java b/services/core/java/com/android/server/pm/pkg/component/ParsedActivityUtils.java
index 305062b..ea791e1 100644
--- a/services/core/java/com/android/server/pm/pkg/component/ParsedActivityUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/component/ParsedActivityUtils.java
@@ -220,17 +220,17 @@
pkg.setVisibleToInstantApps(true);
}
- String targetDisplayCategory = sa.getNonConfigurationString(
- R.styleable.AndroidManifestActivity_targetDisplayCategory, 0);
+ String requiredDisplayCategory = sa.getNonConfigurationString(
+ R.styleable.AndroidManifestActivity_requiredDisplayCategory, 0);
- if (targetDisplayCategory != null
- && FrameworkParsingPackageUtils.validateName(targetDisplayCategory,
+ if (requiredDisplayCategory != null
+ && FrameworkParsingPackageUtils.validateName(requiredDisplayCategory,
false /* requireSeparator */, false /* requireFilename */) != null) {
- return input.error("targetDisplayCategory attribute can only consists of "
- + "alphanumeric characters, '_', and '.'");
+ return input.error("requiredDisplayCategory attribute can only consist "
+ + "of alphanumeric characters, '_', and '.'");
}
- activity.setTargetDisplayCategory(targetDisplayCategory);
+ activity.setRequiredDisplayCategory(requiredDisplayCategory);
return parseActivityOrAlias(activity, pkg, tag, parser, res, sa, receiver,
false /*isAlias*/, visibleToEphemeral, input,
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 7737421..85f1357 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -200,6 +200,9 @@
if (!mKeyguardState.enabled) {
mKeyguardService.setKeyguardEnabled(mKeyguardState.enabled);
}
+ if (mKeyguardState.dreaming) {
+ mKeyguardService.onDreamingStarted();
+ }
}
@Override
diff --git a/services/core/java/com/android/server/power/PowerGroup.java b/services/core/java/com/android/server/power/PowerGroup.java
index 431cf38..1c4e143 100644
--- a/services/core/java/com/android/server/power/PowerGroup.java
+++ b/services/core/java/com/android/server/power/PowerGroup.java
@@ -324,11 +324,6 @@
return mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM;
}
- public boolean isPolicyVrLocked() {
- return mDisplayPowerRequest.isVr();
-
- }
-
public boolean isBrightOrDimLocked() {
return mDisplayPowerRequest.isBrightOrDim();
}
@@ -382,7 +377,7 @@
@VisibleForTesting
int getDesiredScreenPolicyLocked(boolean quiescent, boolean dozeAfterScreenOff,
- boolean vrModeEnabled, boolean bootCompleted, boolean screenBrightnessBoostInProgress) {
+ boolean bootCompleted, boolean screenBrightnessBoostInProgress) {
final int wakefulness = getWakefulnessLocked();
final int wakeLockSummary = getWakeLockSummaryLocked();
if (wakefulness == WAKEFULNESS_ASLEEP || quiescent) {
@@ -398,13 +393,6 @@
// doze after screen off. This causes the screen off transition to be skipped.
}
- // It is important that POLICY_VR check happens after the wakefulness checks above so
- // that VR-mode does not prevent displays from transitioning to the correct state when
- // dozing or sleeping.
- if (vrModeEnabled) {
- return DisplayPowerRequest.POLICY_VR;
- }
-
if ((wakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
|| !bootCompleted
|| (getUserActivitySummaryLocked() & USER_ACTIVITY_SCREEN_BRIGHT) != 0
@@ -423,10 +411,10 @@
boolean useProximitySensor, boolean boostScreenBrightness, int dozeScreenState,
float dozeScreenBrightness, boolean overrideDrawWakeLock,
PowerSaveState powerSaverState, boolean quiescent, boolean dozeAfterScreenOff,
- boolean vrModeEnabled, boolean bootCompleted, boolean screenBrightnessBoostInProgress,
+ boolean bootCompleted, boolean screenBrightnessBoostInProgress,
boolean waitForNegativeProximity) {
mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked(quiescent, dozeAfterScreenOff,
- vrModeEnabled, bootCompleted, screenBrightnessBoostInProgress);
+ bootCompleted, screenBrightnessBoostInProgress);
mDisplayPowerRequest.screenBrightnessOverride = screenBrightnessOverride;
mDisplayPowerRequest.useAutoBrightness = autoBrightness;
mDisplayPowerRequest.useProximitySensor = useProximitySensor;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 1ea0988..6e3c827 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -90,8 +90,6 @@
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.service.dreams.DreamManagerInternal;
-import android.service.vr.IVrManager;
-import android.service.vr.IVrStateCallbacks;
import android.sysprop.InitProperties;
import android.sysprop.PowerProperties;
import android.util.ArrayMap;
@@ -196,8 +194,6 @@
private static final int DIRTY_SCREEN_BRIGHTNESS_BOOST = 1 << 11;
// Dirty bit: sQuiescent changed
private static final int DIRTY_QUIESCENT = 1 << 12;
- // Dirty bit: VR Mode enabled changed
- private static final int DIRTY_VR_MODE_CHANGED = 1 << 13;
// Dirty bit: attentive timer may have timed out
private static final int DIRTY_ATTENTIVE = 1 << 14;
// Dirty bit: display group wakefulness has changed
@@ -580,9 +576,6 @@
public final float mScreenBrightnessDefault;
public final float mScreenBrightnessDoze;
public final float mScreenBrightnessDim;
- public final float mScreenBrightnessMinimumVr;
- public final float mScreenBrightnessMaximumVr;
- public final float mScreenBrightnessDefaultVr;
// Value we store for tracking face down behavior.
private boolean mIsFaceDown = false;
@@ -666,9 +659,6 @@
// True if double tap to wake is enabled
private boolean mDoubleTapWakeEnabled;
- // True if we are currently in VR Mode.
- private boolean mIsVrModeEnabled;
-
// True if we in the process of performing a forceSuspend
private boolean mForceSuspendActive;
@@ -1145,29 +1135,6 @@
mScreenBrightnessDim = dim;
}
- final float vrMin = mContext.getResources().getFloat(com.android.internal.R.dimen
- .config_screenBrightnessSettingForVrMinimumFloat);
- final float vrMax = mContext.getResources().getFloat(com.android.internal.R.dimen
- .config_screenBrightnessSettingForVrMaximumFloat);
- final float vrDef = mContext.getResources().getFloat(com.android.internal.R.dimen
- .config_screenBrightnessSettingForVrDefaultFloat);
- if (vrMin == INVALID_BRIGHTNESS_IN_CONFIG || vrMax == INVALID_BRIGHTNESS_IN_CONFIG
- || vrDef == INVALID_BRIGHTNESS_IN_CONFIG) {
- mScreenBrightnessMinimumVr = BrightnessSynchronizer.brightnessIntToFloat(
- mContext.getResources().getInteger(com.android.internal.R.integer
- .config_screenBrightnessForVrSettingMinimum));
- mScreenBrightnessMaximumVr = BrightnessSynchronizer.brightnessIntToFloat(
- mContext.getResources().getInteger(com.android.internal.R.integer
- .config_screenBrightnessForVrSettingMaximum));
- mScreenBrightnessDefaultVr = BrightnessSynchronizer.brightnessIntToFloat(
- mContext.getResources().getInteger(com.android.internal.R.integer
- .config_screenBrightnessForVrSettingDefault));
- } else {
- mScreenBrightnessMinimumVr = vrMin;
- mScreenBrightnessMaximumVr = vrMax;
- mScreenBrightnessDefaultVr = vrDef;
- }
-
synchronized (mLock) {
mBootingSuspendBlocker =
mInjector.createSuspendBlocker(this, "PowerManagerService.Booting");
@@ -1373,14 +1340,6 @@
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.DEVICE_DEMO_MODE),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
- IVrManager vrManager = IVrManager.Stub.asInterface(getBinderService(Context.VR_SERVICE));
- if (vrManager != null) {
- try {
- vrManager.registerListener(mVrStateCallbacks);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to register VR mode state listener: " + e);
- }
- }
// Register for broadcasts from other components of the system.
IntentFilter filter = new IntentFilter();
@@ -2848,7 +2807,7 @@
>= powerGroup.getLastWakeTimeLocked()) {
groupNextTimeout = lastUserActivityTimeNoChangeLights + screenOffTimeout;
if (now < groupNextTimeout) {
- if (powerGroup.isPolicyBrightLocked() || powerGroup.isPolicyVrLocked()) {
+ if (powerGroup.isPolicyBrightLocked()) {
groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
} else if (powerGroup.isPolicyDimLocked()) {
groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
@@ -3415,7 +3374,6 @@
|| !mDreamsSupportedConfig
|| !mDreamsEnabledSetting
|| !(powerGroup.isBrightOrDimLocked())
- || powerGroup.isPolicyVrLocked()
|| (powerGroup.getUserActivitySummaryLocked() & (USER_ACTIVITY_SCREEN_BRIGHT
| USER_ACTIVITY_SCREEN_DIM | USER_ACTIVITY_SCREEN_DREAM)) == 0) {
return false;
@@ -3460,8 +3418,8 @@
final boolean oldPowerGroupsReady = areAllPowerGroupsReadyLocked();
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
- | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |
- DIRTY_QUIESCENT | DIRTY_DISPLAY_GROUP_WAKEFULNESS)) != 0) {
+ | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST
+ | DIRTY_QUIESCENT | DIRTY_DISPLAY_GROUP_WAKEFULNESS)) != 0) {
if ((dirty & DIRTY_QUIESCENT) != 0) {
if (areAllPowerGroupsReadyLocked()) {
sQuiescent = false;
@@ -3496,7 +3454,7 @@
mDozeScreenBrightnessOverrideFromDreamManagerFloat,
mDrawWakeLockOverrideFromSidekick,
mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS),
- sQuiescent, mDozeAfterScreenOff, mIsVrModeEnabled, mBootCompleted,
+ sQuiescent, mDozeAfterScreenOff, mBootCompleted,
mScreenBrightnessBoostInProgress, mRequestWaitForNegativeProximity);
int wakefulness = powerGroup.getWakefulnessLocked();
if (DEBUG_SPEW) {
@@ -3514,7 +3472,6 @@
+ ", useAutoBrightness=" + autoBrightness
+ ", mScreenBrightnessBoostInProgress="
+ mScreenBrightnessBoostInProgress
- + ", mIsVrModeEnabled= " + mIsVrModeEnabled
+ ", sQuiescent=" + sQuiescent);
}
@@ -3562,7 +3519,7 @@
}
private boolean shouldBoostScreenBrightness() {
- return !mIsVrModeEnabled && mScreenBrightnessBoostInProgress;
+ return mScreenBrightnessBoostInProgress;
}
private static boolean isValidBrightness(float value) {
@@ -3573,7 +3530,7 @@
@GuardedBy("mLock")
int getDesiredScreenPolicyLocked(int groupId) {
return mPowerGroups.get(groupId).getDesiredScreenPolicyLocked(sQuiescent,
- mDozeAfterScreenOff, mIsVrModeEnabled, mBootCompleted,
+ mDozeAfterScreenOff, mBootCompleted,
mScreenBrightnessBoostInProgress);
}
@@ -3654,8 +3611,7 @@
@GuardedBy("mLock")
private boolean shouldUseProximitySensorLocked() {
// Use default display group for proximity sensor.
- return !mIsVrModeEnabled
- && (mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP).getWakeLockSummaryLocked()
+ return (mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP).getWakeLockSummaryLocked()
& WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
}
@@ -4279,11 +4235,6 @@
}
}
- @VisibleForTesting
- void setVrModeEnabled(boolean enabled) {
- mIsVrModeEnabled = enabled;
- }
-
private void setPowerBoostInternal(int boost, int durationMs) {
// Maybe filter the event.
mNativeWrapper.nativeSetPowerBoost(boost, durationMs);
@@ -4553,7 +4504,6 @@
pw.println(" mScreenBrightnessMaximum=" + mScreenBrightnessMaximum);
pw.println(" mScreenBrightnessDefault=" + mScreenBrightnessDefault);
pw.println(" mDoubleTapWakeEnabled=" + mDoubleTapWakeEnabled);
- pw.println(" mIsVrModeEnabled=" + mIsVrModeEnabled);
pw.println(" mForegroundProfile=" + mForegroundProfile);
pw.println(" mUserId=" + mUserId);
@@ -4964,9 +4914,6 @@
proto.write(
PowerServiceSettingsAndConfigurationDumpProto.IS_DOUBLE_TAP_WAKE_ENABLED,
mDoubleTapWakeEnabled);
- proto.write(
- PowerServiceSettingsAndConfigurationDumpProto.IS_VR_MODE_ENABLED,
- mIsVrModeEnabled);
proto.end(settingsAndConfigurationToken);
final long attentiveTimeout = getAttentiveTimeoutLocked();
@@ -5095,21 +5042,6 @@
}
}
- private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
- @Override
- public void onVrStateChanged(boolean enabled) {
- setPowerModeInternal(Mode.VR, enabled);
-
- synchronized (mLock) {
- if (mIsVrModeEnabled != enabled) {
- setVrModeEnabled(enabled);
- mDirty |= DIRTY_VR_MODE_CHANGED;
- updatePowerStateLocked();
- }
- }
- }
- };
-
private final AmbientDisplaySuppressionChangedCallback mAmbientSuppressionChangedCallback =
new AmbientDisplaySuppressionChangedCallback() {
@Override
@@ -5837,12 +5769,6 @@
return mScreenBrightnessDim;
case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DOZE:
return mScreenBrightnessDoze;
- case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR:
- return mScreenBrightnessMinimumVr;
- case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR:
- return mScreenBrightnessMaximumVr;
- case PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT_VR:
- return mScreenBrightnessDefaultVr;
default:
return PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
@@ -6626,7 +6552,6 @@
case Display.STATE_DOZE_SUSPEND:
case Display.STATE_ON_SUSPEND:
case Display.STATE_ON:
- case Display.STATE_VR:
break;
default:
screenState = Display.STATE_UNKNOWN;
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index fca9743..74d52b2 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -272,6 +272,7 @@
handleClosingApps();
handleOpeningApps();
handleChangingApps(transit);
+ handleClosingChangingContainers();
appTransition.setLastAppTransition(transit, topOpeningApp,
topClosingApp, topChangingApp);
@@ -290,6 +291,7 @@
mDisplayContent.mClosingApps.clear();
mDisplayContent.mChangingContainers.clear();
mDisplayContent.mUnknownAppVisibilityController.clear();
+ mDisplayContent.mClosingChangingContainers.clear();
// This has changed the visibility of windows, so perform
// a new layout to get them all up-to-date.
@@ -1178,6 +1180,24 @@
}
}
+ private void handleClosingChangingContainers() {
+ final ArrayMap<WindowContainer, Rect> containers =
+ mDisplayContent.mClosingChangingContainers;
+ while (!containers.isEmpty()) {
+ final WindowContainer container = containers.keyAt(0);
+ containers.remove(container);
+
+ // For closing changing windows that are part of the transition, they should have been
+ // removed from mClosingChangingContainers in WindowContainer#getAnimationAdapter()
+ // If the closing changing TaskFragment is not part of the transition, update its
+ // surface after removing it from mClosingChangingContainers.
+ final TaskFragment taskFragment = container.asTaskFragment();
+ if (taskFragment != null) {
+ taskFragment.updateOrganizedTaskFragmentSurface();
+ }
+ }
+ }
+
private void handleChangingApps(@TransitionOldType int transit) {
final ArraySet<WindowContainer> apps = mDisplayContent.mChangingContainers;
final int appsCount = apps.size();
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 690779d..6140508 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -192,6 +192,7 @@
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.DisplayUtils;
@@ -356,6 +357,11 @@
final ArraySet<ActivityRecord> mClosingApps = new ArraySet<>();
final ArraySet<WindowContainer> mChangingContainers = new ArraySet<>();
final UnknownAppVisibilityController mUnknownAppVisibilityController;
+ /**
+ * If a container is closing when resizing, keeps track of its starting bounds when it is
+ * removed from {@link #mChangingContainers}.
+ */
+ final ArrayMap<WindowContainer, Rect> mClosingChangingContainers = new ArrayMap<>();
private MetricsLogger mMetricsLogger;
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index d34e610..3635ebb 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -104,10 +104,29 @@
RemoteAnimationRecord createRemoteAnimationRecord(WindowContainer windowContainer,
Point position, Rect localBounds, Rect endBounds, Rect startBounds,
boolean showBackdrop) {
+ return createRemoteAnimationRecord(windowContainer, position, localBounds, endBounds,
+ startBounds, showBackdrop, startBounds != null /* shouldCreateSnapshot */);
+ }
+
+ /**
+ * Creates an animation record for each individual {@link WindowContainer}.
+ *
+ * @param windowContainer The windows to animate.
+ * @param position The position app bounds relative to its parent.
+ * @param localBounds The bounds of the app relative to its parent.
+ * @param endBounds The end bounds after the transition, in screen coordinates.
+ * @param startBounds The start bounds before the transition, in screen coordinates.
+ * @param showBackdrop To show background behind a window during animation.
+ * @param shouldCreateSnapshot Whether this target should create a snapshot animation.
+ * @return The record representing animation(s) to run on the app.
+ */
+ RemoteAnimationRecord createRemoteAnimationRecord(WindowContainer windowContainer,
+ Point position, Rect localBounds, Rect endBounds, Rect startBounds,
+ boolean showBackdrop, boolean shouldCreateSnapshot) {
ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createAnimationAdapter(): container=%s",
windowContainer);
final RemoteAnimationRecord adapters = new RemoteAnimationRecord(windowContainer, position,
- localBounds, endBounds, startBounds, showBackdrop);
+ localBounds, endBounds, startBounds, showBackdrop, shouldCreateSnapshot);
mPendingAnimations.add(adapters);
return adapters;
}
@@ -441,14 +460,15 @@
private @RemoteAnimationTarget.Mode int mMode = RemoteAnimationTarget.MODE_CHANGING;
RemoteAnimationRecord(WindowContainer windowContainer, Point endPos, Rect localBounds,
- Rect endBounds, Rect startBounds, boolean showBackdrop) {
+ Rect endBounds, @Nullable Rect startBounds, boolean showBackdrop,
+ boolean shouldCreateSnapshot) {
mWindowContainer = windowContainer;
mShowBackdrop = showBackdrop;
if (startBounds != null) {
mStartBounds = new Rect(startBounds);
mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds,
mStartBounds, mShowBackdrop);
- if (mRemoteAnimationAdapter.getChangeNeedsSnapshot()) {
+ if (shouldCreateSnapshot && mRemoteAnimationAdapter.getChangeNeedsSnapshot()) {
final Rect thumbnailLocalBounds = new Rect(startBounds);
thumbnailLocalBounds.offsetTo(0, 0);
// Snapshot is located at (0,0) of the animation leash. It doesn't have size
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 443e304..d69d949 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -2320,11 +2320,7 @@
@Override
public void onConfigurationChanged(Configuration newParentConfig) {
super.onConfigurationChanged(newParentConfig);
-
- if (mTaskFragmentOrganizer != null) {
- updateOrganizedTaskFragmentSurface();
- }
-
+ updateOrganizedTaskFragmentSurface();
sendTaskFragmentInfoChanged();
}
@@ -2337,8 +2333,13 @@
updateOrganizedTaskFragmentSurface();
}
- private void updateOrganizedTaskFragmentSurface() {
- if (mDelayOrganizedTaskFragmentSurfaceUpdate) {
+ /**
+ * TaskFragmentOrganizer doesn't have access to the surface for security reasons, so we need to
+ * update its surface on the server side if it is not collected for Shell or in pending
+ * animation.
+ */
+ void updateOrganizedTaskFragmentSurface() {
+ if (mDelayOrganizedTaskFragmentSurfaceUpdate || mTaskFragmentOrganizer == null) {
return;
}
if (mTransitionController.isShellTransitionsEnabled()
@@ -2370,7 +2371,10 @@
return;
}
- final Rect bounds = getBounds();
+ // If this TaskFragment is closing while resizing, crop to the starting bounds instead.
+ final Rect bounds = isClosingWhenResizing()
+ ? mDisplayContent.mClosingChangingContainers.get(this)
+ : getBounds();
final int width = bounds.width();
final int height = bounds.height();
if (!forceUpdate && width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
@@ -2418,6 +2422,15 @@
|| endBounds.height() != startBounds.height();
}
+ /** Records the starting bounds of the closing organized TaskFragment. */
+ void setClosingChangingStartBoundsIfNeeded() {
+ if (isOrganizedTaskFragment() && mDisplayContent != null
+ && mDisplayContent.mChangingContainers.remove(this)) {
+ mDisplayContent.mClosingChangingContainers.put(
+ this, new Rect(mSurfaceFreezer.mFreezeBounds));
+ }
+ }
+
@Override
boolean isSyncFinished() {
return super.isSyncFinished() && isReadyToTransit();
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 6d149da..da73fad 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -278,31 +278,29 @@
// is set with the suggestedDisplayArea. If it is set, but the eventual TaskDisplayArea is
// different, we should recalcuating the bounds.
boolean hasInitialBoundsForSuggestedDisplayAreaInFreeformMode = false;
- // shouldSetAsOverrideWindowingMode is set if the task needs to retain the launchMode
- // regardless of the windowing mode of the parent.
- boolean shouldSetAsOverrideWindowingMode = false;
- if (launchMode == WINDOWING_MODE_PINNED) {
- if (DEBUG) appendLog("picture-in-picture");
- } else if (!root.isResizeable()) {
- if (shouldLaunchUnresizableAppInFreeformInFreeformMode(root, suggestedDisplayArea,
- options)) {
- launchMode = WINDOWING_MODE_UNDEFINED;
- if (outParams.mBounds.isEmpty()) {
- getTaskBounds(root, suggestedDisplayArea, layout, launchMode, hasInitialBounds,
- outParams.mBounds);
- hasInitialBoundsForSuggestedDisplayAreaInFreeformMode = true;
+ if (suggestedDisplayArea.inFreeformWindowingMode()) {
+ if (launchMode == WINDOWING_MODE_PINNED) {
+ if (DEBUG) appendLog("picture-in-picture");
+ } else if (!root.isResizeable()) {
+ if (shouldLaunchUnresizableAppInFreeform(root, suggestedDisplayArea, options)) {
+ launchMode = WINDOWING_MODE_FREEFORM;
+ if (outParams.mBounds.isEmpty()) {
+ getTaskBounds(root, suggestedDisplayArea, layout, launchMode,
+ hasInitialBounds, outParams.mBounds);
+ hasInitialBoundsForSuggestedDisplayAreaInFreeformMode = true;
+ }
+ if (DEBUG) appendLog("unresizable-freeform");
+ } else {
+ launchMode = WINDOWING_MODE_FULLSCREEN;
+ outParams.mBounds.setEmpty();
+ if (DEBUG) appendLog("unresizable-forced-maximize");
}
- if (DEBUG) appendLog("unresizable-freeform");
- } else {
- launchMode = WINDOWING_MODE_FULLSCREEN;
- outParams.mBounds.setEmpty();
- shouldSetAsOverrideWindowingMode = true;
- if (DEBUG) appendLog("unresizable-forced-maximize");
}
+ } else {
+ if (DEBUG) appendLog("non-freeform-task-display-area");
}
// If launch mode matches display windowing mode, let it inherit from display.
outParams.mWindowingMode = launchMode == suggestedDisplayArea.getWindowingMode()
- && !shouldSetAsOverrideWindowingMode
? WINDOWING_MODE_UNDEFINED : launchMode;
if (phase == PHASE_WINDOWING_MODE) {
@@ -669,7 +667,7 @@
inOutBounds.offset(xOffset, yOffset);
}
- private boolean shouldLaunchUnresizableAppInFreeformInFreeformMode(ActivityRecord activity,
+ private boolean shouldLaunchUnresizableAppInFreeform(ActivityRecord activity,
TaskDisplayArea displayArea, @Nullable ActivityOptions options) {
if (options != null && options.getLaunchWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
// Do not launch the activity in freeform if it explicitly requested fullscreen mode.
@@ -682,7 +680,8 @@
final int displayOrientation = orientationFromBounds(displayArea.getBounds());
final int activityOrientation = resolveOrientation(activity, displayArea,
displayArea.getBounds());
- if (displayOrientation != activityOrientation) {
+ if (displayArea.getWindowingMode() == WINDOWING_MODE_FREEFORM
+ && displayOrientation != activityOrientation) {
return true;
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 05dea0e..6e61071 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -813,6 +813,7 @@
void removeImmediately() {
final DisplayContent dc = getDisplayContent();
if (dc != null) {
+ dc.mClosingChangingContainers.remove(this);
mSurfaceFreezer.unfreeze(getSyncTransaction());
}
while (!mChildren.isEmpty()) {
@@ -1022,9 +1023,12 @@
* @param dc The display this container is on after changes.
*/
void onDisplayChanged(DisplayContent dc) {
- if (mDisplayContent != null && mDisplayContent.mChangingContainers.remove(this)) {
- // Cancel any change transition queued-up for this container on the old display.
- mSurfaceFreezer.unfreeze(getSyncTransaction());
+ if (mDisplayContent != null) {
+ mDisplayContent.mClosingChangingContainers.remove(this);
+ if (mDisplayContent.mChangingContainers.remove(this)) {
+ // Cancel any change transition queued-up for this container on the old display.
+ mSurfaceFreezer.unfreeze(getSyncTransaction());
+ }
}
mDisplayContent = dc;
if (dc != null && dc != this) {
@@ -1301,6 +1305,13 @@
// If we are losing visibility, then a snapshot isn't necessary and we are no-longer
// part of a change transition.
if (!visible) {
+ if (asTaskFragment() != null) {
+ // If the organized TaskFragment is closing while resizing, we want to keep track of
+ // its starting bounds to make sure the animation starts at the correct position.
+ // This should be called before unfreeze() because we record the starting bounds
+ // in SurfaceFreezer.
+ asTaskFragment().setClosingChangingStartBoundsIfNeeded();
+ }
mSurfaceFreezer.unfreeze(getSyncTransaction());
}
WindowContainer parent = getParent();
@@ -1309,6 +1320,12 @@
}
}
+ /** Whether this window is closing while resizing. */
+ boolean isClosingWhenResizing() {
+ return mDisplayContent != null
+ && mDisplayContent.mClosingChangingContainers.containsKey(this);
+ }
+
void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
proto.write(HASH_CODE, System.identityHashCode(this));
@@ -3018,10 +3035,22 @@
}
final Rect localBounds = new Rect(mTmpRect);
localBounds.offsetTo(mTmpPoint.x, mTmpPoint.y);
- final RemoteAnimationController.RemoteAnimationRecord adapters =
- controller.createRemoteAnimationRecord(
- this, mTmpPoint, localBounds, screenBounds,
- (isChanging ? mSurfaceFreezer.mFreezeBounds : null), showBackdrop);
+ final RemoteAnimationController.RemoteAnimationRecord adapters;
+ if (!isChanging && !enter && isClosingWhenResizing()) {
+ // Container that is closing while resizing. Pass in the closing start bounds, so
+ // the animation can start with the correct bounds, there won't be a snapshot.
+ // Cleanup the mClosingChangingContainers so that when the animation is finished, it
+ // will reset the surface.
+ final Rect closingStartBounds = getDisplayContent().mClosingChangingContainers
+ .remove(this);
+ adapters = controller.createRemoteAnimationRecord(
+ this, mTmpPoint, localBounds, screenBounds, closingStartBounds,
+ showBackdrop, false /* shouldCreateSnapshot */);
+ } else {
+ final Rect startBounds = isChanging ? mSurfaceFreezer.mFreezeBounds : null;
+ adapters = controller.createRemoteAnimationRecord(
+ this, mTmpPoint, localBounds, screenBounds, startBounds, showBackdrop);
+ }
if (backdropColor != 0) {
adapters.setBackDropColor(backdropColor);
}
@@ -3470,7 +3499,13 @@
return;
}
- getRelativePosition(mTmpPos);
+ if (isClosingWhenResizing()) {
+ // This container is closing while resizing, keep its surface at the starting position
+ // to prevent animation flicker.
+ getRelativePosition(mDisplayContent.mClosingChangingContainers.get(this), mTmpPos);
+ } else {
+ getRelativePosition(mTmpPos);
+ }
final int deltaRotation = getRelativeDisplayRotation();
if (mTmpPos.equals(mLastSurfacePosition) && deltaRotation == mLastDeltaRotation) {
return;
@@ -3535,9 +3570,14 @@
outSurfaceInsets.setEmpty();
}
+ /** Gets the position of this container in its parent's coordinate. */
void getRelativePosition(Point outPos) {
- final Rect dispBounds = getBounds();
- outPos.set(dispBounds.left, dispBounds.top);
+ getRelativePosition(getBounds(), outPos);
+ }
+
+ /** Gets the position of {@code curBounds} in this container's parent's coordinate. */
+ void getRelativePosition(Rect curBounds, Point outPos) {
+ outPos.set(curBounds.left, curBounds.top);
final WindowContainer parent = getParent();
if (parent != null) {
final Rect parentBounds = parent.getBounds();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 19409b1..73759d3 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -4927,7 +4927,8 @@
// animation on the keyguard but seeing the IME window that originally on the app
// which behinds the keyguard.
final WindowState imeInputTarget = getImeInputTarget();
- if (imeInputTarget != null && !(imeInputTarget.isDrawn() || imeInputTarget.isVisible())) {
+ if (imeInputTarget != null
+ && !(imeInputTarget.isDrawn() || imeInputTarget.isVisibleRequested())) {
return false;
}
return mDisplayContent.forAllImeWindows(callback, traverseTopToBottom);
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 5d0551b..969056e 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -310,7 +310,7 @@
const InputDeviceIdentifier& identifier) override;
std::string getDeviceAlias(const InputDeviceIdentifier& identifier) override;
TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
- int32_t surfaceRotation) override;
+ ui::Rotation surfaceRotation) override;
TouchAffineTransformation getTouchAffineTransformation(JNIEnv* env, jfloatArray matrixArr);
void notifyStylusGestureStarted(int32_t deviceId, nsecs_t eventTime) override;
@@ -1153,7 +1153,7 @@
}
TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
- const std::string& inputDeviceDescriptor, int32_t surfaceRotation) {
+ const std::string& inputDeviceDescriptor, ui::Rotation surfaceRotation) {
JNIEnv* env = jniEnv();
ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.c_str()));
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/PackageParserTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/PackageParserTest.java
index 59f27ec..c8e2676 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/PackageParserTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/PackageParserTest.java
@@ -334,7 +334,7 @@
}
@Test
- public void testParseActivityTargetDisplayCategoryValid() throws Exception {
+ public void testParseActivityRequiredDisplayCategoryValid() throws Exception {
final File testFile = extractFile(TEST_APP4_APK);
String actualDisplayCategory = null;
try {
@@ -342,7 +342,7 @@
final List<ParsedActivity> activities = pkg.getActivities();
for (ParsedActivity activity : activities) {
if ((PACKAGE_NAME + ".MyActivity").equals(activity.getName())) {
- actualDisplayCategory = activity.getTargetDisplayCategory();
+ actualDisplayCategory = activity.getRequiredDisplayCategory();
}
}
} finally {
@@ -352,7 +352,7 @@
}
@Test
- public void testParseActivityTargetDisplayCategoryInvalid() throws Exception {
+ public void testParseActivityRequiredDisplayCategoryInvalid() throws Exception {
final File testFile = extractFile(TEST_APP6_APK);
String actualDisplayCategory = null;
try {
@@ -360,12 +360,12 @@
final List<ParsedActivity> activities = pkg.getActivities();
for (ParsedActivity activity : activities) {
if ((PACKAGE_NAME + ".MyActivity").equals(activity.getName())) {
- actualDisplayCategory = activity.getTargetDisplayCategory();
+ actualDisplayCategory = activity.getRequiredDisplayCategory();
}
}
} catch (PackageManagerException e) {
assertThat(e.getMessage()).contains(
- "targetDisplayCategory attribute can only consists"
+ "requiredDisplayCategory attribute can only consist"
+ " of alphanumeric characters, '_', and '.'");
} finally {
testFile.delete();
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt
index 4ceae96..0e2e35f 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParsedActivityTest.kt
@@ -54,7 +54,7 @@
ParsedActivity::getTheme,
ParsedActivity::getUiOptions,
ParsedActivity::isSupportsSizeChanges,
- ParsedActivity::getTargetDisplayCategory
+ ParsedActivity::getRequiredDisplayCategory
)
override fun mainComponentSubclassExtraParams() = listOf(
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 4c28c51..f2cba40 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -237,8 +237,8 @@
when(mLogicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(mLogicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(mDisplayDeviceMock);
when(mLogicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
- when(mLogicalDisplayMock.isEnabled()).thenReturn(true);
- when(mLogicalDisplayMock.getPhase()).thenReturn(LogicalDisplay.DISPLAY_PHASE_ENABLED);
+ when(mLogicalDisplayMock.isEnabledLocked()).thenReturn(true);
+ when(mLogicalDisplayMock.isInTransitionLocked()).thenReturn(false);
when(mDisplayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(mDisplayDeviceMock.getUniqueId()).thenReturn(uniqueId);
when(mDisplayDeviceMock.getDisplayDeviceConfig()).thenReturn(mDisplayDeviceConfigMock);
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 9a4bb22..4f8cb88 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -219,8 +219,8 @@
when(mLogicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(mLogicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(mDisplayDeviceMock);
when(mLogicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
- when(mLogicalDisplayMock.isEnabled()).thenReturn(true);
- when(mLogicalDisplayMock.getPhase()).thenReturn(LogicalDisplay.DISPLAY_PHASE_ENABLED);
+ when(mLogicalDisplayMock.isEnabledLocked()).thenReturn(true);
+ when(mLogicalDisplayMock.isInTransitionLocked()).thenReturn(false);
when(mDisplayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(mDisplayDeviceMock.getUniqueId()).thenReturn(uniqueId);
when(mDisplayDeviceMock.getDisplayDeviceConfig()).thenReturn(mDisplayDeviceConfigMock);
@@ -233,4 +233,4 @@
});
when(mDisplayDeviceConfigMock.getNits()).thenReturn(new float[]{2, 500});
}
-}
\ No newline at end of file
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceOrInternalTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceOrInternalTestCase.java
deleted file mode 100644
index 6c85b7a..0000000
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceOrInternalTestCase.java
+++ /dev/null
@@ -1,213 +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.
- */
-package com.android.server.pm;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
-
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.annotation.UserIdInt;
-import android.app.ActivityManagerInternal;
-import android.content.Context;
-import android.content.pm.UserInfo;
-import android.os.UserManager;
-import android.util.Log;
-import android.util.SparseArray;
-
-import androidx.test.annotation.UiThreadTest;
-
-import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
-import com.android.server.ExtendedMockitoTestCase;
-import com.android.server.LocalServices;
-import com.android.server.am.UserState;
-import com.android.server.pm.UserManagerService.UserData;
-
-import org.junit.After;
-import org.junit.Before;
-import org.mockito.Mock;
-
-/**
- * Base class for {@link UserManagerInternalTest} and {@link UserManagerInternalTest}.
- *
- * <p>{@link UserManagerService} and its {@link UserManagerInternal} implementation have a
- * "symbiotic relationship - some methods of the former simply call the latter and vice versa.
- *
- * <p>Ideally, only one of them should have the logic, but since that's not the case, this class
- * provides the infra to make it easier to test both (which in turn would make it easier / safer to
- * refactor their logic later).
- */
-// TODO(b/244644281): there is no UserManagerInternalTest anymore as the logic being tested there
-// moved to UserVisibilityController, so it might be simpler to merge this class into
-// UserManagerServiceTest (once the UserVisibilityController -> UserManagerService dependency is
-// fixed)
-abstract class UserManagerServiceOrInternalTestCase extends ExtendedMockitoTestCase {
-
- private static final String TAG = UserManagerServiceOrInternalTestCase.class.getSimpleName();
-
- /**
- * Id for a simple user (that doesn't have profiles).
- */
- protected static final int USER_ID = 600;
-
- /**
- * Id for another simple user.
- */
- protected static final int OTHER_USER_ID = 666;
-
- /**
- * Id for a user that has one profile (whose id is {@link #PROFILE_USER_ID}.
- *
- * <p>You can use {@link #addDefaultProfileAndParent()} to add both of this user to the service.
- */
- protected static final int PARENT_USER_ID = 642;
-
- /**
- * Id for a profile whose parent is {@link #PARENTUSER_ID}.
- *
- * <p>You can use {@link #addDefaultProfileAndParent()} to add both of this user to the service.
- */
- protected static final int PROFILE_USER_ID = 643;
-
- private final Object mPackagesLock = new Object();
- private final Context mRealContext = androidx.test.InstrumentationRegistry.getInstrumentation()
- .getTargetContext();
- private final SparseArray<UserData> mUsers = new SparseArray<>();
-
- private Context mSpiedContext;
-
- private @Mock PackageManagerService mMockPms;
- private @Mock UserDataPreparer mMockUserDataPreparer;
- private @Mock ActivityManagerInternal mActivityManagerInternal;
-
- /**
- * Reference to the {@link UserManagerService} being tested.
- */
- protected UserManagerService mUms;
-
- /**
- * Reference to the {@link UserManagerInternal} being tested.
- */
- protected UserManagerInternal mUmi;
-
- @Override
- protected void initializeSession(StaticMockitoSessionBuilder builder) {
- builder
- .spyStatic(UserManager.class)
- .spyStatic(LocalServices.class);
- }
-
- @Before
- @UiThreadTest // Needed to initialize main handler
- public final void setFixtures() {
- mSpiedContext = spy(mRealContext);
-
- // Called when WatchedUserStates is constructed
- doNothing().when(() -> UserManager.invalidateIsUserUnlockedCache());
-
- // Must construct UserManagerService in the UiThread
- mUms = new UserManagerService(mSpiedContext, mMockPms, mMockUserDataPreparer,
- mPackagesLock, mRealContext.getDataDir(), mUsers);
- mUmi = LocalServices.getService(UserManagerInternal.class);
- assertWithMessage("LocalServices.getService(UserManagerInternal.class)").that(mUmi)
- .isNotNull();
- }
-
- @After
- public final void resetUserManagerInternal() {
- // LocalServices follows the "Highlander rule" - There can be only one!
- LocalServices.removeServiceForTest(UserManagerInternal.class);
- }
-
- ///////////////////////////////////////////
- // Helper methods exposed to sub-classes //
- ///////////////////////////////////////////
-
- protected final void mockCurrentUser(@UserIdInt int userId) {
- mockGetLocalService(ActivityManagerInternal.class, mActivityManagerInternal);
-
- when(mActivityManagerInternal.getCurrentUserId()).thenReturn(userId);
- }
-
- protected final <T> void mockGetLocalService(Class<T> serviceClass, T service) {
- doReturn(service).when(() -> LocalServices.getService(serviceClass));
- }
-
- protected final void addDefaultProfileAndParent() {
- addUser(PARENT_USER_ID);
- addProfile(PROFILE_USER_ID, PARENT_USER_ID);
- }
-
- protected final void addProfile(@UserIdInt int profileId, @UserIdInt int parentId) {
- TestUserData profileData = new TestUserData(profileId);
- profileData.info.flags = UserInfo.FLAG_PROFILE;
- profileData.info.profileGroupId = parentId;
-
- addUserData(profileData);
- }
-
- protected final void addUser(@UserIdInt int userId) {
- TestUserData userData = new TestUserData(userId);
-
- addUserData(userData);
- }
-
- protected final void startDefaultProfile() {
- startUser(PROFILE_USER_ID);
- }
-
- protected final void stopDefaultProfile() {
- stopUser(PROFILE_USER_ID);
- }
-
- protected final void startUser(@UserIdInt int userId) {
- setUserState(userId, UserState.STATE_RUNNING_UNLOCKED);
- }
-
- protected final void stopUser(@UserIdInt int userId) {
- setUserState(userId, UserState.STATE_STOPPING);
- }
-
- protected final void setUserState(@UserIdInt int userId, int userState) {
- mUmi.setUserState(userId, userState);
- }
-
- ///////////////////
- // Private infra //
- ///////////////////
-
- private void addUserData(TestUserData userData) {
- Log.d(TAG, "Adding " + userData);
- mUsers.put(userData.info.id, userData);
- }
-
- private static final class TestUserData extends UserData {
-
- @SuppressWarnings("deprecation")
- TestUserData(@UserIdInt int userId) {
- info = new UserInfo();
- info.id = userId;
- }
-
- @Override
- public String toString() {
- return "TestUserData[" + info.toFullString() + "]";
- }
- }
-}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
index b5ffe5f..1367af8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -15,17 +15,116 @@
*/
package com.android.server.pm;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+
import static com.google.common.truth.Truth.assertWithMessage;
-import android.app.ActivityManagerInternal;
-import android.os.UserHandle;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import android.annotation.UserIdInt;
+import android.app.ActivityManagerInternal;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+import android.util.SparseArray;
+
+import androidx.test.annotation.UiThreadTest;
+
+import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
+import com.android.server.ExtendedMockitoTestCase;
+import com.android.server.LocalServices;
+import com.android.server.am.UserState;
+import com.android.server.pm.UserManagerService.UserData;
+
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mock;
/**
* Run as {@code atest FrameworksMockingServicesTests:com.android.server.pm.UserManagerServiceTest}
*/
-public final class UserManagerServiceTest extends UserManagerServiceOrInternalTestCase {
+public final class UserManagerServiceTest extends ExtendedMockitoTestCase {
+
+ private static final String TAG = UserManagerServiceTest.class.getSimpleName();
+
+ /**
+ * Id for a simple user (that doesn't have profiles).
+ */
+ private static final int USER_ID = 600;
+
+ /**
+ * Id for another simple user.
+ */
+ private static final int OTHER_USER_ID = 666;
+
+ /**
+ * Id for a user that has one profile (whose id is {@link #PROFILE_USER_ID}.
+ *
+ * <p>You can use {@link #addDefaultProfileAndParent()} to add both of this user to the service.
+ */
+ private static final int PARENT_USER_ID = 642;
+
+ /**
+ * Id for a profile whose parent is {@link #PARENTUSER_ID}.
+ *
+ * <p>You can use {@link #addDefaultProfileAndParent()} to add both of this user to the service.
+ */
+ private static final int PROFILE_USER_ID = 643;
+
+ private final Object mPackagesLock = new Object();
+ private final Context mRealContext = androidx.test.InstrumentationRegistry.getInstrumentation()
+ .getTargetContext();
+ private final SparseArray<UserData> mUsers = new SparseArray<>();
+
+ private Context mSpiedContext;
+
+ private @Mock PackageManagerService mMockPms;
+ private @Mock UserDataPreparer mMockUserDataPreparer;
+ private @Mock ActivityManagerInternal mActivityManagerInternal;
+
+ /**
+ * Reference to the {@link UserManagerService} being tested.
+ */
+ private UserManagerService mUms;
+
+ /**
+ * Reference to the {@link UserManagerInternal} being tested.
+ */
+ private UserManagerInternal mUmi;
+
+ @Override
+ protected void initializeSession(StaticMockitoSessionBuilder builder) {
+ builder
+ .spyStatic(UserManager.class)
+ .spyStatic(LocalServices.class);
+ }
+
+ @Before
+ @UiThreadTest // Needed to initialize main handler
+ public void setFixtures() {
+ mSpiedContext = spy(mRealContext);
+
+ // Called when WatchedUserStates is constructed
+ doNothing().when(() -> UserManager.invalidateIsUserUnlockedCache());
+
+ // Must construct UserManagerService in the UiThread
+ mUms = new UserManagerService(mSpiedContext, mMockPms, mMockUserDataPreparer,
+ mPackagesLock, mRealContext.getDataDir(), mUsers);
+ mUmi = LocalServices.getService(UserManagerInternal.class);
+ assertWithMessage("LocalServices.getService(UserManagerInternal.class)").that(mUmi)
+ .isNotNull();
+ }
+
+ @After
+ public void resetUserManagerInternal() {
+ // LocalServices follows the "Highlander rule" - There can be only one!
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ }
@Test
public void testGetCurrentUserId_amInternalNotReady() {
@@ -123,4 +222,72 @@
assertWithMessage("isUserRunning(%s)", PROFILE_USER_ID)
.that(mUms.isUserRunning(PROFILE_USER_ID)).isFalse();
}
+
+ private void mockCurrentUser(@UserIdInt int userId) {
+ mockGetLocalService(ActivityManagerInternal.class, mActivityManagerInternal);
+
+ when(mActivityManagerInternal.getCurrentUserId()).thenReturn(userId);
+ }
+
+ private <T> void mockGetLocalService(Class<T> serviceClass, T service) {
+ doReturn(service).when(() -> LocalServices.getService(serviceClass));
+ }
+
+ private void addDefaultProfileAndParent() {
+ addUser(PARENT_USER_ID);
+ addProfile(PROFILE_USER_ID, PARENT_USER_ID);
+ }
+
+ private void addProfile(@UserIdInt int profileId, @UserIdInt int parentId) {
+ TestUserData profileData = new TestUserData(profileId);
+ profileData.info.flags = UserInfo.FLAG_PROFILE;
+ profileData.info.profileGroupId = parentId;
+
+ addUserData(profileData);
+ }
+
+ private void addUser(@UserIdInt int userId) {
+ TestUserData userData = new TestUserData(userId);
+
+ addUserData(userData);
+ }
+
+ private void startDefaultProfile() {
+ startUser(PROFILE_USER_ID);
+ }
+
+ private void stopDefaultProfile() {
+ stopUser(PROFILE_USER_ID);
+ }
+
+ private void startUser(@UserIdInt int userId) {
+ setUserState(userId, UserState.STATE_RUNNING_UNLOCKED);
+ }
+
+ private void stopUser(@UserIdInt int userId) {
+ setUserState(userId, UserState.STATE_STOPPING);
+ }
+
+ private void setUserState(@UserIdInt int userId, int userState) {
+ mUmi.setUserState(userId, userState);
+ }
+
+ private void addUserData(TestUserData userData) {
+ Log.d(TAG, "Adding " + userData);
+ mUsers.put(userData.info.id, userData);
+ }
+
+ private static final class TestUserData extends UserData {
+
+ @SuppressWarnings("deprecation")
+ TestUserData(@UserIdInt int userId) {
+ info = new UserInfo();
+ info.id = userId;
+ }
+
+ @Override
+ public String toString() {
+ return "TestUserData[" + info.toFullString() + "]";
+ }
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java b/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
index 234d70b..93a1f30 100644
--- a/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
@@ -20,7 +20,6 @@
import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DIM;
import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_OFF;
-import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_VR;
import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
import static android.view.Display.DEFAULT_DISPLAY_GROUP;
@@ -59,8 +58,7 @@
Arrays.asList(POLICY_OFF,
POLICY_DOZE,
POLICY_DIM,
- POLICY_BRIGHT,
- POLICY_VR);
+ POLICY_BRIGHT);
private static final int OTHER_DISPLAY_GROUP = DEFAULT_DISPLAY_GROUP + 1;
@ClassRule
@@ -291,7 +289,7 @@
@Test
public void recordScreenPolicy_dimToNonBright_resets() {
- for (int to : Arrays.asList(POLICY_OFF, POLICY_DOZE, POLICY_VR)) {
+ for (int to : Arrays.asList(POLICY_OFF, POLICY_DOZE)) {
setup();
mScreenUndimDetector.mUndimCounter = 1;
mScreenUndimDetector.mUndimCounterStartedMillis = 123;
@@ -309,7 +307,7 @@
@Test
public void recordScreenPolicy_brightToNonDim_resets() {
- for (int to : Arrays.asList(POLICY_OFF, POLICY_DOZE, POLICY_VR)) {
+ for (int to : Arrays.asList(POLICY_OFF, POLICY_DOZE)) {
setup();
mScreenUndimDetector.mUndimCounter = 1;
mScreenUndimDetector.mUndimCounterStartedMillis = 123;
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index e8b8253..6e446f0 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -113,6 +113,8 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* Tests for {@link UserController}.
@@ -146,9 +148,11 @@
private static final List<String> START_FOREGROUND_USER_ACTIONS = newArrayList(
Intent.ACTION_USER_STARTED,
- Intent.ACTION_USER_SWITCHED,
Intent.ACTION_USER_STARTING);
+ private static final List<String> START_FOREGROUND_USER_DEFERRED_ACTIONS = newArrayList(
+ Intent.ACTION_USER_SWITCHED);
+
private static final List<String> START_BACKGROUND_USER_ACTIONS = newArrayList(
Intent.ACTION_USER_STARTED,
Intent.ACTION_LOCKED_BOOT_COMPLETED,
@@ -251,7 +255,6 @@
.isTrue();
verifyUserAssignedToDisplay(TEST_USER_ID, 42);
- // TODO(b/239982558): might need to change assertions
verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt());
verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
verify(mInjector, never()).clearAllLockedTasks(anyString());
@@ -397,11 +400,11 @@
private void continueAndCompleteUserSwitch(UserState userState, int oldUserId, int newUserId) {
mUserController.continueUserSwitch(userState, oldUserId, newUserId);
mInjector.mHandler.removeMessages(UserController.COMPLETE_USER_SWITCH_MSG);
- mUserController.completeUserSwitch(newUserId);
+ mUserController.completeUserSwitch(oldUserId, newUserId);
}
@Test
- public void testContinueUserSwitch() throws RemoteException {
+ public void testContinueUserSwitch() {
mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
/* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
// Start user -- this will update state of mUserController
@@ -416,12 +419,12 @@
continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
verify(mInjector, times(0)).dismissKeyguard(any(), anyString());
verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
- continueUserSwitchAssertions(TEST_USER_ID, false);
+ continueUserSwitchAssertions(oldUserId, TEST_USER_ID, false);
verifySystemUserVisibilityChangesNeverNotified();
}
@Test
- public void testContinueUserSwitchDismissKeyguard() throws RemoteException {
+ public void testContinueUserSwitchDismissKeyguard() {
when(mInjector.mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(false);
mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
/* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
@@ -437,12 +440,12 @@
continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
verify(mInjector, times(1)).dismissKeyguard(any(), anyString());
verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
- continueUserSwitchAssertions(TEST_USER_ID, false);
+ continueUserSwitchAssertions(oldUserId, TEST_USER_ID, false);
verifySystemUserVisibilityChangesNeverNotified();
}
@Test
- public void testContinueUserSwitchUIDisabled() throws RemoteException {
+ public void testContinueUserSwitchUIDisabled() {
mUserController.setInitialConfig(/* userSwitchUiEnabled= */ false,
/* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
@@ -457,11 +460,11 @@
// Verify that continueUserSwitch worked as expected
continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
verify(mInjector.getWindowManager(), never()).stopFreezingScreen();
- continueUserSwitchAssertions(TEST_USER_ID, false);
+ continueUserSwitchAssertions(oldUserId, TEST_USER_ID, false);
}
- private void continueUserSwitchAssertions(int expectedUserId, boolean backgroundUserStopping)
- throws RemoteException {
+ private void continueUserSwitchAssertions(int expectedOldUserId, int expectedNewUserId,
+ boolean backgroundUserStopping) {
Set<Integer> expectedCodes = new LinkedHashSet<>();
expectedCodes.add(COMPLETE_USER_SWITCH_MSG);
expectedCodes.add(REPORT_USER_SWITCH_COMPLETE_MSG);
@@ -473,7 +476,8 @@
assertEquals("Unexpected message sent", expectedCodes, actualCodes);
Message msg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_COMPLETE_MSG);
assertNotNull(msg);
- assertEquals("Unexpected userId", expectedUserId, msg.arg1);
+ assertEquals("Unexpected oldUserId", expectedOldUserId, msg.arg1);
+ assertEquals("Unexpected newUserId", expectedNewUserId, msg.arg2);
}
@Test
@@ -486,16 +490,21 @@
mUserController.startUser(TEST_USER_ID, true);
Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
assertNotNull(reportMsg);
+ int oldUserId = reportMsg.arg1;
int newUserId = reportMsg.arg2;
mInjector.mHandler.clearAllRecordedMessages();
// Mockito can't reset only interactions, so just verify that this hasn't been
// called with 'false' until after dispatchUserSwitchComplete.
verify(mInjector.getWindowManager(), never()).setSwitchingUser(false);
// Call dispatchUserSwitchComplete
- mUserController.dispatchUserSwitchComplete(newUserId);
+ mUserController.dispatchUserSwitchComplete(oldUserId, newUserId);
verify(observer, times(1)).onUserSwitchComplete(anyInt());
verify(observer).onUserSwitchComplete(TEST_USER_ID);
verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(false);
+ startUserAssertions(Stream.concat(
+ START_FOREGROUND_USER_ACTIONS.stream(),
+ START_FOREGROUND_USER_DEFERRED_ACTIONS.stream()
+ ).collect(Collectors.toList()), Collections.emptySet());
}
@Test
@@ -902,8 +911,7 @@
}
private void addForegroundUserAndContinueUserSwitch(int newUserId, int expectedOldUserId,
- int expectedNumberOfCalls, boolean expectOldUserStopping)
- throws RemoteException {
+ int expectedNumberOfCalls, boolean expectOldUserStopping) {
// Start user -- this will update state of mUserController
mUserController.startUser(newUserId, true);
Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
@@ -918,7 +926,7 @@
continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
verify(mInjector.getWindowManager(), times(expectedNumberOfCalls))
.stopFreezingScreen();
- continueUserSwitchAssertions(newUserId, expectOldUserStopping);
+ continueUserSwitchAssertions(oldUserId, newUserId, expectOldUserStopping);
}
private void setUpUser(@UserIdInt int userId, @UserInfoFlag int flags) {
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 3e8a070..3daf0f8 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
@@ -212,14 +212,14 @@
private ArrayList<ActivityInfo> getActivityInfoList(
String packageName, String name, boolean displayOnRemoveDevices,
- String targetDisplayCategory) {
+ String requiredDisplayCategory) {
ActivityInfo activityInfo = new ActivityInfo();
activityInfo.packageName = packageName;
activityInfo.name = name;
activityInfo.flags = displayOnRemoveDevices
? FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES : FLAG_CANNOT_DISPLAY_ON_REMOTE_DEVICES;
activityInfo.applicationInfo = mApplicationInfoMock;
- activityInfo.targetDisplayCategory = targetDisplayCategory;
+ activityInfo.requiredDisplayCategory = requiredDisplayCategory;
return new ArrayList<>(Arrays.asList(activityInfo));
}
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 ce35626..109abd0 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -319,7 +319,7 @@
when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
- final int displayIds[] = bs.getDisplayIds();
+ final int[] displayIds = bs.getDisplayIds(/* includeDisabled= */ true);
final int size = displayIds.length;
assertTrue(size > 0);
@@ -1417,7 +1417,8 @@
DisplayManagerService.BinderService displayManagerBinderService,
FakeDisplayDevice displayDevice) {
- final int[] displayIds = displayManagerBinderService.getDisplayIds();
+ final int[] displayIds = displayManagerBinderService.getDisplayIds(
+ /* includeDisabled= */ true);
assertTrue(displayIds.length > 0);
int displayId = Display.INVALID_DISPLAY;
for (int i = 0; i < displayIds.length; i++) {
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index 71f3d15..865bc98 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -200,12 +200,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testDisplayModeVoting(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testDisplayModeVoting() {
// With no votes present, DisplayModeDirector should allow any refresh rate.
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
DesiredDisplayModeSpecs modeSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
@@ -242,12 +237,7 @@
.isEqualTo((float) (minFps + i));
assertThat(modeSpecs.primary.physical.max)
.isEqualTo((float) (maxFps - i));
- if (frameRateIsRefreshRate) {
- assertThat(modeSpecs.primary.render.min)
- .isEqualTo((float) (minFps + i));
- } else {
- assertThat(modeSpecs.primary.render.min).isZero();
- }
+ assertThat(modeSpecs.primary.render.min).isZero();
assertThat(modeSpecs.primary.render.max)
.isEqualTo((float) (maxFps - i));
if (priority >= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF) {
@@ -255,12 +245,7 @@
.isEqualTo((float) (minFps + i));
assertThat(modeSpecs.appRequest.physical.max)
.isEqualTo((float) (maxFps - i));
- if (frameRateIsRefreshRate) {
- assertThat(modeSpecs.appRequest.render.min).isEqualTo(
- (float) (minFps + i));
- } else {
- assertThat(modeSpecs.appRequest.render.min).isZero();
- }
+ assertThat(modeSpecs.appRequest.render.min).isZero();
assertThat(modeSpecs.appRequest.render.max).isEqualTo(
(float) (maxFps - i));
} else {
@@ -292,12 +277,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testVotingWithFloatingPointErrors(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testVotingWithFloatingPointErrors() {
DisplayModeDirector director = createDirectorFromFpsRange(50, 90);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
@@ -318,12 +298,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testFlickerHasLowerPriorityThanUserAndRangeIsSingle(
- boolean frameRateIsRefreshRate) {
+ public void testFlickerHasLowerPriorityThanUserAndRangeIsSingle() {
assertTrue(Vote.PRIORITY_FLICKER_REFRESH_RATE
< Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
assertTrue(Vote.PRIORITY_FLICKER_REFRESH_RATE
@@ -332,7 +307,6 @@
assertTrue(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH
> Vote.PRIORITY_LOW_POWER_MODE);
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
Display.Mode[] modes = new Display.Mode[4];
modes[0] = new Display.Mode(
/*modeId=*/1, /*width=*/1000, /*height=*/1000, 60);
@@ -408,17 +382,12 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testLPMHasHigherPriorityThanUser(boolean frameRateIsRefreshRate) {
+ public void testLPMHasHigherPriorityThanUser() {
assertTrue(Vote.PRIORITY_LOW_POWER_MODE
> Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
assertTrue(Vote.PRIORITY_LOW_POWER_MODE
> Vote.PRIORITY_APP_REQUEST_SIZE);
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
Display.Mode[] modes = new Display.Mode[4];
modes[0] = new Display.Mode(
/*modeId=*/1, /*width=*/1000, /*height=*/1000, 60);
@@ -443,11 +412,7 @@
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(2);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
- } else {
- assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
- }
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
@@ -462,11 +427,7 @@
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(4);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
- } else {
- assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
- }
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(90);
assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(90);
@@ -481,11 +442,7 @@
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(2);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
- } else {
- assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
- }
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
@@ -500,21 +457,13 @@
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(4);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
- } else {
- assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
- }
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(90);
assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(90);
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testAppRequestRefreshRateRange(boolean frameRateIsRefreshRate) {
+ public void testAppRequestRefreshRateRange() {
// Confirm that the app request range doesn't include flicker or min refresh rate settings,
// but does include everything else.
assertTrue(
@@ -525,7 +474,6 @@
assertTrue(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE
>= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
Display.Mode[] modes = new Display.Mode[3];
modes[0] = new Display.Mode(
/*modeId=*/60, /*width=*/1000, /*height=*/1000, 60);
@@ -582,12 +530,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testSpecsFromRefreshRateSettings(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testSpecsFromRefreshRateSettings() {
// Confirm that, with varying settings for min, peak, and default refresh rate,
// DesiredDisplayModeSpecs is calculated correctly.
float[] refreshRates = {30.f, 60.f, 90.f, 120.f, 150.f};
@@ -607,27 +550,12 @@
RefreshRateRanges frameRateAll = new RefreshRateRanges(rangeAll, rangeAll);
RefreshRateRanges frameRate90toInf = new RefreshRateRanges(range90toInf, range90toInf);
- RefreshRateRanges frameRate0to60;
- RefreshRateRanges frameRate0to90;
- RefreshRateRanges frameRate0to120;
- RefreshRateRanges frameRate60to90;
- RefreshRateRanges frameRate90to90;
- RefreshRateRanges frameRate90to120;
- if (frameRateIsRefreshRate) {
- frameRate0to60 = new RefreshRateRanges(range0to60, range0to60);
- frameRate0to90 = new RefreshRateRanges(range0to90, range0to90);
- frameRate0to120 = new RefreshRateRanges(range0to120, range0to120);
- frameRate60to90 = new RefreshRateRanges(range60to90, range60to90);
- frameRate90to90 = new RefreshRateRanges(range90to90, range90to90);
- frameRate90to120 = new RefreshRateRanges(range90to120, range90to120);
- } else {
- frameRate0to60 = new RefreshRateRanges(rangeAll, range0to60);
- frameRate0to90 = new RefreshRateRanges(rangeAll, range0to90);
- frameRate0to120 = new RefreshRateRanges(rangeAll, range0to120);
- frameRate60to90 = new RefreshRateRanges(range60toInf, range60to90);
- frameRate90to90 = new RefreshRateRanges(range90toInf, range90to90);
- frameRate90to120 = new RefreshRateRanges(range90toInf, range90to120);
- }
+ RefreshRateRanges frameRate0to60 = new RefreshRateRanges(rangeAll, range0to60);
+ RefreshRateRanges frameRate0to90 = new RefreshRateRanges(rangeAll, range0to90);
+ RefreshRateRanges frameRate0to120 = new RefreshRateRanges(rangeAll, range0to120);
+ RefreshRateRanges frameRate60to90 = new RefreshRateRanges(range60toInf, range60to90);
+ RefreshRateRanges frameRate90to90 = new RefreshRateRanges(range90toInf, range90to90);
+ RefreshRateRanges frameRate90to120 = new RefreshRateRanges(range90toInf, range90to120);
verifySpecsWithRefreshRateSettings(director, 0, 0, 0, frameRateAll, frameRateAll);
verifySpecsWithRefreshRateSettings(director, 0, 0, 90, frameRate0to90, frameRateAll);
@@ -657,12 +585,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testBrightnessObserverCallWithRefreshRateSettings(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testBrightnessObserverCallWithRefreshRateSettings() {
// Confirm that, with varying settings for min, peak, and default refresh rate, we make the
// correct call to the brightness observer.
float[] refreshRates = {60.f, 90.f, 120.f};
@@ -677,12 +600,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testVotingWithAlwaysRespectAppRequest(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testVotingWithAlwaysRespectAppRequest() {
Display.Mode[] modes = new Display.Mode[3];
modes[0] = new Display.Mode(
/*modeId=*/50, /*width=*/1000, /*height=*/1000, 50);
@@ -711,11 +629,7 @@
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
- } else {
- assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
- }
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.baseModeId).isEqualTo(60);
@@ -734,23 +648,14 @@
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
- } else {
- assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
- }
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.baseModeId).isEqualTo(60);
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testVotingWithSwitchingTypeNone(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testVotingWithSwitchingTypeNone() {
DisplayModeDirector director = createDirectorFromFpsRange(0, 90);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
@@ -765,20 +670,11 @@
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(30);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
- } else {
- assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
- }
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(30);
assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(0);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(
- 60);
- } else {
- assertThat(desiredSpecs.appRequest.physical.max).isPositiveInfinity();
- }
+ assertThat(desiredSpecs.appRequest.physical.max).isPositiveInfinity();
assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0);
assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.baseModeId).isEqualTo(30);
@@ -800,12 +696,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testVotingWithSwitchingTypeRenderFrameRateOnly(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testVotingWithSwitchingTypeRenderFrameRateOnly() {
DisplayModeDirector director = createDirectorFromFpsRange(0, 90);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
@@ -816,24 +707,15 @@
director.injectVotesByDisplay(votesByDisplay);
assertThat(director.getModeSwitchingType())
- .isNotEqualTo(DisplayManager.SWITCHING_TYPE_NONE);
+ .isNotEqualTo(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(30);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
- } else {
- assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
- }
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(30);
assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(0);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(
- 60);
- } else {
- assertThat(desiredSpecs.appRequest.physical.max).isPositiveInfinity();
- }
+ assertThat(desiredSpecs.appRequest.physical.max).isPositiveInfinity();
assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0);
assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.baseModeId).isEqualTo(30);
@@ -846,25 +728,58 @@
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(30);
assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(30);
assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(30);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(30);
- } else {
- assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
- }
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(30);
assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(30);
assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(30);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(30);
- assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(30);
- } else {
- assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0);
- assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60);
- }
+ assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0);
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(30);
assertThat(desiredSpecs.baseModeId).isEqualTo(30);
}
@Test
+ public void testVotingWithSwitchingTypeRenderFrameRateOnlyRenderRateIsNotPhysicalRefreshRate() {
+ DisplayModeDirector director = createDirectorFromFpsRange(90, 120);
+ SparseArray<Vote> votes = new SparseArray<>();
+ SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
+ votesByDisplay.put(DISPLAY_ID, votes);
+ votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(30, 90));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60));
+
+ director.injectVotesByDisplay(votesByDisplay);
+ assertThat(director.getModeSwitchingType())
+ .isNotEqualTo(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY);
+ DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
+
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(30);
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(30);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(0);
+ assertThat(desiredSpecs.appRequest.physical.max).isPositiveInfinity();
+ assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0);
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.baseModeId).isEqualTo(90);
+
+ director.setModeSwitchingType(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY);
+ assertThat(director.getModeSwitchingType())
+ .isEqualTo(DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY);
+
+ desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0);
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60);
+
+ assertThat(desiredSpecs.baseModeId).isEqualTo(90);
+ }
+
+ @Test
public void testVotingWithSwitchingTypeWithinGroups() {
DisplayModeDirector director = createDirectorFromFpsRange(0, 90);
@@ -887,12 +802,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testDefaultDisplayModeIsSelectedIfAvailable(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testDefaultDisplayModeIsSelectedIfAvailable() {
final float[] refreshRates = new float[]{24f, 25f, 30f, 60f, 90f};
final int defaultModeId = 3;
DisplayModeDirector director = createDirectorFromRefreshRateArray(
@@ -1173,17 +1083,12 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testAppRequestMinRefreshRate(boolean frameRateIsRefreshRate) {
+ public void testAppRequestMinRefreshRate() {
// Confirm that the app min request range doesn't include flicker or min refresh rate
// settings but does include everything else.
assertTrue(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE
>= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
Display.Mode[] modes = new Display.Mode[3];
modes[0] = new Display.Mode(
/*modeId=*/60, /*width=*/1000, /*height=*/1000, 60);
@@ -1225,11 +1130,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testAppRequestMaxRefreshRate(boolean frameRateIsRefreshRate) {
+ public void testAppRequestMaxRefreshRate() {
// Confirm that the app max request range doesn't include flicker or min refresh rate
// settings but does include everything else.
assertTrue(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE
@@ -1243,7 +1144,6 @@
modes[2] = new Display.Mode(
/*modeId=*/90, /*width=*/1000, /*height=*/1000, 90);
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
DisplayModeDirector director = createDirectorFromModeArray(modes, modes[1]);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
@@ -1254,19 +1154,11 @@
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60);
- } else {
- assertThat(desiredSpecs.primary.render.min).isZero();
- }
+ assertThat(desiredSpecs.primary.render.min).isZero();
assertThat(desiredSpecs.primary.render.max).isAtMost(60);
assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f);
assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.appRequest.render.min).isAtMost(60f);
- } else {
- assertThat(desiredSpecs.appRequest.render.min).isZero();
- }
+ assertThat(desiredSpecs.appRequest.render.min).isZero();
assertThat(desiredSpecs.appRequest.render.max).isAtLeast(90f);
votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
@@ -1288,30 +1180,16 @@
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(75);
assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(75);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(75);
- } else {
- assertThat(desiredSpecs.primary.render.min).isZero();
- }
+ assertThat(desiredSpecs.primary.render.min).isZero();
assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(75);
assertThat(desiredSpecs.appRequest.physical.min).isZero();
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(
- 75);
- } else {
- assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f);
- }
+ assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f);
assertThat(desiredSpecs.appRequest.render.min).isZero();
assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(75);
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testAppRequestObserver_modeId(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testAppRequestObserver_modeId() {
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 60, 0, 0);
@@ -1373,12 +1251,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testAppRequestObserver_minRefreshRate(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testAppRequestObserver_minRefreshRate() {
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 60, 0);
Vote appRequestRefreshRate =
@@ -1391,15 +1264,9 @@
Vote appRequestRefreshRateRange =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
assertNotNull(appRequestRefreshRateRange);
- if (frameRateIsRefreshRate) {
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min)
- .isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max).isAtLeast(90);
- } else {
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero();
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
- .isPositiveInfinity();
- }
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero();
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
+ .isPositiveInfinity();
assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min)
.isWithin(FLOAT_TOLERANCE).of(60);
assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max).isAtLeast(90);
@@ -1417,15 +1284,9 @@
appRequestRefreshRateRange =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
assertNotNull(appRequestRefreshRateRange);
- if (frameRateIsRefreshRate) {
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isWithin(
- FLOAT_TOLERANCE).of(90);
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max).isAtLeast(90);
- } else {
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero();
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
- .isPositiveInfinity();
- }
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero();
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
+ .isPositiveInfinity();
assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min)
.isWithin(FLOAT_TOLERANCE).of(90);
@@ -1435,12 +1296,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testAppRequestObserver_maxRefreshRate(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testAppRequestObserver_maxRefreshRate() {
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 0, 90);
Vote appRequestRefreshRate =
@@ -1454,13 +1310,8 @@
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
assertNotNull(appRequestRefreshRateRange);
assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero();
- if (frameRateIsRefreshRate) {
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
- .isWithin(FLOAT_TOLERANCE).of(90);
- } else {
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
- .isPositiveInfinity();
- }
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
+ .isPositiveInfinity();
assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min).isZero();
assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max)
@@ -1480,13 +1331,8 @@
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
assertNotNull(appRequestRefreshRateRange);
assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero();
- if (frameRateIsRefreshRate) {
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
- .isWithin(FLOAT_TOLERANCE).of(60);
- } else {
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
- .isPositiveInfinity();
- }
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
+ .isPositiveInfinity();
assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min).isZero();
assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max)
@@ -1512,12 +1358,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testAppRequestObserver_modeIdAndRefreshRateRange(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testAppRequestObserver_modeIdAndRefreshRateRange() {
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 60, 90, 90);
@@ -1547,16 +1388,9 @@
Vote appRequestRefreshRateRange =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
assertNotNull(appRequestRefreshRateRange);
- if (frameRateIsRefreshRate) {
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min)
- .isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
- .isWithin(FLOAT_TOLERANCE).of(90);
- } else {
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero();
- assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
- .isPositiveInfinity();
- }
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero();
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
+ .isPositiveInfinity();
assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min)
.isWithin(FLOAT_TOLERANCE).of(90);
assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max)
@@ -1566,12 +1400,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testAppRequestsIsTheDefaultMode(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testAppRequestsIsTheDefaultMode() {
Display.Mode[] modes = new Display.Mode[2];
modes[0] = new Display.Mode(
/*modeId=*/1, /*width=*/1000, /*height=*/1000, 60);
@@ -1600,12 +1429,7 @@
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testDisableRefreshRateSwitchingVote(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testDisableRefreshRateSwitchingVote() {
DisplayModeDirector director = createDirectorFromFpsRange(50, 90);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
@@ -1650,8 +1474,8 @@
"true",
"false"
})
- public void testBaseModeIdInPrimaryRange(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testBaseModeIdInPrimaryRange(boolean supportsFrameRateOverride) {
+ when(mInjector.supportsFrameRateOverride()).thenReturn(supportsFrameRateOverride);
DisplayModeDirector director = createDirectorFromFpsRange(50, 90);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
@@ -1662,12 +1486,12 @@
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(0);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.baseModeId).isEqualTo(50);
- } else {
- assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ if (supportsFrameRateOverride) {
assertThat(desiredSpecs.baseModeId).isEqualTo(70);
+ } else {
+ assertThat(desiredSpecs.baseModeId).isEqualTo(50);
+
}
assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0);
assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
@@ -1679,11 +1503,7 @@
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(0);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
- } else {
- assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
- }
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0);
assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.baseModeId).isEqualTo(55);
@@ -1697,12 +1517,11 @@
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(0);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
- } else {
- assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ if (supportsFrameRateOverride) {
assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(52);
+ } else {
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
}
assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0);
assertThat(desiredSpecs.baseModeId).isEqualTo(55);
@@ -1716,23 +1535,14 @@
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(0);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(58);
- } else {
- assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
- }
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0);
assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(58);
assertThat(desiredSpecs.baseModeId).isEqualTo(55);
}
@Test
- @Parameters({
- "true",
- "false"
- })
- public void testStaleAppVote(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testStaleAppVote() {
Display.Mode[] modes = new Display.Mode[4];
modes[0] = new Display.Mode(
/*modeId=*/1, /*width=*/1000, /*height=*/1000, 60);
@@ -1782,8 +1592,8 @@
"true",
"false"
})
- public void testRefreshRateIsSubsetOfFrameRate(boolean frameRateIsRefreshRate) {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ public void testRefreshRateIsSubsetOfFrameRate(boolean supportsFrameRateOverride) {
+ when(mInjector.supportsFrameRateOverride()).thenReturn(supportsFrameRateOverride);
DisplayModeDirector director = createDirectorFromFpsRange(60, 120);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
@@ -1795,11 +1605,7 @@
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(90);
- } else {
- assertThat(desiredSpecs.appRequest.render.min).isZero();
- }
+ assertThat(desiredSpecs.appRequest.render.min).isZero();
assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(120);
votes.clear();
@@ -1810,13 +1616,11 @@
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(
- 120);
- } else {
- assertThat(desiredSpecs.appRequest.render.min).isZero();
+ assertThat(desiredSpecs.appRequest.render.min).isZero();
+ if (supportsFrameRateOverride) {
assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60);
+ } else {
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(120);
}
votes.clear();
@@ -1827,13 +1631,12 @@
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(
- 120);
- } else {
+ if (supportsFrameRateOverride) {
assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60);
+ } else {
+ assertThat(desiredSpecs.appRequest.render.min).isZero();
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(120);
}
votes.clear();
@@ -1844,17 +1647,12 @@
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120);
- if (frameRateIsRefreshRate) {
- assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(90);
- } else {
- assertThat(desiredSpecs.appRequest.render.min).isZero();
- }
+ assertThat(desiredSpecs.appRequest.render.min).isZero();
assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(120);
}
@Test
public void testRenderFrameRateIsAchievableByPhysicalRefreshRate() {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(false);
DisplayModeDirector director = createDirectorFromFpsRange(60, 120);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
@@ -1872,8 +1670,34 @@
}
@Test
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testRenderFrameRateIncludesPhysicalRefreshRate(boolean supportsFrameRateOverride) {
+ when(mInjector.supportsFrameRateOverride()).thenReturn(supportsFrameRateOverride);
+ DisplayModeDirector director = createDirectorFromFpsRange(60, 120);
+ SparseArray<Vote> votes = new SparseArray<>();
+ SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
+ votesByDisplay.put(DISPLAY_ID, votes);
+
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60));
+ votes.put(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(0, 30));
+ director.injectVotesByDisplay(votesByDisplay);
+ DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
+ assertThat(desiredSpecs.appRequest.physical.min).isZero();
+ assertThat(desiredSpecs.appRequest.physical.max).isPositiveInfinity();
+ assertThat(desiredSpecs.appRequest.render.min).isZero();
+ if (supportsFrameRateOverride) {
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(30);
+ } else {
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60);
+ }
+ }
+
+ @Test
public void testRenderFrameRateIsDroppedIfLowerPriorityThenBaseModeRefreshRate() {
- when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(false);
DisplayModeDirector director = createDirectorFromFpsRange(60, 120);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
@@ -2692,7 +2516,7 @@
}
@Override
- public boolean renderFrameRateIsPhysicalRefreshRate() {
+ public boolean supportsFrameRateOverride() {
return true;
}
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 657bda6..246945c 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -30,6 +30,8 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
@@ -52,6 +54,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.display.layout.Layout;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -59,6 +63,7 @@
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
import java.io.InputStream;
import java.io.OutputStream;
@@ -83,6 +88,7 @@
@Mock Resources mResourcesMock;
@Mock IPowerManager mIPowerManagerMock;
@Mock IThermalService mIThermalServiceMock;
+ @Spy DeviceStateToLayoutMap mDeviceStateToLayoutMapSpy = new DeviceStateToLayoutMap();
@Captor ArgumentCaptor<LogicalDisplay> mDisplayCaptor;
@@ -132,7 +138,8 @@
mLooper = new TestLooper();
mHandler = new Handler(mLooper.getLooper());
mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mDisplayDeviceRepo,
- mListenerMock, new DisplayManagerService.SyncRoot(), mHandler);
+ mListenerMock, new DisplayManagerService.SyncRoot(), mHandler,
+ mDeviceStateToLayoutMapSpy);
}
@@ -259,7 +266,8 @@
add(createDisplayDevice(Display.TYPE_EXTERNAL, 600, 800, 0));
add(createDisplayDevice(Display.TYPE_VIRTUAL, 600, 800, 0));
- int [] ids = mLogicalDisplayMapper.getDisplayIdsLocked(Process.SYSTEM_UID);
+ int [] ids = mLogicalDisplayMapper.getDisplayIdsLocked(Process.SYSTEM_UID,
+ /* includeDisabled= */ true);
assertEquals(3, ids.length);
Arrays.sort(ids);
assertEquals(DEFAULT_DISPLAY, ids[0]);
@@ -503,10 +511,183 @@
/* isBootCompleted= */true));
}
+ @Test
+ public void testDeviceStateLocked() {
+ DisplayDevice device1 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
+ DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
+ DisplayDevice device2 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
+ DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
+
+ Layout layout = new Layout();
+ layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address, true, true);
+ layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address, false, false);
+ when(mDeviceStateToLayoutMapSpy.get(0)).thenReturn(layout);
+
+ layout = new Layout();
+ layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address, false, false);
+ layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address, true, true);
+ when(mDeviceStateToLayoutMapSpy.get(1)).thenReturn(layout);
+ when(mDeviceStateToLayoutMapSpy.get(2)).thenReturn(layout);
+
+ LogicalDisplay display1 = add(device1);
+ assertEquals(info(display1).address, info(device1).address);
+ assertEquals(DEFAULT_DISPLAY, id(display1));
+
+ LogicalDisplay display2 = add(device2);
+ assertEquals(info(display2).address, info(device2).address);
+ // We can only have one default display
+ assertEquals(DEFAULT_DISPLAY, id(display1));
+
+ mLogicalDisplayMapper.setDeviceStateLocked(0, false);
+ advanceTime(1000);
+ assertTrue(mLogicalDisplayMapper.getDisplayLocked(device1).isEnabledLocked());
+ assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
+ assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
+ assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
+
+ mLogicalDisplayMapper.setDeviceStateLocked(1, false);
+ advanceTime(1000);
+ assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isEnabledLocked());
+ assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
+ assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
+ assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
+
+ mLogicalDisplayMapper.setDeviceStateLocked(2, false);
+ advanceTime(1000);
+ assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isEnabledLocked());
+ assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
+ assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
+ assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
+ }
+
+ @Test
+ public void testEnabledAndDisabledDisplays() {
+ DisplayAddress displayAddressOne = new TestUtils.TestDisplayAddress();
+ DisplayAddress displayAddressTwo = new TestUtils.TestDisplayAddress();
+ DisplayAddress displayAddressThree = new TestUtils.TestDisplayAddress();
+
+ TestDisplayDevice device1 = createDisplayDevice(displayAddressOne, "one",
+ Display.TYPE_INTERNAL, 600, 800,
+ DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
+ TestDisplayDevice device2 = createDisplayDevice(displayAddressTwo, "two",
+ Display.TYPE_INTERNAL, 200, 800,
+ DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
+ TestDisplayDevice device3 = createDisplayDevice(displayAddressThree, "three",
+ Display.TYPE_INTERNAL, 600, 900,
+ DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
+
+ Layout threeDevicesEnabledLayout = new Layout();
+ threeDevicesEnabledLayout.createDisplayLocked(
+ displayAddressOne,
+ /* isDefault= */ true,
+ /* isEnabled= */ true);
+ threeDevicesEnabledLayout.createDisplayLocked(
+ displayAddressTwo,
+ /* isDefault= */ false,
+ /* isEnabled= */ true);
+ threeDevicesEnabledLayout.createDisplayLocked(
+ displayAddressThree,
+ /* isDefault= */ false,
+ /* isEnabled= */ true);
+
+ when(mDeviceStateToLayoutMapSpy.get(DeviceStateToLayoutMap.STATE_DEFAULT))
+ .thenReturn(threeDevicesEnabledLayout);
+
+ LogicalDisplay display1 = add(device1);
+ LogicalDisplay display2 = add(device2);
+ LogicalDisplay display3 = add(device3);
+
+ // ensure 3 displays are returned
+ int [] ids = mLogicalDisplayMapper.getDisplayIdsLocked(Process.SYSTEM_UID, false);
+ assertEquals(3, ids.length);
+ Arrays.sort(ids);
+ assertEquals(DEFAULT_DISPLAY, ids[0]);
+ assertNotNull(mLogicalDisplayMapper.getDisplayLocked(device1,
+ /* includeDisabled= */ false));
+ assertNotNull(mLogicalDisplayMapper.getDisplayLocked(device2,
+ /* includeDisabled= */ false));
+ assertNotNull(mLogicalDisplayMapper.getDisplayLocked(device3,
+ /* includeDisabled= */ false));
+ assertNotNull(mLogicalDisplayMapper.getDisplayLocked(
+ threeDevicesEnabledLayout.getByAddress(displayAddressOne).getLogicalDisplayId(),
+ /* includeDisabled= */ false));
+ assertNotNull(mLogicalDisplayMapper.getDisplayLocked(
+ threeDevicesEnabledLayout.getByAddress(displayAddressTwo).getLogicalDisplayId(),
+ /* includeDisabled= */ false));
+ assertNotNull(mLogicalDisplayMapper.getDisplayLocked(
+ threeDevicesEnabledLayout.getByAddress(displayAddressThree).getLogicalDisplayId(),
+ /* includeDisabled= */ false));
+
+ Layout oneDeviceEnabledLayout = new Layout();
+ oneDeviceEnabledLayout.createDisplayLocked(
+ displayAddressOne,
+ /* isDefault= */ true,
+ /* isEnabled= */ true);
+ oneDeviceEnabledLayout.createDisplayLocked(
+ displayAddressTwo,
+ /* isDefault= */ false,
+ /* isEnabled= */ false);
+ oneDeviceEnabledLayout.createDisplayLocked(
+ displayAddressThree,
+ /* isDefault= */ false,
+ /* isEnabled= */ false);
+
+ when(mDeviceStateToLayoutMapSpy.get(0)).thenReturn(oneDeviceEnabledLayout);
+ when(mDeviceStateToLayoutMapSpy.get(1)).thenReturn(threeDevicesEnabledLayout);
+
+ // 1) Set the new state
+ // 2) Mark the displays as STATE_OFF so that it can continue with transition
+ // 3) Send DISPLAY_DEVICE_EVENT_CHANGE to inform the mapper of the new display state
+ // 4) Dispatch handler events.
+ mLogicalDisplayMapper.setDeviceStateLocked(0, false);
+ mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED);
+ advanceTime(1000);
+ final int[] allDisplayIds = mLogicalDisplayMapper.getDisplayIdsLocked(
+ Process.SYSTEM_UID, false);
+ if (allDisplayIds.length != 1) {
+ throw new RuntimeException("Displays: \n"
+ + mLogicalDisplayMapper.getDisplayLocked(device1).toString()
+ + "\n" + mLogicalDisplayMapper.getDisplayLocked(device2).toString()
+ + "\n" + mLogicalDisplayMapper.getDisplayLocked(device3).toString());
+ }
+ // ensure only one display is returned
+ assertEquals(1, allDisplayIds.length);
+ assertNotNull(mLogicalDisplayMapper.getDisplayLocked(device1,
+ /* includeDisabled= */ false));
+ assertNull(mLogicalDisplayMapper.getDisplayLocked(device2,
+ /* includeDisabled= */ false));
+ assertNull(mLogicalDisplayMapper.getDisplayLocked(device3,
+ /* includeDisabled= */ false));
+ assertNotNull(mLogicalDisplayMapper.getDisplayLocked(
+ oneDeviceEnabledLayout.getByAddress(displayAddressOne).getLogicalDisplayId(),
+ /* includeDisabled= */ false));
+ assertNull(mLogicalDisplayMapper.getDisplayLocked(
+ oneDeviceEnabledLayout.getByAddress(displayAddressTwo).getLogicalDisplayId(),
+ /* includeDisabled= */ false));
+ assertNull(mLogicalDisplayMapper.getDisplayLocked(
+ oneDeviceEnabledLayout.getByAddress(displayAddressThree).getLogicalDisplayId(),
+ /* includeDisabled= */ false));
+
+ // Now do it again to go back to state 1
+ mLogicalDisplayMapper.setDeviceStateLocked(1, false);
+ mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED);
+ advanceTime(1000);
+ final int[] threeDisplaysEnabled = mLogicalDisplayMapper.getDisplayIdsLocked(
+ Process.SYSTEM_UID, false);
+
+ // ensure all three displays are returned
+ assertEquals(3, threeDisplaysEnabled.length);
+ }
+
/////////////////
// Helper Methods
/////////////////
+ private void advanceTime(long timeMs) {
+ mLooper.moveTimeForward(1000);
+ mLooper.dispatchAll();
+ }
+
private TestDisplayDevice createDisplayDevice(int type, int width, int height, int flags) {
return createDisplayDevice(
new TestUtils.TestDisplayAddress(), /* uniqueId */ "", type, width, height, flags);
@@ -575,6 +756,7 @@
class TestDisplayDevice extends DisplayDevice {
private DisplayDeviceInfo mInfo;
private DisplayDeviceInfo mSentInfo;
+ private int mState;
TestDisplayDevice() {
super(null, null, "test_display_" + sUniqueTestDisplayId++, mContextMock);
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
index 5a43530..1d70fc6 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
@@ -126,12 +126,12 @@
verify(t).setDisplayFlags(any(), eq(SurfaceControl.DISPLAY_RECEIVES_INPUT));
reset(t);
- mLogicalDisplay.setPhase(LogicalDisplay.DISPLAY_PHASE_DISABLED);
+ mLogicalDisplay.setEnabledLocked(false);
mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false);
verify(t).setDisplayFlags(any(), eq(0));
reset(t);
- mLogicalDisplay.setPhase(LogicalDisplay.DISPLAY_PHASE_ENABLED);
+ mLogicalDisplay.setEnabledLocked(true);
mDisplayDeviceInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false);
verify(t).setDisplayFlags(any(), eq(SurfaceControl.DISPLAY_RECEIVES_INPUT));
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java b/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java
index e3ca170..b034b0d 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java
@@ -21,7 +21,6 @@
import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DIM;
import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE;
import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_OFF;
-import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_VR;
import static android.os.PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
import static android.os.PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN;
import static android.os.PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD;
@@ -267,7 +266,6 @@
powerSaveState,
/* quiescent= */ false,
/* dozeAfterScreenOff= */ false,
- /* vrModeEnabled= */ false,
/* bootCompleted= */ true,
/* screenBrightnessBoostInProgress= */ false,
/* waitForNegativeProximity= */ false);
@@ -308,7 +306,6 @@
powerSaveState,
/* quiescent= */ false,
/* dozeAfterScreenOff= */ false,
- /* vrModeEnabled= */ false,
/* bootCompleted= */ true,
/* screenBrightnessBoostInProgress= */ false,
/* waitForNegativeProximity= */ false);
@@ -348,7 +345,6 @@
powerSaveState,
/* quiescent= */ false,
/* dozeAfterScreenOff= */ true,
- /* vrModeEnabled= */ false,
/* bootCompleted= */ true,
/* screenBrightnessBoostInProgress= */ false,
/* waitForNegativeProximity= */ false);
@@ -387,7 +383,6 @@
powerSaveState,
/* quiescent= */ true,
/* dozeAfterScreenOff= */ true,
- /* vrModeEnabled= */ false,
/* bootCompleted= */ true,
/* screenBrightnessBoostInProgress= */ false,
/* waitForNegativeProximity= */ false);
@@ -407,83 +402,6 @@
}
@Test
- public void testUpdateWhileAsleep_VrModeEnabled() {
- final boolean batterySaverEnabled = false;
- float brightnessFactor = 0.3f;
- PowerSaveState powerSaveState = new PowerSaveState.Builder()
- .setBatterySaverEnabled(batterySaverEnabled)
- .setBrightnessFactor(brightnessFactor)
- .build();
- mPowerGroup.sleepLocked(TIMESTAMP1, UID, GO_TO_SLEEP_REASON_TIMEOUT);
- assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
- mPowerGroup.updateLocked(/* screenBrightnessOverride= */ BRIGHTNESS,
- /* autoBrightness = */ true,
- /* useProximitySensor= */ true,
- /* boostScreenBrightness= */ true,
- /* dozeScreenStateOverride= */ Display.STATE_ON,
- /* dozeScreenBrightness= */ BRIGHTNESS_DOZE,
- /* overrideDrawWakeLock= */ false,
- powerSaveState,
- /* quiescent= */ false,
- /* dozeAfterScreenOff= */ true,
- /* vrModeEnabled= */ true,
- /* bootCompleted= */ true,
- /* screenBrightnessBoostInProgress= */ false,
- /* waitForNegativeProximity= */ false);
- DisplayManagerInternal.DisplayPowerRequest displayPowerRequest =
- mPowerGroup.mDisplayPowerRequest;
- assertThat(displayPowerRequest.policy).isEqualTo(POLICY_OFF);
- assertThat(displayPowerRequest.screenBrightnessOverride).isWithin(PRECISION).of(BRIGHTNESS);
- assertThat(displayPowerRequest.useAutoBrightness).isEqualTo(true);
- assertThat(displayPowerRequest.useProximitySensor).isEqualTo(true);
- assertThat(displayPowerRequest.boostScreenBrightness).isEqualTo(true);
- assertThat(displayPowerRequest.dozeScreenState).isEqualTo(Display.STATE_UNKNOWN);
- assertThat(displayPowerRequest.dozeScreenBrightness).isEqualTo(
- PowerManager.BRIGHTNESS_INVALID_FLOAT);
- assertThat(displayPowerRequest.lowPowerMode).isEqualTo(batterySaverEnabled);
- assertThat(displayPowerRequest.screenLowPowerBrightnessFactor).isWithin(PRECISION).of(
- brightnessFactor);
- }
-
- @Test
- public void testUpdateWhileAwake_VrModeEnabled() {
- final boolean batterySaverEnabled = false;
- float brightnessFactor = 0.3f;
- PowerSaveState powerSaveState = new PowerSaveState.Builder()
- .setBatterySaverEnabled(batterySaverEnabled)
- .setBrightnessFactor(brightnessFactor)
- .build();
- assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
- mPowerGroup.updateLocked(/* screenBrightnessOverride= */ BRIGHTNESS,
- /* autoBrightness = */ true,
- /* useProximitySensor= */ true,
- /* boostScreenBrightness= */ true,
- /* dozeScreenStateOverride= */ Display.STATE_ON,
- /* dozeScreenBrightness= */ BRIGHTNESS_DOZE,
- /* overrideDrawWakeLock= */ false,
- powerSaveState,
- /* quiescent= */ false,
- /* dozeAfterScreenOff= */ true,
- /* vrModeEnabled= */ true,
- /* bootCompleted= */ true,
- /* screenBrightnessBoostInProgress= */ false,
- /* waitForNegativeProximity= */ false);
- DisplayManagerInternal.DisplayPowerRequest displayPowerRequest =
- mPowerGroup.mDisplayPowerRequest;
- assertThat(displayPowerRequest.policy).isEqualTo(POLICY_VR);
- assertThat(displayPowerRequest.screenBrightnessOverride).isWithin(PRECISION).of(BRIGHTNESS);
- assertThat(displayPowerRequest.useAutoBrightness).isEqualTo(true);
- assertThat(displayPowerRequest.useProximitySensor).isEqualTo(true);
- assertThat(displayPowerRequest.boostScreenBrightness).isEqualTo(true);
- assertThat(displayPowerRequest.dozeScreenState).isEqualTo(Display.STATE_UNKNOWN);
- assertThat(displayPowerRequest.dozeScreenBrightness).isEqualTo(
- PowerManager.BRIGHTNESS_INVALID_FLOAT);
- assertThat(displayPowerRequest.lowPowerMode).isEqualTo(batterySaverEnabled);
- assertThat(displayPowerRequest.screenLowPowerBrightnessFactor).isWithin(PRECISION).of(
- brightnessFactor);
- }
-
- @Test
public void testUpdateWhileAsleep_UpdatesDisplayPowerRequest() {
final boolean batterySaverEnabled = false;
float brightnessFactor = 0.3f;
@@ -503,7 +421,6 @@
powerSaveState,
/* quiescent= */ false,
/* dozeAfterScreenOff= */ false,
- /* vrModeEnabled= */ false,
/* bootCompleted= */ true,
/* screenBrightnessBoostInProgress= */ false,
/* waitForNegativeProximity= */ false);
@@ -543,7 +460,6 @@
powerSaveState,
/* quiescent= */ false,
/* dozeAfterScreenOff= */ false,
- /* vrModeEnabled= */ false,
/* bootCompleted= */ true,
/* screenBrightnessBoostInProgress= */ false,
/* waitForNegativeProximity= */ false);
@@ -581,7 +497,6 @@
powerSaveState,
/* quiescent= */ false,
/* dozeAfterScreenOff= */ false,
- /* vrModeEnabled= */ false,
/* bootCompleted= */ false,
/* screenBrightnessBoostInProgress= */ false,
/* waitForNegativeProximity= */ false);
@@ -620,7 +535,6 @@
powerSaveState,
/* quiescent= */ false,
/* dozeAfterScreenOff= */ false,
- /* vrModeEnabled= */ false,
/* bootCompleted= */ true,
/* screenBrightnessBoostInProgress= */ false,
/* waitForNegativeProximity= */ false);
@@ -658,7 +572,6 @@
powerSaveState,
/* quiescent= */ false,
/* dozeAfterScreenOff= */ false,
- /* vrModeEnabled= */ false,
/* bootCompleted= */ true,
/* screenBrightnessBoostInProgress= */ true,
/* waitForNegativeProximity= */ false);
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 6258d6d..d7ff553 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -454,39 +454,6 @@
}
@Test
- public void testGetDesiredScreenPolicy_WithVR() {
- createService();
- startSystem();
- // Brighten up the screen
- mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_AWAKE, 0, 0, 0, 0,
- null, null);
- assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY)).isEqualTo(
- DisplayPowerRequest.POLICY_BRIGHT);
-
- // Move to VR
- mService.setVrModeEnabled(true);
- assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY)).isEqualTo(
- DisplayPowerRequest.POLICY_VR);
-
- // Then take a nap
- mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
- null, null);
- assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY)).isEqualTo(
- DisplayPowerRequest.POLICY_OFF);
-
- // Wake up to VR
- mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_AWAKE, 0, 0, 0, 0,
- null, null);
- assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY)).isEqualTo(
- DisplayPowerRequest.POLICY_VR);
-
- // And back to normal
- mService.setVrModeEnabled(false);
- assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY)).isEqualTo(
- DisplayPowerRequest.POLICY_BRIGHT);
- }
-
- @Test
public void testWakefulnessAwake_InitialValue() {
createService();
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
@@ -1787,10 +1754,8 @@
when(mNativeWrapperMock.nativeSetPowerMode(anyInt(), anyBoolean())).thenReturn(true);
mService.getBinderServiceInstance().setPowerMode(Mode.LAUNCH, true);
- mService.getBinderServiceInstance().setPowerMode(Mode.VR, false);
verify(mNativeWrapperMock).nativeSetPowerMode(eq(Mode.LAUNCH), eq(true));
- verify(mNativeWrapperMock).nativeSetPowerMode(eq(Mode.VR), eq(false));
}
@Test
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp4.xml b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp4.xml
index 4dcb442..5451735 100644
--- a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp4.xml
+++ b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp4.xml
@@ -32,7 +32,7 @@
<activity android:name="com.android.servicestests.apps.packageparserapp.MyActivity"
android:exported="true"
- android:targetDisplayCategory="automotive">
+ android:requiredDisplayCategory="automotive">
<property android:name="android.cts.PROPERTY_ACTIVITY" android:value="@integer/integer_property" />
<property android:name="android.cts.PROPERTY_COMPONENT" android:value="@integer/integer_property" />
<property android:name="android.cts.PROPERTY_STRING" android:value="koala activity" />
diff --git a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp6.xml b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp6.xml
index 8e694e1..601479d 100644
--- a/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp6.xml
+++ b/services/tests/servicestests/test-apps/PackageParserApp/AndroidManifestApp6.xml
@@ -21,7 +21,7 @@
<application>
<activity android:name="com.android.servicestests.apps.packageparserapp.MyActivity"
android:exported="true"
- android:targetDisplayCategory="$automotive">
+ android:requiredDisplayCategory="$automotive">
</activity>
</application>
</manifest>
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index c898119..cdb2642 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -443,6 +443,44 @@
}
@Test
+ public void testUpdateAboveInsetsState_imeTargetOnScreenBehavior() {
+ final WindowToken imeToken = createTestWindowToken(TYPE_INPUT_METHOD, mDisplayContent);
+ final WindowState ime = createWindow(null, TYPE_INPUT_METHOD, imeToken, "ime");
+ final WindowState app = createTestWindow("app");
+
+ getController().getSourceProvider(ITYPE_IME).setWindowContainer(ime, null, null);
+ ime.getControllableInsetProvider().setServerVisible(true);
+
+ app.mActivityRecord.setVisibility(true);
+ mDisplayContent.setImeLayeringTarget(app);
+ mDisplayContent.updateImeInputAndControlTarget(app);
+
+ app.setRequestedVisibleTypes(ime(), ime());
+ getController().onInsetsModified(app);
+ assertTrue(ime.getControllableInsetProvider().getSource().isVisible());
+
+ getController().updateAboveInsetsState(true /* notifyInsetsChange */);
+ assertNotNull(app.getInsetsState().peekSource(ITYPE_IME));
+ verify(app, atLeastOnce()).notifyInsetsChanged();
+
+ // Expect the app will still get IME insets even when the app was invisible.
+ // (i.e. app invisible after locking the device)
+ app.mActivityRecord.setVisible(false);
+ app.setHasSurface(false);
+ getController().updateAboveInsetsState(true /* notifyInsetsChange */);
+ assertNotNull(app.getInsetsState().peekSource(ITYPE_IME));
+ verify(app, atLeastOnce()).notifyInsetsChanged();
+
+ // Expect the app will get IME insets when the app is requesting visible.
+ // (i.e. app is going to visible when unlocking the device)
+ app.mActivityRecord.setVisibility(true);
+ assertTrue(app.isVisibleRequested());
+ getController().updateAboveInsetsState(true /* notifyInsetsChange */);
+ assertNotNull(app.getInsetsState().peekSource(ITYPE_IME));
+ verify(app, atLeastOnce()).notifyInsetsChanged();
+ }
+
+ @Test
public void testDispatchGlobalInsets() {
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindowContainer(navBar, null,
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index c548dc3..eb26415 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -772,6 +772,7 @@
// Simulating now win1 is being covered by the lockscreen which has no surface,
// and then launching an activity win2 with the remote animation
win1.mHasSurface = false;
+ win1.mActivityRecord.setVisibility(false);
mDisplayContent.mOpeningApps.add(win2.mActivityRecord);
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
win2.mActivityRecord, new Point(50, 100), null,
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index a4cc09a..e7813ff 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -893,11 +893,10 @@
}
@Test
- public void testLaunchesPortraitUnresizableOnFreeformLandscapeDisplay() {
+ public void testLaunchesPortraitUnresizableOnFreeformDisplayWithFreeformSizeCompat() {
mAtm.mDevEnableNonResizableMultiWindow = true;
final TestDisplayContent freeformDisplay = createNewDisplayContent(
WINDOWING_MODE_FREEFORM);
- assertTrue(freeformDisplay.getBounds().width() > freeformDisplay.getBounds().height());
final ActivityOptions options = ActivityOptions.makeBasic();
mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
@@ -905,42 +904,12 @@
assertEquals(RESULT_CONTINUE,
new CalculateRequestBuilder().setOptions(options).calculate());
- assertEquals(WINDOWING_MODE_UNDEFINED, mResult.mWindowingMode);
- }
-
- @Test
- public void testLaunchesLandscapeUnresizableOnFreeformLandscapeDisplay() {
- mAtm.mDevEnableNonResizableMultiWindow = true;
- final TestDisplayContent freeformDisplay = createNewDisplayContent(
+ assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
WINDOWING_MODE_FREEFORM);
- assertTrue(freeformDisplay.getBounds().width() > freeformDisplay.getBounds().height());
- final ActivityOptions options = ActivityOptions.makeBasic();
- mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
- mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
- mActivity.info.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
- assertEquals(RESULT_CONTINUE,
- new CalculateRequestBuilder().setOptions(options).calculate());
-
- assertEquals(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode);
}
@Test
- public void testLaunchesUndefinedUnresizableOnFreeformLandscapeDisplay() {
- mAtm.mDevEnableNonResizableMultiWindow = true;
- final TestDisplayContent freeformDisplay = createNewDisplayContent(
- WINDOWING_MODE_FREEFORM);
- assertTrue(freeformDisplay.getBounds().width() > freeformDisplay.getBounds().height());
- final ActivityOptions options = ActivityOptions.makeBasic();
- mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
- mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
- assertEquals(RESULT_CONTINUE,
- new CalculateRequestBuilder().setOptions(options).calculate());
-
- assertEquals(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode);
- }
-
- @Test
- public void testForceMaximizingAppsOnNonFreeformDisplay() {
+ public void testSkipsForceMaximizingAppsOnNonFreeformDisplay() {
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
options.setLaunchBounds(new Rect(0, 0, 200, 100));
@@ -954,9 +923,8 @@
assertEquals(RESULT_CONTINUE,
new CalculateRequestBuilder().setOptions(options).calculate());
- // Non-resizable apps must be launched in fullscreen in a fullscreen display regardless of
- // other properties.
- assertEquals(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode);
+ assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
+ WINDOWING_MODE_FULLSCREEN);
}
@Test
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java
index 7657454..81cd194 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java
@@ -19,6 +19,13 @@
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.service.voice.HotwordAudioStream.KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES;
+import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_CLOSE_ERROR_FROM_SYSTEM;
+import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_EMPTY_AUDIO_STREAM_LIST;
+import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_END;
+import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_ILLEGAL_COPY_BUFFER_SIZE;
+import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_INTERRUPTED_EXCEPTION;
+import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_NO_PERMISSION;
+import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_START;
import static com.android.server.voiceinteraction.HotwordDetectionConnection.DEBUG;
import android.annotation.NonNull;
@@ -59,15 +66,17 @@
private static final int MAX_COPY_BUFFER_LENGTH_BYTES = 65_536;
private final AppOpsManager mAppOpsManager;
+ private final int mDetectorType;
private final int mVoiceInteractorUid;
private final String mVoiceInteractorPackageName;
private final String mVoiceInteractorAttributionTag;
private final ExecutorService mExecutorService = Executors.newCachedThreadPool();
- HotwordAudioStreamCopier(@NonNull AppOpsManager appOpsManager,
+ HotwordAudioStreamCopier(@NonNull AppOpsManager appOpsManager, int detectorType,
int voiceInteractorUid, @NonNull String voiceInteractorPackageName,
@NonNull String voiceInteractorAttributionTag) {
mAppOpsManager = appOpsManager;
+ mDetectorType = detectorType;
mVoiceInteractorUid = voiceInteractorUid;
mVoiceInteractorPackageName = voiceInteractorPackageName;
mVoiceInteractorAttributionTag = voiceInteractorAttributionTag;
@@ -89,6 +98,9 @@
throws IOException {
List<HotwordAudioStream> audioStreams = result.getAudioStreams();
if (audioStreams.isEmpty()) {
+ HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
+ HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_EMPTY_AUDIO_STREAM_LIST,
+ mVoiceInteractorUid);
return result;
}
@@ -108,6 +120,9 @@
if (metadata.containsKey(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES)) {
copyBufferLength = metadata.getInt(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES, -1);
if (copyBufferLength < 1 || copyBufferLength > MAX_COPY_BUFFER_LENGTH_BYTES) {
+ HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
+ HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_ILLEGAL_COPY_BUFFER_SIZE,
+ mVoiceInteractorUid);
Slog.w(TAG, "Attempted to set an invalid copy buffer length ("
+ copyBufferLength + ") for: " + audioStream);
copyBufferLength = DEFAULT_COPY_BUFFER_LENGTH_BYTES;
@@ -160,16 +175,25 @@
CopyTaskInfo copyTaskInfo = mCopyTaskInfos.get(i);
String streamTaskId = mResultTaskId + "@" + i;
tasks.add(new SingleAudioStreamCopyTask(streamTaskId, copyTaskInfo.mSource,
- copyTaskInfo.mSink, copyTaskInfo.mCopyBufferLength));
+ copyTaskInfo.mSink, copyTaskInfo.mCopyBufferLength, mDetectorType,
+ mVoiceInteractorUid));
}
if (mAppOpsManager.startOpNoThrow(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD,
mVoiceInteractorUid, mVoiceInteractorPackageName,
mVoiceInteractorAttributionTag, OP_MESSAGE) == MODE_ALLOWED) {
try {
+ HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
+ HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_START,
+ mVoiceInteractorUid);
// TODO(b/244599891): Set timeout, close after inactivity
mExecutorService.invokeAll(tasks);
+ HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
+ HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_END, mVoiceInteractorUid);
} catch (InterruptedException e) {
+ HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
+ HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_INTERRUPTED_EXCEPTION,
+ mVoiceInteractorUid);
Slog.e(TAG, mResultTaskId + ": Task was interrupted", e);
bestEffortPropagateError(e.getMessage());
} finally {
@@ -178,6 +202,9 @@
mVoiceInteractorAttributionTag);
}
} else {
+ HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
+ HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_NO_PERMISSION,
+ mVoiceInteractorUid);
bestEffortPropagateError(
"Failed to obtain RECORD_AUDIO_HOTWORD permission for voice interactor with"
+ " uid=" + mVoiceInteractorUid
@@ -192,6 +219,9 @@
copyTaskInfo.mSource.closeWithError(errorMessage);
copyTaskInfo.mSink.closeWithError(errorMessage);
}
+ HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
+ HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_CLOSE_ERROR_FROM_SYSTEM,
+ mVoiceInteractorUid);
} catch (IOException e) {
Slog.e(TAG, mResultTaskId + ": Failed to propagate error", e);
}
@@ -204,12 +234,17 @@
private final ParcelFileDescriptor mAudioSink;
private final int mCopyBufferLength;
+ private final int mDetectorType;
+ private final int mUid;
+
SingleAudioStreamCopyTask(String streamTaskId, ParcelFileDescriptor audioSource,
- ParcelFileDescriptor audioSink, int copyBufferLength) {
+ ParcelFileDescriptor audioSink, int copyBufferLength, int detectorType, int uid) {
mStreamTaskId = streamTaskId;
mAudioSource = audioSource;
mAudioSink = audioSink;
mCopyBufferLength = copyBufferLength;
+ mDetectorType = detectorType;
+ mUid = uid;
}
@Override
@@ -253,6 +288,8 @@
mAudioSource.closeWithError(e.getMessage());
mAudioSink.closeWithError(e.getMessage());
Slog.e(TAG, mStreamTaskId + ": Failed to copy audio stream", e);
+ HotwordMetricsLogger.writeDetectorEvent(mDetectorType,
+ HOTWORD_DETECTOR_EVENTS__EVENT__AUDIO_EGRESS_CLOSE_ERROR_FROM_SYSTEM, mUid);
} finally {
if (fis != null) {
fis.close();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 3bcba6c..2ac25b6 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -245,7 +245,7 @@
mVoiceInteractionServiceUid = voiceInteractionServiceUid;
mVoiceInteractorIdentity = voiceInteractorIdentity;
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
- mHotwordAudioStreamCopier = new HotwordAudioStreamCopier(mAppOpsManager,
+ mHotwordAudioStreamCopier = new HotwordAudioStreamCopier(mAppOpsManager, detectorType,
mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName,
mVoiceInteractorIdentity.attributionTag);
mDetectionComponentName = serviceName;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/TrustedHotwordDetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/TrustedHotwordDetectorSession.java
index eeafe91..02f5889 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/TrustedHotwordDetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/TrustedHotwordDetectorSession.java
@@ -245,7 +245,7 @@
mVoiceInteractionServiceUid = voiceInteractionServiceUid;
mVoiceInteractorIdentity = voiceInteractorIdentity;
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
- mHotwordAudioStreamCopier = new HotwordAudioStreamCopier(mAppOpsManager,
+ mHotwordAudioStreamCopier = new HotwordAudioStreamCopier(mAppOpsManager, detectorType,
mVoiceInteractorIdentity.uid, mVoiceInteractorIdentity.packageName,
mVoiceInteractorIdentity.attributionTag);
mDetectionComponentName = serviceName;
diff --git a/startop/view_compiler/TEST_MAPPING b/startop/view_compiler/TEST_MAPPING
deleted file mode 100644
index 791e471..0000000
--- a/startop/view_compiler/TEST_MAPPING
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "presubmit": [
- {
- "name": "dex-builder-test"
- },
- {
- "name": "CtsViewTestCases",
- "options": [
- {
- "include-filter": "android.view.cts.PrecompiledLayoutTest"
- }
- ]
- }
- ]
-}
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index 5e11163..f346b92 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -147,7 +147,7 @@
if (mApnSetting != null) {
return mApnSetting.getProtocol();
}
- return ApnSetting.PROTOCOL_IP;
+ return ApnSetting.PROTOCOL_IPV4V6;
}
/**
diff --git a/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl
index 8519173..ea4480d 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl
@@ -65,6 +65,7 @@
oneway void sendSms(in int token, int messageRef, String format, String smsc, boolean retry,
in byte[] pdu);
oneway void acknowledgeSms(int token, int messageRef, int result);
+ oneway void acknowledgeSmsWithPdu(int token, int messageRef, int result, in byte[] pdu);
oneway void acknowledgeSmsReport(int token, int messageRef, int result);
String getSmsFormat();
oneway void onSmsReady();
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 8147759..d776928 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -275,6 +275,12 @@
}
@Override
+ public void acknowledgeSmsWithPdu(int token, int messageRef, int result, byte[] pdu) {
+ executeMethodAsyncNoException(() -> MmTelFeature.this
+ .acknowledgeSms(token, messageRef, result, pdu), "acknowledgeSms");
+ }
+
+ @Override
public void acknowledgeSmsReport(int token, int messageRef, int result) {
executeMethodAsyncNoException(() -> MmTelFeature.this
.acknowledgeSmsReport(token, messageRef, result), "acknowledgeSmsReport");
@@ -1087,6 +1093,11 @@
getSmsImplementation().acknowledgeSms(token, messageRef, result);
}
+ private void acknowledgeSms(int token, int messageRef,
+ @ImsSmsImplBase.DeliverStatusResult int result, byte[] pdu) {
+ getSmsImplementation().acknowledgeSms(token, messageRef, result, pdu);
+ }
+
private void acknowledgeSmsReport(int token, int messageRef,
@ImsSmsImplBase.StatusReportResult int result) {
getSmsImplementation().acknowledgeSmsReport(token, messageRef, result);
diff --git a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
index fb997d1..66833d1 100644
--- a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.RemoteException;
import android.telephony.SmsManager;
@@ -174,6 +175,9 @@
* {@link #onSmsReceived(int, String, byte[])} has been called to deliver the result to the IMS
* provider.
*
+ * If the framework needs to provide the PDU used to acknowledge the SMS,
+ * {@link #acknowledgeSms(int, int, int, byte[])} will be called.
+ *
* @param token token provided in {@link #onSmsReceived(int, String, byte[])}
* @param messageRef the message reference, which may be 1 byte if it is in
* {@link SmsMessage#FORMAT_3GPP} format (see TS.123.040) or 2 bytes if it is in
@@ -186,6 +190,27 @@
}
/**
+ * This method will be called by the platform after
+ * {@link #onSmsReceived(int, String, byte[])} has been called to acknowledge an incoming SMS.
+ *
+ * This method is only called in cases where the framework needs to provide the PDU such as the
+ * case where we provide the Short Message Transfer Layer PDU (see 3GPP TS 23.040). Otherwise,
+ * {@link #acknowledgeSms(int, int, int)} will be used.
+ *
+ * @param token token provided in {@link #onSmsReceived(int, String, byte[])}
+ * @param messageRef the message reference, which may be 1 byte if it is in
+ * {@link SmsMessage#FORMAT_3GPP} format (see TS.123.040) or 2 bytes if it is in
+ * {@link SmsMessage#FORMAT_3GPP2} format (see 3GPP2 C.S0015-B).
+ * @param result result of delivering the message.
+ * @param pdu PDU representing the contents of the message.
+ */
+ public void acknowledgeSms(int token, @IntRange(from = 0, to = 65535) int messageRef,
+ @DeliverStatusResult int result, @NonNull byte[] pdu) {
+ Log.e(LOG_TAG, "acknowledgeSms() not implemented. acknowledgeSms(int, int, int) called.");
+ acknowledgeSms(token, messageRef, result);
+ }
+
+ /**
* This method will be triggered by the platform after
* {@link #onSmsStatusReportReceived(int, int, String, byte[])} or
* {@link #onSmsStatusReportReceived(int, String, byte[])} has been called to provide the
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 939c7de..7383d6a 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -1146,5 +1146,13 @@
</intent-filter>
</activity>
+ <activity android:name="MeshActivity"
+ android:label="Mesh/SimpleMesh"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="com.android.test.hwui.TEST"/>
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MeshActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MeshActivity.java
new file mode 100644
index 0000000..efe242c
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MeshActivity.java
@@ -0,0 +1,124 @@
+/*
+ * 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 com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.BlendMode;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Mesh;
+import android.graphics.MeshSpecification;
+import android.graphics.MeshSpecification.Attribute;
+import android.graphics.MeshSpecification.Varying;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.view.View;
+
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+public class MeshActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(new MeshView(this));
+ }
+
+ static class MeshView extends View {
+ MeshView(Context c) {
+ super(c);
+ this.setOnTouchListener((v, event) -> {
+ invalidate();
+ return true;
+ });
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ MeshSpecification meshSpec = createMeshSpecification();
+ FloatBuffer vertexBuffer = FloatBuffer.allocate(6);
+ vertexBuffer.put(0, 100.0f);
+ vertexBuffer.put(1, 100.0f);
+ vertexBuffer.put(2, 400.0f);
+ vertexBuffer.put(3, 0.0f);
+ vertexBuffer.put(4, 0.0f);
+ vertexBuffer.put(5, 400.0f);
+ vertexBuffer.rewind();
+ Mesh mesh = Mesh.make(
+ meshSpec, Mesh.Mode.Triangles, vertexBuffer, 3, new Rect(0, 0, 1000, 1000));
+
+ int numTriangles = 100;
+ // number of triangles plus first 2 vertices
+ FloatBuffer iVertexBuffer = FloatBuffer.allocate(numTriangles * 2 + 4);
+ ShortBuffer indexBuffer = ShortBuffer.allocate(300);
+
+ int radius = 200;
+ // origin
+ iVertexBuffer.put(0, 500.0f);
+ iVertexBuffer.put(1, 500.0f);
+
+ // first point
+ iVertexBuffer.put(2, 500.0f + radius);
+ iVertexBuffer.put(3, 500.0f);
+ int nVert = 2;
+ int nInd = 0;
+ for (int i = 1; i <= numTriangles; i++) {
+ double angle = (Math.PI * i) / numTriangles;
+ double x = radius * Math.cos(angle);
+ double y = radius * Math.sin(angle);
+ iVertexBuffer.put((i + 1) * 2, 500 + (float) x);
+ iVertexBuffer.put((i + 1) * 2 + 1, 500 + (float) y);
+
+ indexBuffer.put(nInd++, (short) 0);
+ indexBuffer.put(nInd++, (short) (nVert - 1));
+ indexBuffer.put(nInd++, (short) nVert);
+ nVert++;
+ }
+ iVertexBuffer.rewind();
+ indexBuffer.rewind();
+ Mesh mesh2 = Mesh.makeIndexed(meshSpec, Mesh.Mode.Triangles, iVertexBuffer, 102,
+ indexBuffer, new Rect(0, 0, 1000, 1000));
+
+ Paint paint = new Paint();
+ paint.setColor(Color.RED);
+ canvas.drawMesh(mesh, BlendMode.COLOR, new Paint());
+ canvas.drawMesh(mesh2, BlendMode.COLOR, paint);
+ }
+
+ private MeshSpecification createMeshSpecification() {
+ String vs = "Varyings main(const Attributes attributes) { "
+ + " Varyings varyings;"
+ + " varyings.position = attributes.position;"
+ + " return varyings;"
+ + "}";
+ String fs = "float2 main(const Varyings varyings, out float4 color) {\n"
+ + " color = vec4(1.0, 0.0, 0.0, 1.0);"
+ + " return varyings.position;\n"
+ + "}";
+ Attribute[] attList =
+ new Attribute[] {new Attribute(MeshSpecification.FLOAT2, 0, "position")};
+ Varying[] varyList =
+ new MeshSpecification.Varying[] {};
+ return MeshSpecification.make(attList, 8, varyList, vs, fs);
+ }
+ }
+}
diff --git a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
index 15a6afc..7c5dcf8 100644
--- a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
+++ b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
@@ -50,6 +50,7 @@
"android.app.servertransaction.", // all tests under the package.
"android.view.CutoutSpecificationTest",
"android.view.DisplayCutoutTest",
+ "android.view.DisplayShapeTest",
"android.view.InsetsAnimationControlImplTest",
"android.view.InsetsControllerTest",
"android.view.InsetsFlagsTest",
diff --git a/tools/lint/common/src/main/java/com/google/android/lint/PermissionMethodUtils.kt b/tools/lint/common/src/main/java/com/google/android/lint/PermissionMethodUtils.kt
index 720f835..0157596 100644
--- a/tools/lint/common/src/main/java/com/google/android/lint/PermissionMethodUtils.kt
+++ b/tools/lint/common/src/main/java/com/google/android/lint/PermissionMethodUtils.kt
@@ -17,6 +17,7 @@
package com.google.android.lint
import com.android.tools.lint.detector.api.getUMethod
+import org.jetbrains.uast.UAnnotation
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.UMethod
import org.jetbrains.uast.UParameter
@@ -26,10 +27,11 @@
return hasPermissionMethodAnnotation(method)
}
-fun hasPermissionMethodAnnotation(method: UMethod): Boolean = method.annotations
- .any {
- it.hasQualifiedName(ANNOTATION_PERMISSION_METHOD)
- }
+fun hasPermissionMethodAnnotation(method: UMethod): Boolean =
+ getPermissionMethodAnnotation(method) != null
+
+fun getPermissionMethodAnnotation(method: UMethod?): UAnnotation? = method?.uAnnotations
+ ?.firstOrNull { it.qualifiedName == ANNOTATION_PERMISSION_METHOD }
fun hasPermissionNameAnnotation(parameter: UParameter) = parameter.annotations.any {
it.hasQualifiedName(ANNOTATION_PERMISSION_NAME)
diff --git a/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt b/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
index 413e197..c5cf0fb 100644
--- a/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
+++ b/tools/lint/framework/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
@@ -40,7 +40,7 @@
EnforcePermissionDetector.ISSUE_MISSING_ENFORCE_PERMISSION,
EnforcePermissionDetector.ISSUE_MISMATCHING_ENFORCE_PERMISSION,
EnforcePermissionHelperDetector.ISSUE_ENFORCE_PERMISSION_HELPER,
- SimpleManualPermissionEnforcementDetector.ISSUE_USE_ENFORCE_PERMISSION_ANNOTATION,
+ SimpleManualPermissionEnforcementDetector.ISSUE_SIMPLE_MANUAL_PERMISSION_ENFORCEMENT,
SaferParcelChecker.ISSUE_UNSAFE_API_USAGE,
PackageVisibilityDetector.ISSUE_PACKAGE_NAME_NO_PACKAGE_VISIBILITY_FILTERS,
RegisterReceiverFlagDetector.ISSUE_RECEIVER_EXPORTED_FLAG,
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt
index b377d50..a20266a 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/AndroidGlobalIssueRegistry.kt
@@ -31,7 +31,7 @@
EnforcePermissionDetector.ISSUE_MISSING_ENFORCE_PERMISSION,
EnforcePermissionDetector.ISSUE_MISMATCHING_ENFORCE_PERMISSION,
EnforcePermissionHelperDetector.ISSUE_ENFORCE_PERMISSION_HELPER,
- SimpleManualPermissionEnforcementDetector.ISSUE_USE_ENFORCE_PERMISSION_ANNOTATION,
+ SimpleManualPermissionEnforcementDetector.ISSUE_SIMPLE_MANUAL_PERMISSION_ENFORCEMENT,
)
override val api: Int
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
index f1b6348..ee7dd62 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
@@ -17,10 +17,14 @@
package com.google.android.lint.aidl
import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.LintFix
import com.android.tools.lint.detector.api.Location
+import com.android.tools.lint.detector.api.UastLintUtils.Companion.getAnnotationBooleanValue
import com.android.tools.lint.detector.api.getUMethod
+import com.google.android.lint.getPermissionMethodAnnotation
import com.google.android.lint.hasPermissionNameAnnotation
import com.google.android.lint.isPermissionMethodCall
+import com.intellij.psi.PsiType
import org.jetbrains.kotlin.psi.psiUtil.parameterIndex
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.evaluateString
@@ -36,13 +40,37 @@
*/
data class EnforcePermissionFix(
val locations: List<Location>,
- val permissionNames: List<String>
+ val permissionNames: List<String>,
+ val errorLevel: Boolean,
) {
- val annotation: String
+ fun toLintFix(annotationLocation: Location): LintFix {
+ val removeFixes = this.locations.map {
+ LintFix.create()
+ .replace()
+ .reformat(true)
+ .range(it)
+ .with("")
+ .autoFix()
+ .build()
+ }
+
+ val annotateFix = LintFix.create()
+ .annotate(this.annotation)
+ .range(annotationLocation)
+ .autoFix()
+ .build()
+
+ return LintFix.create().composite(annotateFix, *removeFixes.toTypedArray())
+ }
+
+ private val annotation: String
get() {
val quotedPermissions = permissionNames.joinToString(", ") { """"$it"""" }
+
val annotationParameter =
- if (permissionNames.size > 1) "allOf={$quotedPermissions}" else quotedPermissions
+ if (permissionNames.size > 1) "allOf={$quotedPermissions}"
+ else quotedPermissions
+
return "@$ANNOTATION_ENFORCE_PERMISSION($annotationParameter)"
}
@@ -54,19 +82,28 @@
fun fromCallExpression(
context: JavaContext,
callExpression: UCallExpression
- ): EnforcePermissionFix? =
- if (isPermissionMethodCall(callExpression)) {
- EnforcePermissionFix(
+ ): EnforcePermissionFix? {
+ val method = callExpression.resolve()?.getUMethod() ?: return null
+ val annotation = getPermissionMethodAnnotation(method) ?: return null
+ val enforces = method.returnType == PsiType.VOID
+ val orSelf = getAnnotationBooleanValue(annotation, "orSelf") ?: false
+ return EnforcePermissionFix(
listOf(getPermissionCheckLocation(context, callExpression)),
- getPermissionCheckValues(callExpression)
- )
- } else null
+ getPermissionCheckValues(callExpression),
+ // If we detect that the PermissionMethod enforces that permission is granted,
+ // AND is of the "orSelf" variety, we are very confident that this is a behavior
+ // preserving migration to @EnforcePermission. Thus, the incident should be ERROR
+ // level.
+ errorLevel = enforces && orSelf
+ )
+ }
fun compose(individuals: List<EnforcePermissionFix>): EnforcePermissionFix =
EnforcePermissionFix(
individuals.flatMap { it.locations },
- individuals.flatMap { it.permissionNames }
+ individuals.flatMap { it.permissionNames },
+ errorLevel = individuals.all(EnforcePermissionFix::errorLevel)
)
/**
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt
index 4c0cbe7..9999a0b 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt
@@ -18,6 +18,7 @@
import com.android.tools.lint.detector.api.Category
import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
import com.android.tools.lint.detector.api.Issue
import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Scope
@@ -28,6 +29,7 @@
import org.jetbrains.uast.UIfExpression
import org.jetbrains.uast.UMethod
import org.jetbrains.uast.UQualifiedReferenceExpression
+import org.jetbrains.uast.skipParenthesizedExprDown
/**
* Looks for methods implementing generated AIDL interface stubs
@@ -44,30 +46,25 @@
interfaceName: String,
body: UBlockExpression
) {
- val fix = accumulateSimplePermissionCheckFixes(body, context) ?: return
+ val enforcePermissionFix = accumulateSimplePermissionCheckFixes(body, context) ?: return
+ val lintFix = enforcePermissionFix.toLintFix(context.getLocation(node))
+ val message =
+ "$interfaceName permission check ${
+ if (enforcePermissionFix.errorLevel) "should" else "can"
+ } be converted to @EnforcePermission annotation"
- val javaRemoveFixes = fix.locations.map {
- fix()
- .replace()
- .reformat(true)
- .range(it)
- .with("")
- .autoFix()
- .build()
+ val incident = Incident(
+ ISSUE_SIMPLE_MANUAL_PERMISSION_ENFORCEMENT,
+ enforcePermissionFix.locations.last(),
+ message,
+ lintFix
+ )
+
+ if (enforcePermissionFix.errorLevel) {
+ incident.overrideSeverity(Severity.ERROR)
}
- val javaAnnotateFix = fix()
- .annotate(fix.annotation)
- .range(context.getLocation(node))
- .autoFix()
- .build()
-
- context.report(
- ISSUE_USE_ENFORCE_PERMISSION_ANNOTATION,
- fix.locations.last(),
- "$interfaceName permission check can be converted to @EnforcePermission annotation",
- fix().composite(*javaRemoveFixes.toTypedArray(), javaAnnotateFix)
- )
+ context.report(incident)
}
/**
@@ -89,7 +86,8 @@
EnforcePermissionFix? {
val singleFixes = mutableListOf<EnforcePermissionFix>()
for (expression in methodBody.expressions) {
- singleFixes.add(getPermissionCheckFix(expression, context) ?: break)
+ singleFixes.add(getPermissionCheckFix(expression.skipParenthesizedExprDown(), context)
+ ?: break)
}
return when (singleFixes.size) {
0 -> null
@@ -133,7 +131,7 @@
""".trimIndent()
@JvmField
- val ISSUE_USE_ENFORCE_PERMISSION_ANNOTATION = Issue.create(
+ val ISSUE_SIMPLE_MANUAL_PERMISSION_ENFORCEMENT = Issue.create(
id = "SimpleManualPermissionEnforcement",
briefDescription = "Manual permission check can be @EnforcePermission annotation",
explanation = EXPLANATION,
diff --git a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt
index 150fc26..bdf9c89 100644
--- a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt
+++ b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt
@@ -18,7 +18,6 @@
import com.android.tools.lint.checks.infrastructure.LintDetectorTest
import com.android.tools.lint.checks.infrastructure.TestLintTask
-import com.android.tools.lint.checks.infrastructure.TestMode
import com.android.tools.lint.detector.api.Detector
import com.android.tools.lint.detector.api.Issue
@@ -27,7 +26,7 @@
override fun getDetector(): Detector = SimpleManualPermissionEnforcementDetector()
override fun getIssues(): List<Issue> = listOf(
SimpleManualPermissionEnforcementDetector
- .ISSUE_USE_ENFORCE_PERMISSION_ANNOTATION
+ .ISSUE_SIMPLE_MANUAL_PERMISSION_ENFORCEMENT
)
override fun lint(): TestLintTask = super.lint().allowMissingSdk()
@@ -36,15 +35,15 @@
lint().files(
java(
"""
- import android.content.Context;
- import android.test.ITest;
- public class Foo extends ITest.Stub {
- private Context mContext;
- @Override
- public void test() throws android.os.RemoteException {
- mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
- }
+ import android.content.Context;
+ import android.test.ITest;
+ public class Foo extends ITest.Stub {
+ private Context mContext;
+ @Override
+ public void test() throws android.os.RemoteException {
+ mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
}
+ }
"""
).indented(),
*stubs
@@ -52,10 +51,10 @@
.run()
.expect(
"""
- src/Foo.java:7: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:7: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 0 errors, 1 warnings
+ 1 errors, 0 warnings
"""
)
.expectFixDiffs(
@@ -69,22 +68,96 @@
)
}
+ fun testClass_orSelfFalse_warning() {
+ lint().files(
+ java(
+ """
+ import android.content.Context;
+ import android.test.ITest;
+ public class Foo extends ITest.Stub {
+ private Context mContext;
+ @Override
+ public void test() throws android.os.RemoteException {
+ mContext.enforceCallingPermission("android.permission.READ_CONTACTS", "foo");
+ }
+ }
+ """
+ ).indented(),
+ *stubs
+ )
+ .run()
+ .expect(
+ """
+ src/Foo.java:7: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ mContext.enforceCallingPermission("android.permission.READ_CONTACTS", "foo");
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ .expectFixDiffs(
+ """
+ Fix for src/Foo.java line 7: Annotate with @EnforcePermission:
+ @@ -5 +5
+ + @android.annotation.EnforcePermission("android.permission.READ_CONTACTS")
+ @@ -7 +8
+ - mContext.enforceCallingPermission("android.permission.READ_CONTACTS", "foo");
+ """
+ )
+ }
+
+ fun testClass_enforcesFalse_warning() {
+ lint().files(
+ java(
+ """
+ import android.content.Context;
+ import android.test.ITest;
+ public class Foo extends ITest.Stub {
+ private Context mContext;
+ @Override
+ public void test() throws android.os.RemoteException {
+ mContext.checkCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
+ }
+ }
+ """
+ ).indented(),
+ *stubs
+ )
+ .run()
+ .expect(
+ """
+ src/Foo.java:7: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ mContext.checkCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ .expectFixDiffs(
+ """
+ Fix for src/Foo.java line 7: Annotate with @EnforcePermission:
+ @@ -5 +5
+ + @android.annotation.EnforcePermission("android.permission.READ_CONTACTS")
+ @@ -7 +8
+ - mContext.checkCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
+ """
+ )
+ }
+
fun testAnonClass() {
lint().files(
java(
"""
- import android.content.Context;
- import android.test.ITest;
- public class Foo {
- private Context mContext;
- private ITest itest = new ITest.Stub() {
- @Override
- public void test() throws android.os.RemoteException {
- mContext.enforceCallingOrSelfPermission(
- "android.permission.READ_CONTACTS", "foo");
- }
- };
- }
+ import android.content.Context;
+ import android.test.ITest;
+ public class Foo {
+ private Context mContext;
+ private ITest itest = new ITest.Stub() {
+ @Override
+ public void test() throws android.os.RemoteException {
+ mContext.enforceCallingOrSelfPermission(
+ "android.permission.READ_CONTACTS", "foo");
+ }
+ };
+ }
"""
).indented(),
*stubs
@@ -92,10 +165,10 @@
.run()
.expect(
"""
- src/Foo.java:8: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:8: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
mContext.enforceCallingOrSelfPermission(
^
- 0 errors, 1 warnings
+ 1 errors, 0 warnings
"""
)
.expectFixDiffs(
@@ -114,16 +187,16 @@
lint().files(
java(
"""
- import android.content.Context;
- import android.test.ITest;
+ import android.content.Context;
+ import android.test.ITest;
- public class Foo extends ITest.Stub {
- private Context mContext;
- @Override
- public void test() throws android.os.RemoteException {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_CONTACTS, "foo");
- }
+ public class Foo extends ITest.Stub {
+ private Context mContext;
+ @Override
+ public void test() throws android.os.RemoteException {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_CONTACTS, "foo");
}
+ }
"""
).indented(),
*stubs,
@@ -132,10 +205,10 @@
.run()
.expect(
"""
- src/Foo.java:8: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:8: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_CONTACTS, "foo");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 0 errors, 1 warnings
+ 1 errors, 0 warnings
"""
)
.expectFixDiffs(
@@ -153,20 +226,20 @@
lint().files(
java(
"""
- import android.content.Context;
- import android.test.ITest;
- public class Foo {
- private Context mContext;
- private ITest itest = new ITest.Stub() {
- @Override
- public void test() throws android.os.RemoteException {
- mContext.enforceCallingOrSelfPermission(
- "android.permission.READ_CONTACTS", "foo");
- mContext.enforceCallingOrSelfPermission(
- "android.permission.WRITE_CONTACTS", "foo");
- }
- };
- }
+ import android.content.Context;
+ import android.test.ITest;
+ public class Foo {
+ private Context mContext;
+ private ITest itest = new ITest.Stub() {
+ @Override
+ public void test() throws android.os.RemoteException {
+ mContext.enforceCallingOrSelfPermission(
+ "android.permission.READ_CONTACTS", "foo");
+ mContext.enforceCallingOrSelfPermission(
+ "android.permission.WRITE_CONTACTS", "foo");
+ }
+ };
+ }
"""
).indented(),
*stubs
@@ -174,10 +247,10 @@
.run()
.expect(
"""
- src/Foo.java:10: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:10: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
mContext.enforceCallingOrSelfPermission(
^
- 0 errors, 1 warnings
+ 1 errors, 0 warnings
"""
)
.expectFixDiffs(
@@ -194,20 +267,110 @@
)
}
+ fun testAllOf_mixedOrSelf_warning() {
+ lint().files(
+ java(
+ """
+ import android.content.Context;
+ import android.test.ITest;
+ public class Foo {
+ private Context mContext;
+ private ITest itest = new ITest.Stub() {
+ @Override
+ public void test() throws android.os.RemoteException {
+ mContext.enforceCallingOrSelfPermission(
+ "android.permission.READ_CONTACTS", "foo");
+ mContext.enforceCallingPermission(
+ "android.permission.WRITE_CONTACTS", "foo");
+ }
+ };
+ }
+ """
+ ).indented(),
+ *stubs
+ )
+ .run()
+ .expect(
+ """
+ src/Foo.java:10: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ mContext.enforceCallingPermission(
+ ^
+ 0 errors, 1 warnings
+ """
+ )
+ .expectFixDiffs(
+ """
+ Fix for src/Foo.java line 10: Annotate with @EnforcePermission:
+ @@ -6 +6
+ + @android.annotation.EnforcePermission(allOf={"android.permission.READ_CONTACTS", "android.permission.WRITE_CONTACTS"})
+ @@ -8 +9
+ - mContext.enforceCallingOrSelfPermission(
+ - "android.permission.READ_CONTACTS", "foo");
+ - mContext.enforceCallingPermission(
+ - "android.permission.WRITE_CONTACTS", "foo");
+ """
+ )
+ }
+
+ fun testAllOf_mixedEnforces_warning() {
+ lint().files(
+ java(
+ """
+ import android.content.Context;
+ import android.test.ITest;
+ public class Foo {
+ private Context mContext;
+ private ITest itest = new ITest.Stub() {
+ @Override
+ public void test() throws android.os.RemoteException {
+ mContext.enforceCallingOrSelfPermission(
+ "android.permission.READ_CONTACTS", "foo");
+ mContext.checkCallingOrSelfPermission(
+ "android.permission.WRITE_CONTACTS", "foo");
+ }
+ };
+ }
+ """
+ ).indented(),
+ *stubs
+ )
+ .run()
+ .expect(
+ """
+ src/Foo.java:10: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ mContext.checkCallingOrSelfPermission(
+ ^
+ 0 errors, 1 warnings
+ """
+ )
+ .expectFixDiffs(
+ """
+ Fix for src/Foo.java line 10: Annotate with @EnforcePermission:
+ @@ -6 +6
+ + @android.annotation.EnforcePermission(allOf={"android.permission.READ_CONTACTS", "android.permission.WRITE_CONTACTS"})
+ @@ -8 +9
+ - mContext.enforceCallingOrSelfPermission(
+ - "android.permission.READ_CONTACTS", "foo");
+ - mContext.checkCallingOrSelfPermission(
+ - "android.permission.WRITE_CONTACTS", "foo");
+ """
+ )
+ }
+
fun testPrecedingExpressions() {
lint().files(
java(
"""
- import android.os.Binder;
- import android.test.ITest;
- public class Foo extends ITest.Stub {
- private mContext Context;
- @Override
- public void test() throws android.os.RemoteException {
- long uid = Binder.getCallingUid();
- mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
- }
+ import android.os.Binder;
+ import android.test.ITest;
+ public class Foo extends ITest.Stub {
+ private mContext Context;
+ @Override
+ public void test() throws android.os.RemoteException {
+ long uid = Binder.getCallingUid();
+ mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
}
+ }
"""
).indented(),
*stubs
@@ -217,25 +380,25 @@
}
fun testPermissionHelper() {
- lint().skipTestModes(TestMode.PARENTHESIZED).files(
+ lint().files(
java(
"""
- import android.content.Context;
- import android.test.ITest;
+ import android.content.Context;
+ import android.test.ITest;
- public class Foo extends ITest.Stub {
- private Context mContext;
+ public class Foo extends ITest.Stub {
+ private Context mContext;
- @android.content.pm.PermissionMethod
- private void helper() {
- mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
- }
-
- @Override
- public void test() throws android.os.RemoteException {
- helper();
- }
+ @android.content.pm.PermissionMethod(orSelf = true)
+ private void helper() {
+ mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
}
+
+ @Override
+ public void test() throws android.os.RemoteException {
+ helper();
+ }
+ }
"""
).indented(),
*stubs
@@ -243,10 +406,10 @@
.run()
.expect(
"""
- src/Foo.java:14: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:14: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
helper();
~~~~~~~~~
- 0 errors, 1 warnings
+ 1 errors, 0 warnings
"""
)
.expectFixDiffs(
@@ -260,8 +423,52 @@
)
}
+ fun testPermissionHelper_orSelfNotBubbledUp_warning() {
+ lint().files(
+ java(
+ """
+ import android.content.Context;
+ import android.test.ITest;
+
+ public class Foo extends ITest.Stub {
+ private Context mContext;
+
+ @android.content.pm.PermissionMethod
+ private void helper() {
+ mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
+ }
+
+ @Override
+ public void test() throws android.os.RemoteException {
+ helper();
+ }
+ }
+ """
+ ).indented(),
+ *stubs
+ )
+ .run()
+ .expect(
+ """
+ src/Foo.java:14: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ helper();
+ ~~~~~~~~~
+ 0 errors, 1 warnings
+ """
+ )
+ .expectFixDiffs(
+ """
+ Fix for src/Foo.java line 14: Annotate with @EnforcePermission:
+ @@ -12 +12
+ + @android.annotation.EnforcePermission("android.permission.READ_CONTACTS")
+ @@ -14 +15
+ - helper();
+ """
+ )
+ }
+
fun testPermissionHelperAllOf() {
- lint().skipTestModes(TestMode.PARENTHESIZED).files(
+ lint().files(
java(
"""
import android.content.Context;
@@ -270,7 +477,7 @@
public class Foo extends ITest.Stub {
private Context mContext;
- @android.content.pm.PermissionMethod
+ @android.content.pm.PermissionMethod(orSelf = true)
private void helper() {
mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
mContext.enforceCallingOrSelfPermission("android.permission.WRITE_CONTACTS", "foo");
@@ -289,10 +496,10 @@
.run()
.expect(
"""
- src/Foo.java:16: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:16: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
mContext.enforceCallingOrSelfPermission("FOO", "foo");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 0 errors, 1 warnings
+ 1 errors, 0 warnings
"""
)
.expectFixDiffs(
@@ -309,7 +516,7 @@
fun testPermissionHelperNested() {
- lint().skipTestModes(TestMode.PARENTHESIZED).files(
+ lint().files(
java(
"""
import android.content.Context;
@@ -318,12 +525,12 @@
public class Foo extends ITest.Stub {
private Context mContext;
- @android.content.pm.PermissionMethod
+ @android.content.pm.PermissionMethod(orSelf = true)
private void helperHelper() {
helper("android.permission.WRITE_CONTACTS");
}
- @android.content.pm.PermissionMethod
+ @android.content.pm.PermissionMethod(orSelf = true)
private void helper(@android.content.pm.PermissionName String extraPermission) {
mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
}
@@ -340,10 +547,10 @@
.run()
.expect(
"""
- src/Foo.java:19: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:19: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
helperHelper();
~~~~~~~~~~~~~~~
- 0 errors, 1 warnings
+ 1 errors, 0 warnings
"""
)
.expectFixDiffs(
diff --git a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt
index bd6b195..5ac8a0b 100644
--- a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt
+++ b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt
@@ -17,8 +17,12 @@
"""
package android.content;
public class Context {
- @android.content.pm.PermissionMethod
+ @android.content.pm.PermissionMethod(orSelf = true)
public void enforceCallingOrSelfPermission(@android.content.pm.PermissionName String permission, String message) {}
+ @android.content.pm.PermissionMethod
+ public void enforceCallingPermission(@android.content.pm.PermissionName String permission, String message) {}
+ @android.content.pm.PermissionMethod(orSelf = true)
+ public int checkCallingOrSelfPermission(@android.content.pm.PermissionName String permission, String message) {}
}
"""
).indented()