Merge changes from topic "initialize-from-frame"
* changes:
Update FrameMetricsReporterTests to test that we don't report any frames when fromFrame is not explicitly set
Make sure fields are initialized before access
diff --git a/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt b/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt
index 90dca25..f9ddf9a 100644
--- a/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt
+++ b/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt
@@ -191,7 +191,7 @@
}
class ParallelParser2(cacher: PackageCacher2? = null)
- : ParallelParser<ParsingPackageRead>(cacher) {
+ : ParallelParser<ParsingPackageImpl>(cacher) {
val input = ThreadLocal.withInitial {
// For testing, just disable enforcement to avoid hooking up to compat framework
ParseTypeImpl(ParseInput.Callback { _, _, _ -> false })
@@ -211,6 +211,7 @@
override fun parseImpl(file: File) =
parser.parsePackage(input.get()!!.reset(), file, 0).result
+ as ParsingPackageImpl
}
abstract class PackageCacher<PackageType : Parcelable>(private val cacheDir: File) {
@@ -266,7 +267,7 @@
/**
* Re-implementation of the server side PackageCacher, as it's inaccessible here.
*/
- class PackageCacher2(cacheDir: File) : PackageCacher<ParsingPackageRead>(cacheDir) {
+ class PackageCacher2(cacheDir: File) : PackageCacher<ParsingPackageImpl>(cacheDir) {
override fun fromParcel(parcel: Parcel) = ParsingPackageImpl(parcel)
}
}
diff --git a/apct-tests/perftests/core/src/android/util/ArrayMapPerfTest.java b/apct-tests/perftests/core/src/android/util/ArrayMapPerfTest.java
index b93a6ea..cf15123 100644
--- a/apct-tests/perftests/core/src/android/util/ArrayMapPerfTest.java
+++ b/apct-tests/perftests/core/src/android/util/ArrayMapPerfTest.java
@@ -27,6 +27,7 @@
import org.junit.runner.RunWith;
import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
@RunWith(AndroidJUnit4.class)
@LargeTest
@@ -69,4 +70,34 @@
}
}
}
+
+ @Test
+ public void testReplaceAll_Small() {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ BiFunction<Integer, Integer, Integer> function = (k, v) -> 2 * v;
+ while (state.keepRunning()) {
+ for (int i = 0; i < NUM_ITERATIONS; ++i) {
+ ArrayMap<Integer, Integer> map = new ArrayMap<>();
+ for (int j = 0; j < SET_SIZE_SMALL; j++) {
+ map.put(j, j);
+ }
+ map.replaceAll(function);
+ }
+ }
+ }
+
+ @Test
+ public void testReplaceAll_Large() {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ BiFunction<Integer, Integer, Integer> function = (k, v) -> 2 * v;
+ while (state.keepRunning()) {
+ for (int i = 0; i < NUM_ITERATIONS; ++i) {
+ ArrayMap<Integer, Integer> map = new ArrayMap<>();
+ for (int j = 0; j < SET_SIZE_LARGE; j++) {
+ map.put(j, j);
+ }
+ map.replaceAll(function);
+ }
+ }
+ }
}
diff --git a/apex/media/framework/java/android/media/MediaSession2.java b/apex/media/framework/java/android/media/MediaSession2.java
index e76d61c..cb6e1a0 100644
--- a/apex/media/framework/java/android/media/MediaSession2.java
+++ b/apex/media/framework/java/android/media/MediaSession2.java
@@ -262,7 +262,7 @@
}
/**
- * Returns whehther the playback is active (i.e. playing something)
+ * Returns whether the playback is active (i.e. playing something)
*
* @return {@code true} if the playback active, {@code false} otherwise.
*/
diff --git a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
index 09f65b5..74abf31 100644
--- a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
+++ b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
@@ -54,7 +54,6 @@
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
-import java.util.stream.Collectors;
/**
* A system service that manages {@link android.media.MediaSession2} creations
@@ -281,6 +280,16 @@
session.close();
}
+ void onSessionPlaybackStateChanged(Session2Record session, boolean promotePriority) {
+ FullUserRecord user = session.getFullUser();
+ if (user == null || !user.containsSession(session)) {
+ Log.d(TAG, "Unknown session changed playback state. Ignoring.");
+ return;
+ }
+ user.onPlaybackStateChanged(session, promotePriority);
+ }
+
+
static boolean isMediaSessionKey(int keyCode) {
switch (keyCode) {
case KeyEvent.KEYCODE_MEDIA_PLAY:
@@ -520,26 +529,20 @@
final class FullUserRecord {
private final int mFullUserId;
- private final Object mUserLock = new Object();
- @GuardedBy("mUserLock")
- private final List<Session2Record> mSessionRecords = new ArrayList<>();
+ private final SessionPriorityList mSessionPriorityList = new SessionPriorityList();
FullUserRecord(int fullUserId) {
mFullUserId = fullUserId;
}
public void addSession(Session2Record record) {
- synchronized (mUserLock) {
- mSessionRecords.add(record);
- }
+ mSessionPriorityList.addSession(record);
mHandler.post(() -> dispatchSession2Created(record.mSessionToken));
mHandler.post(() -> dispatchSession2Changed(mFullUserId));
}
private void removeSession(Session2Record record) {
- synchronized (mUserLock) {
- mSessionRecords.remove(record);
- }
+ mSessionPriorityList.removeSession(record);
mHandler.post(() -> dispatchSession2Changed(mFullUserId));
//TODO: Handle if the removed session was the media button session.
}
@@ -549,48 +552,31 @@
}
public List<Session2Token> getAllSession2Tokens() {
- synchronized (mUserLock) {
- return mSessionRecords.stream()
- .map(Session2Record::getSessionToken)
- .collect(Collectors.toList());
- }
+ return mSessionPriorityList.getAllTokens();
}
public List<Session2Token> getSession2Tokens(int userId) {
- synchronized (mUserLock) {
- return mSessionRecords.stream()
- .filter(record -> record.getUserId() == userId)
- .map(Session2Record::getSessionToken)
- .collect(Collectors.toList());
- }
+ return mSessionPriorityList.getTokensByUserId(userId);
}
public void destroyAllSessions() {
- synchronized (mUserLock) {
- for (Session2Record session : mSessionRecords) {
- session.close();
- }
- mSessionRecords.clear();
- }
+ mSessionPriorityList.destroyAllSessions();
mHandler.post(() -> dispatchSession2Changed(mFullUserId));
}
public void destroySessionsForUser(int userId) {
- boolean changed = false;
- synchronized (mUserLock) {
- for (int i = mSessionRecords.size() - 1; i >= 0; i--) {
- Session2Record session = mSessionRecords.get(i);
- if (session.getUserId() == userId) {
- mSessionRecords.remove(i);
- session.close();
- changed = true;
- }
- }
- }
- if (changed) {
+ if (mSessionPriorityList.destroySessionsByUserId(userId)) {
mHandler.post(() -> dispatchSession2Changed(mFullUserId));
}
}
+
+ public boolean containsSession(Session2Record session) {
+ return mSessionPriorityList.contains(session);
+ }
+
+ public void onPlaybackStateChanged(Session2Record session, boolean promotePriority) {
+ mSessionPriorityList.onPlaybackStateChanged(session, promotePriority);
+ }
}
static final class Session2Record {
@@ -606,6 +592,7 @@
@GuardedBy("mSession2RecordLock")
private boolean mIsClosed;
+ //TODO: introduce policy (See MediaSessionPolicyProvider)
Session2Record(MediaCommunicationService service, FullUserRecord fullUser,
Session2Token token, Executor controllerExecutor) {
mServiceRef = new WeakReference<>(service);
@@ -641,6 +628,12 @@
return mSessionToken;
}
+ public boolean checkPlaybackActiveState(boolean expected) {
+ synchronized (mSession2RecordLock) {
+ return mIsConnected && mController.isPlaybackActive() == expected;
+ }
+ }
+
private class Controller2Callback extends MediaController2.ControllerCallback {
@Override
public void onConnected(MediaController2 controller,
@@ -666,6 +659,20 @@
service.onSessionDied(Session2Record.this);
}
}
+
+ @Override
+ public void onPlaybackActiveChanged(
+ @NonNull MediaController2 controller,
+ boolean playbackActive) {
+ if (DEBUG) {
+ Log.d(TAG, "playback active changed, " + mSessionToken + ", active="
+ + playbackActive);
+ }
+ MediaCommunicationService service = mServiceRef.get();
+ if (service != null) {
+ service.onSessionPlaybackStateChanged(Session2Record.this, playbackActive);
+ }
+ }
}
}
}
diff --git a/apex/media/service/java/com/android/server/media/SessionPriorityList.java b/apex/media/service/java/com/android/server/media/SessionPriorityList.java
new file mode 100644
index 0000000..47b14b6
--- /dev/null
+++ b/apex/media/service/java/com/android/server/media/SessionPriorityList.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import android.annotation.Nullable;
+import android.media.Session2Token;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.media.MediaCommunicationService.Session2Record;
+
+import java.util.ArrayList;
+import java.util.List;
+
+//TODO: Define the priority specifically.
+/**
+ * Keeps track of media sessions and their priority for notifications, media
+ * button dispatch, etc.
+ * Higher priority session has more chance to be selected as media button session,
+ * which receives the media button events.
+ */
+class SessionPriorityList {
+ private static final String TAG = "SessionPriorityList";
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private final List<Session2Record> mSessions = new ArrayList<>();
+
+ @Nullable
+ private Session2Record mMediaButtonSession;
+ @Nullable
+ private Session2Record mCachedVolumeSession;
+
+ //TODO: integrate AudioPlayerStateMonitor
+
+ public void addSession(Session2Record record) {
+ synchronized (mLock) {
+ mSessions.add(record);
+ }
+ }
+
+ public void removeSession(Session2Record record) {
+ synchronized (mLock) {
+ mSessions.remove(record);
+ }
+ if (record == mMediaButtonSession) {
+ updateMediaButtonSession(null);
+ }
+ }
+
+ public void destroyAllSessions() {
+ synchronized (mLock) {
+ for (Session2Record session : mSessions) {
+ session.close();
+ }
+ mSessions.clear();
+ }
+ }
+
+ public boolean destroySessionsByUserId(int userId) {
+ boolean changed = false;
+ synchronized (mLock) {
+ for (int i = mSessions.size() - 1; i >= 0; i--) {
+ Session2Record session = mSessions.get(i);
+ if (session.getUserId() == userId) {
+ mSessions.remove(i);
+ session.close();
+ changed = true;
+ }
+ }
+ }
+ return changed;
+ }
+
+ public List<Session2Token> getAllTokens() {
+ List<Session2Token> sessions = new ArrayList<>();
+ synchronized (mLock) {
+ for (Session2Record session : mSessions) {
+ sessions.add(session.getSessionToken());
+ }
+ }
+ return sessions;
+ }
+
+ public List<Session2Token> getTokensByUserId(int userId) {
+ List<Session2Token> sessions = new ArrayList<>();
+ synchronized (mLock) {
+ for (Session2Record session : mSessions) {
+ if (session.getUserId() == userId) {
+ sessions.add(session.getSessionToken());
+ }
+ }
+ }
+ return sessions;
+ }
+
+ /** Gets the media button session which receives the media button events. */
+ @Nullable
+ public Session2Record getMediaButtonSession() {
+ return mMediaButtonSession;
+ }
+
+ /** Gets the media volume session which receives the volume key events. */
+ @Nullable
+ public Session2Record getMediaVolumeSession() {
+ //TODO: if null, calculate it.
+ return mCachedVolumeSession;
+ }
+
+ public boolean contains(Session2Record session) {
+ synchronized (mLock) {
+ return mSessions.contains(session);
+ }
+ }
+
+ public void onPlaybackStateChanged(Session2Record session, boolean promotePriority) {
+ if (promotePriority) {
+ synchronized (mLock) {
+ if (mSessions.remove(session)) {
+ mSessions.add(0, session);
+ } else {
+ Log.w(TAG, "onPlaybackStateChanged: Ignoring unknown session");
+ return;
+ }
+ }
+ } else if (session.checkPlaybackActiveState(false)) {
+ // Just clear the cached volume session when a state goes inactive
+ mCachedVolumeSession = null;
+ }
+
+ // In most cases, playback state isn't needed for finding the media button session,
+ // but we only use it as a hint if an app has multiple local media sessions.
+ // In that case, we pick the media session whose PlaybackState matches
+ // the audio playback configuration.
+ if (mMediaButtonSession != null
+ && mMediaButtonSession.getSessionToken().getUid()
+ == session.getSessionToken().getUid()) {
+ Session2Record newMediaButtonSession =
+ findMediaButtonSession(mMediaButtonSession.getSessionToken().getUid());
+ if (newMediaButtonSession != mMediaButtonSession) {
+ // Check if the policy states that this session should not be updated as a media
+ // button session.
+ updateMediaButtonSession(newMediaButtonSession);
+ }
+ }
+ }
+
+ private void updateMediaButtonSession(@Nullable Session2Record newSession) {
+ mMediaButtonSession = newSession;
+ //TODO: invoke callbacks for media button session changed listeners
+ }
+
+ /**
+ * Finds the media button session with the given {@param uid}.
+ * If the app has multiple media sessions, the media session whose playback state is not null
+ * and matches the audio playback state becomes the media button session. Otherwise the top
+ * priority session becomes the media button session.
+ *
+ * @return The media button session. Returns {@code null} if the app doesn't have a media
+ * session.
+ */
+ @Nullable
+ private Session2Record findMediaButtonSession(int uid) {
+ Session2Record mediaButtonSession = null;
+ synchronized (mLock) {
+ for (Session2Record session : mSessions) {
+ if (uid != session.getSessionToken().getUid()) {
+ continue;
+ }
+ // TODO: check audio player state monitor
+ if (mediaButtonSession == null) {
+ // Pick the top priority session as a default.
+ mediaButtonSession = session;
+ }
+ }
+ }
+ return mediaButtonSession;
+ }
+}
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 8c39b71..59f602c 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -793,6 +793,8 @@
// clear screen
glDisable(GL_DITHER);
glDisable(GL_SCISSOR_TEST);
+ glUseProgram(mImageShader);
+
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(mDisplay, mSurface);
diff --git a/core/api/current.txt b/core/api/current.txt
index 29538ab..028b0bd 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9041,6 +9041,15 @@
field public static final int TELEPHONY = 4194304; // 0x400000
}
+ public final class BluetoothCsipSetCoordinator implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
+ method public void close();
+ method protected void finalize();
+ method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+ method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice);
+ method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
+ field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CSIS_CONNECTION_STATE_CHANGED = "android.bluetooth.action.CSIS_CONNECTION_STATE_CHANGED";
+ }
+
public final class BluetoothDevice implements android.os.Parcelable {
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
@@ -12631,6 +12640,7 @@
method public boolean isPackageSuspended();
method @CheckResult public abstract boolean isPermissionRevokedByPolicy(@NonNull String, @NonNull String);
method public abstract boolean isSafeMode();
+ method public boolean mayPackageQuery(@NonNull String, @NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryActivityProperty(@NonNull String);
method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryApplicationProperty(@NonNull String);
method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(@NonNull android.content.Intent, int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 27d78e5..0c4b631 100755
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1967,6 +1967,21 @@
method public void onOobData(int, @NonNull android.bluetooth.OobData);
}
+ public final class BluetoothCsipSetCoordinator implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
+ method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.List<java.lang.Integer> getAllGroupIds(@Nullable android.os.ParcelUuid);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice);
+ method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.Map getGroupUuidMapByDevice(@Nullable android.bluetooth.BluetoothDevice);
+ method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.UUID groupLock(int, @Nullable java.util.concurrent.Executor, @Nullable android.bluetooth.BluetoothCsipSetCoordinator.ClientLockCallback);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean groupUnlock(@NonNull java.util.UUID);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice, int);
+ field @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static final String ACTION_CSIS_DEVICE_AVAILABLE = "android.bluetooth.action.CSIS_DEVICE_AVAILABLE";
+ field @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static final String ACTION_CSIS_SET_MEMBER_AVAILABLE = "android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE";
+ }
+
+ public static interface BluetoothCsipSetCoordinator.ClientLockCallback {
+ method public void onGroupLockSet(int, int, boolean);
+ }
+
public final class BluetoothDevice implements android.os.Parcelable {
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean canBondWithoutDialog();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean cancelBondProcess();
@@ -2021,7 +2036,10 @@
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean connect(android.bluetooth.BluetoothDevice);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(android.bluetooth.BluetoothDevice);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInbandRingingEnabled();
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean startScoUsingVirtualVoiceCall();
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean stopScoUsingVirtualVoiceCall();
}
public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index b98ee11..183e916 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1180,12 +1180,15 @@
public final class DisplayManager {
method public boolean areUserDisabledHdrTypesAllowed();
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void clearUserPreferredDisplayMode();
method @NonNull public int[] getUserDisabledHdrTypes();
+ method @Nullable public android.view.Display.Mode getUserPreferredDisplayMode();
method public boolean isMinimalPostProcessingRequested(int);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAreUserDisabledHdrTypesAllowed(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE) public void setRefreshRateSwitchingType(int);
method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public void setShouldAlwaysRespectAppRequestedMode(boolean);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setUserDisabledHdrTypes(@NonNull int[]);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setUserPreferredDisplayMode(@NonNull android.view.Display.Mode);
method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public boolean shouldAlwaysRespectAppRequestedMode();
field public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2; // 0x2
field public static final int SWITCHING_TYPE_NONE = 0; // 0x0
@@ -2168,6 +2171,9 @@
field public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
field public static final String SHOW_FIRST_CRASH_DIALOG = "show_first_crash_dialog";
field public static final String USER_DISABLED_HDR_FORMATS = "user_disabled_hdr_formats";
+ field public static final String USER_PREFERRED_REFRESH_RATE = "user_preferred_refresh_rate";
+ field public static final String USER_PREFERRED_RESOLUTION_HEIGHT = "user_preferred_resolution_height";
+ field public static final String USER_PREFERRED_RESOLUTION_WIDTH = "user_preferred_resolution_width";
field public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
}
@@ -2735,6 +2741,7 @@
}
public final class Display {
+ method @NonNull public android.view.Display.Mode getDefaultMode();
method @NonNull public int[] getReportedHdrTypes();
method @NonNull public android.graphics.ColorSpace[] getSupportedWideColorGamut();
method public int getType();
@@ -2748,6 +2755,11 @@
field public static final int TYPE_WIFI = 3; // 0x3
}
+ public static final class Display.Mode implements android.os.Parcelable {
+ ctor public Display.Mode(int, int, float);
+ method public boolean matches(int, int, float);
+ }
+
public class FocusFinder {
method public static void sort(android.view.View[], int, int, android.view.ViewGroup, boolean);
}
@@ -3312,6 +3324,7 @@
method @NonNull public android.window.WindowContainerTransaction scheduleFinishEnterPip(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
method @NonNull public android.window.WindowContainerTransaction setActivityWindowingMode(@NonNull android.window.WindowContainerToken, int);
method @NonNull public android.window.WindowContainerTransaction setAdjacentRoots(@NonNull android.window.WindowContainerToken, @NonNull android.window.WindowContainerToken);
+ method @NonNull public android.window.WindowContainerTransaction setAdjacentTaskFragments(@NonNull android.os.IBinder, @Nullable android.os.IBinder, @Nullable android.window.WindowContainerTransaction.TaskFragmentAdjacentParams);
method @NonNull public android.window.WindowContainerTransaction setAppBounds(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
method @NonNull public android.window.WindowContainerTransaction setBounds(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
method @NonNull public android.window.WindowContainerTransaction setBoundsChangeTransaction(@NonNull android.window.WindowContainerToken, @NonNull android.view.SurfaceControl.Transaction);
@@ -3327,6 +3340,15 @@
field @NonNull public static final android.os.Parcelable.Creator<android.window.WindowContainerTransaction> CREATOR;
}
+ public static class WindowContainerTransaction.TaskFragmentAdjacentParams {
+ ctor public WindowContainerTransaction.TaskFragmentAdjacentParams();
+ ctor public WindowContainerTransaction.TaskFragmentAdjacentParams(@NonNull android.os.Bundle);
+ method public void setShouldDelayPrimaryLastActivityRemoval(boolean);
+ method public void setShouldDelaySecondaryLastActivityRemoval(boolean);
+ method public boolean shouldDelayPrimaryLastActivityRemoval();
+ method public boolean shouldDelaySecondaryLastActivityRemoval();
+ }
+
public abstract class WindowContainerTransactionCallback {
ctor public WindowContainerTransactionCallback();
method public abstract void onTransactionReady(int, @NonNull android.view.SurfaceControl.Transaction);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 57de588..7ddc2c94d 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -3575,4 +3575,19 @@
throw e.rethrowAsRuntimeException();
}
}
+
+ @Override
+ public boolean mayPackageQuery(@NonNull String sourcePackageName,
+ @NonNull String targetPackageName) throws NameNotFoundException {
+ Objects.requireNonNull(sourcePackageName);
+ Objects.requireNonNull(targetPackageName);
+ try {
+ return mPM.mayPackageQuery(sourcePackageName, targetPackageName, getUserId());
+ } catch (ParcelableException e) {
+ e.maybeRethrow(PackageManager.NameNotFoundException.class);
+ throw new RuntimeException(e);
+ } catch (RemoteException re) {
+ throw re.rethrowAsRuntimeException();
+ }
+ }
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index ea7fa2e..8ecfb5a 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1884,6 +1884,14 @@
* clicks. To launch an activity in those cases, provide a {@link PendingIntent} for the
* activity itself.
*
+ * <p>How an Action is displayed, including whether the {@code icon}, {@code text}, or
+ * both are displayed or required, depends on where and how the action is used, and the
+ * {@link Style} applied to the Notification.
+ *
+ * <p>When the {@code title} is a {@link android.text.Spanned}, any colors set by a
+ * {@link ForegroundColorSpan} or {@link TextAppearanceSpan} may be removed or displayed
+ * with an altered in luminance to ensure proper contrast within the Notification.
+ *
* @param icon icon to show for this action
* @param title the title of the action
* @param intent the {@link PendingIntent} to fire when users trigger this action
@@ -6119,21 +6127,22 @@
if (emphasizedMode) {
// change the background bgColor
CharSequence title = action.title;
- ColorStateList[] outResultColor = new ColorStateList[1];
int buttonFillColor = getColors(p).getSecondaryAccentColor();
if (isLegacy()) {
title = ContrastColorUtil.clearColorSpans(title);
} else {
- int notifBackgroundColor = getColors(p).getBackgroundColor();
- title = ensureColorSpanContrast(title, notifBackgroundColor, outResultColor);
+ // Check for a full-length span color to use as the button fill color.
+ Integer fullLengthColor = getFullLengthSpanColor(title);
+ if (fullLengthColor != null) {
+ // Ensure the custom button fill has 1.3:1 contrast w/ notification bg.
+ int notifBackgroundColor = getColors(p).getBackgroundColor();
+ buttonFillColor = ensureButtonFillContrast(
+ fullLengthColor, notifBackgroundColor);
+ }
+ // Remove full-length color spans and ensure text contrast with the button fill.
+ title = ensureColorSpanContrast(title, buttonFillColor);
}
button.setTextViewText(R.id.action0, processTextSpans(title));
- boolean hasColorOverride = outResultColor[0] != null;
- if (hasColorOverride) {
- // There's a span spanning the full text, let's take it and use it as the
- // background color
- buttonFillColor = outResultColor[0].getDefaultColor();
- }
final int textColor = ContrastColorUtil.resolvePrimaryColor(mContext,
buttonFillColor, mInNightMode);
button.setTextColor(R.id.action0, textColor);
@@ -6166,17 +6175,58 @@
}
/**
- * Ensures contrast on color spans against a background color. also returns the color of the
- * text if a span was found that spans over the whole text.
+ * Extract the color from a full-length span from the text.
+ *
+ * @param charSequence the charSequence containing spans
+ * @return the raw color of the text's last full-length span containing a color, or null if
+ * no full-length span sets the text color.
+ * @hide
+ */
+ @VisibleForTesting
+ @Nullable
+ public static Integer getFullLengthSpanColor(CharSequence charSequence) {
+ // NOTE: this method preserves the functionality that for a CharSequence with multiple
+ // full-length spans, the color of the last one is used.
+ Integer result = null;
+ if (charSequence instanceof Spanned) {
+ Spanned ss = (Spanned) charSequence;
+ Object[] spans = ss.getSpans(0, ss.length(), Object.class);
+ // First read through all full-length spans to get the button fill color, which will
+ // be used as the background color for ensuring contrast of non-full-length spans.
+ for (Object span : spans) {
+ int spanStart = ss.getSpanStart(span);
+ int spanEnd = ss.getSpanEnd(span);
+ boolean fullLength = (spanEnd - spanStart) == charSequence.length();
+ if (!fullLength) {
+ continue;
+ }
+ if (span instanceof TextAppearanceSpan) {
+ TextAppearanceSpan originalSpan = (TextAppearanceSpan) span;
+ ColorStateList textColor = originalSpan.getTextColor();
+ if (textColor != null) {
+ result = textColor.getDefaultColor();
+ }
+ } else if (span instanceof ForegroundColorSpan) {
+ ForegroundColorSpan originalSpan = (ForegroundColorSpan) span;
+ result = originalSpan.getForegroundColor();
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Ensures contrast on color spans against a background color.
+ * Note that any full-length color spans will be removed instead of being contrasted.
*
* @param charSequence the charSequence on which the spans are
* @param background the background color to ensure the contrast against
- * @param outResultColor an array in which a color will be returned as the first element if
- * there exists a full length color span.
* @return the contrasted charSequence
+ * @hide
*/
- private static CharSequence ensureColorSpanContrast(CharSequence charSequence,
- int background, ColorStateList[] outResultColor) {
+ @VisibleForTesting
+ public static CharSequence ensureColorSpanContrast(CharSequence charSequence,
+ int background) {
if (charSequence instanceof Spanned) {
Spanned ss = (Spanned) charSequence;
Object[] spans = ss.getSpans(0, ss.length(), Object.class);
@@ -6193,19 +6243,19 @@
TextAppearanceSpan originalSpan = (TextAppearanceSpan) resultSpan;
ColorStateList textColor = originalSpan.getTextColor();
if (textColor != null) {
- int[] colors = textColor.getColors();
- int[] newColors = new int[colors.length];
- for (int i = 0; i < newColors.length; i++) {
- boolean isBgDark = isColorDark(background);
- newColors[i] = ContrastColorUtil.ensureLargeTextContrast(
- colors[i], background, isBgDark);
- }
- textColor = new ColorStateList(textColor.getStates().clone(),
- newColors);
if (fullLength) {
- outResultColor[0] = textColor;
// Let's drop the color from the span
textColor = null;
+ } else {
+ int[] colors = textColor.getColors();
+ int[] newColors = new int[colors.length];
+ for (int i = 0; i < newColors.length; i++) {
+ boolean isBgDark = isColorDark(background);
+ newColors[i] = ContrastColorUtil.ensureLargeTextContrast(
+ colors[i], background, isBgDark);
+ }
+ textColor = new ColorStateList(textColor.getStates().clone(),
+ newColors);
}
resultSpan = new TextAppearanceSpan(
originalSpan.getFamily(),
@@ -6215,15 +6265,14 @@
originalSpan.getLinkTextColor());
}
} else if (resultSpan instanceof ForegroundColorSpan) {
- ForegroundColorSpan originalSpan = (ForegroundColorSpan) resultSpan;
- int foregroundColor = originalSpan.getForegroundColor();
- boolean isBgDark = isColorDark(background);
- foregroundColor = ContrastColorUtil.ensureLargeTextContrast(
- foregroundColor, background, isBgDark);
if (fullLength) {
- outResultColor[0] = ColorStateList.valueOf(foregroundColor);
resultSpan = null;
} else {
+ ForegroundColorSpan originalSpan = (ForegroundColorSpan) resultSpan;
+ int foregroundColor = originalSpan.getForegroundColor();
+ boolean isBgDark = isColorDark(background);
+ foregroundColor = ContrastColorUtil.ensureLargeTextContrast(
+ foregroundColor, background, isBgDark);
resultSpan = new ForegroundColorSpan(foregroundColor);
}
} else {
@@ -6253,6 +6302,21 @@
}
/**
+ * Finds a button fill color with sufficient contrast over bg (1.3:1) that has the same hue
+ * as the original color, but is lightened or darkened depending on whether the background
+ * is dark or light.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public static int ensureButtonFillContrast(int color, int bg) {
+ return isColorDark(bg)
+ ? ContrastColorUtil.findContrastColorAgainstDark(color, bg, true, 1.3)
+ : ContrastColorUtil.findContrastColor(color, bg, true, 1.3);
+ }
+
+
+ /**
* @return Whether we are currently building a notification from a legacy (an app that
* doesn't create material notifications by itself) app.
*/
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index d9a33902..ee50634 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -52,7 +52,7 @@
*/
@SystemService(Context.STATUS_BAR_SERVICE)
public class StatusBarManager {
-
+ // LINT.IfChange
/** @hide */
public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND;
/** @hide */
@@ -150,6 +150,7 @@
})
@Retention(RetentionPolicy.SOURCE)
public @interface Disable2Flags {}
+ // LINT.ThenChange(frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/DisableFlagsLogger.kt)
/**
* Default disable flags for setup
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 84752be..a53ef1b 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -563,7 +563,7 @@
}
if (returnDefault) {
Bitmap defaultWallpaper = mDefaultWallpaper;
- if (defaultWallpaper == null) {
+ if (defaultWallpaper == null || defaultWallpaper.isRecycled()) {
defaultWallpaper = getDefaultWallpaper(context, which);
synchronized (this) {
mDefaultWallpaper = defaultWallpaper;
@@ -574,6 +574,53 @@
return null;
}
+ public Rect peekWallpaperDimensions(Context context, boolean returnDefault, int userId) {
+ if (mService != null) {
+ try {
+ if (!mService.isWallpaperSupported(context.getOpPackageName())) {
+ return new Rect();
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ Rect dimensions = null;
+ synchronized (this) {
+ try {
+ Bundle params = new Bundle();
+ // Let's peek user wallpaper first.
+ ParcelFileDescriptor pfd = mService.getWallpaperWithFeature(
+ context.getOpPackageName(), context.getAttributionTag(), this,
+ FLAG_SYSTEM, params, userId);
+ if (pfd != null) {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor(), null, options);
+ dimensions = new Rect(0, 0, options.outWidth, options.outHeight);
+ }
+ } catch (RemoteException ex) {
+ Log.w(TAG, "peek wallpaper dimensions failed", ex);
+ }
+ }
+ // If user wallpaper is unavailable, may be the default one instead.
+ if ((dimensions == null || dimensions.width() == 0 || dimensions.height() == 0)
+ && returnDefault) {
+ InputStream is = openDefaultWallpaper(context, FLAG_SYSTEM);
+ if (is != null) {
+ try {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeStream(is, null, options);
+ dimensions = new Rect(0, 0, options.outWidth, options.outHeight);
+ } finally {
+ IoUtils.closeQuietly(is);
+ }
+ }
+ }
+ return dimensions;
+ }
+
void forgetLoadedWallpaper() {
synchronized (this) {
mCachedWallpaper = null;
@@ -1054,6 +1101,17 @@
}
/**
+ * Peek the dimensions of system wallpaper of the user without decoding it.
+ *
+ * @return the dimensions of system wallpaper
+ * @hide
+ */
+ public Rect peekBitmapDimensions() {
+ return sGlobals.peekWallpaperDimensions(
+ mContext, true /* returnDefault */, mContext.getUserId());
+ }
+
+ /**
* Get an open, readable file descriptor to the given wallpaper image file.
* The caller is responsible for closing the file descriptor when done ingesting the file.
*
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 063ba11..2e94dd1 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -143,7 +143,7 @@
public ComponentName provider;
/**
- * The default height of the widget when added to a host, in dp. The widget will get
+ * The default height of the widget when added to a host, in px. The widget will get
* at least this width, and will often be given more, depending on the host.
*
* <p>This field corresponds to the <code>android:minWidth</code> attribute in
@@ -152,7 +152,7 @@
public int minWidth;
/**
- * The default height of the widget when added to a host, in dp. The widget will get
+ * The default height of the widget when added to a host, in px. The widget will get
* at least this height, and will often be given more, depending on the host.
*
* <p>This field corresponds to the <code>android:minHeight</code> attribute in
@@ -161,7 +161,7 @@
public int minHeight;
/**
- * Minimum width (in dp) which the widget can be resized to. This field has no effect if it
+ * Minimum width (in px) which the widget can be resized to. This field has no effect if it
* is greater than minWidth or if horizontal resizing isn't enabled (see {@link #resizeMode}).
*
* <p>This field corresponds to the <code>android:minResizeWidth</code> attribute in
@@ -170,7 +170,7 @@
public int minResizeWidth;
/**
- * Minimum height (in dp) which the widget can be resized to. This field has no effect if it
+ * Minimum height (in px) which the widget can be resized to. This field has no effect if it
* is greater than minHeight or if vertical resizing isn't enabled (see {@link #resizeMode}).
*
* <p>This field corresponds to the <code>android:minResizeHeight</code> attribute in
@@ -179,7 +179,7 @@
public int minResizeHeight;
/**
- * Maximum width (in dp) which the widget can be resized to. This field has no effect if it is
+ * Maximum width (in px) which the widget can be resized to. This field has no effect if it is
* smaller than minWidth or if horizontal resizing isn't enabled (see {@link #resizeMode}).
*
* <p>This field corresponds to the <code>android:maxResizeWidth</code> attribute in the
@@ -189,7 +189,7 @@
public int maxResizeWidth;
/**
- * Maximum height (in dp) which the widget can be resized to. This field has no effect if it is
+ * Maximum height (in px) which the widget can be resized to. This field has no effect if it is
* smaller than minHeight or if vertical resizing isn't enabled (see {@link #resizeMode}).
*
* <p>This field corresponds to the <code>android:maxResizeHeight</code> attribute in the
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 2b28c11..77abbe9 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -3068,6 +3068,10 @@
} else if (profile == BluetoothProfile.VOLUME_CONTROL) {
BluetoothVolumeControl vcs = new BluetoothVolumeControl(context, listener, this);
return true;
+ } else if (profile == BluetoothProfile.CSIP_SET_COORDINATOR) {
+ BluetoothCsipSetCoordinator csipSetCoordinator =
+ new BluetoothCsipSetCoordinator(context, listener, this);
+ return true;
} else {
return false;
}
@@ -3165,6 +3169,11 @@
BluetoothVolumeControl vcs = (BluetoothVolumeControl) proxy;
vcs.close();
break;
+ case BluetoothProfile.CSIP_SET_COORDINATOR:
+ BluetoothCsipSetCoordinator csipSetCoordinator =
+ (BluetoothCsipSetCoordinator) proxy;
+ csipSetCoordinator.close();
+ break;
}
}
diff --git a/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java b/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java
new file mode 100644
index 0000000..f0a8df0
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothCsipSetCoordinator.java
@@ -0,0 +1,553 @@
+/*
+ * Copyright 2021 HIMSA II K/S - www.himsa.com.
+ * Represented by EHIMA - www.ehima.com
+ *
+ * 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.bluetooth;
+
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
+import android.content.AttributionSource;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.util.CloseGuard;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.Executor;
+
+/**
+ * This class provides the public APIs to control the Bluetooth CSIP set coordinator.
+ *
+ * <p>BluetoothCsipSetCoordinator is a proxy object for controlling the Bluetooth VC
+ * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothCsipSetCoordinator proxy object.
+ *
+ */
+public final class BluetoothCsipSetCoordinator implements BluetoothProfile, AutoCloseable {
+ private static final String TAG = "BluetoothCsipSetCoordinator";
+ private static final boolean DBG = false;
+ private static final boolean VDBG = false;
+
+ private CloseGuard mCloseGuard;
+
+ /**
+ * @hide
+ */
+ @SystemApi
+ public interface ClientLockCallback {
+ /**
+ * @hide
+ */
+ @SystemApi void onGroupLockSet(int groupId, int opStatus, boolean isLocked);
+ }
+
+ private static class BluetoothCsipSetCoordinatorLockCallbackDelegate
+ extends IBluetoothCsipSetCoordinatorLockCallback.Stub {
+ private final ClientLockCallback mCallback;
+ private final Executor mExecutor;
+
+ BluetoothCsipSetCoordinatorLockCallbackDelegate(
+ Executor executor, ClientLockCallback callback) {
+ mExecutor = executor;
+ mCallback = callback;
+ }
+
+ @Override
+ public void onGroupLockSet(int groupId, int opStatus, boolean isLocked) {
+ mExecutor.execute(() -> mCallback.onGroupLockSet(groupId, opStatus, isLocked));
+ }
+ };
+
+ /**
+ * Intent used to broadcast the change in connection state of the CSIS
+ * Client.
+ *
+ * <p>This intent will have 3 extras:
+ * <ul>
+ * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+ * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+ * </ul>
+ *
+ * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+ * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
+ * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_CSIS_CONNECTION_STATE_CHANGED =
+ "android.bluetooth.action.CSIS_CONNECTION_STATE_CHANGED";
+
+ /**
+ * Intent used to expose broadcast receiving device.
+ *
+ * <p>This intent will have 2 extras:
+ * <ul>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote Broadcast receiver device. </li>
+ * <li> {@link #EXTRA_CSIS_GROUP_ID} - Group identifier. </li>
+ * <li> {@link #EXTRA_CSIS_GROUP_SIZE} - Group size. </li>
+ * <li> {@link #EXTRA_CSIS_GROUP_TYPE_UUID} - Group type UUID. </li>
+ * </ul>
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_CSIS_DEVICE_AVAILABLE =
+ "android.bluetooth.action.CSIS_DEVICE_AVAILABLE";
+
+ /**
+ * Used as an extra field in {@link #ACTION_CSIS_DEVICE_AVAILABLE} intent.
+ * Contains the group id.
+ *
+ * @hide
+ */
+ public static final String EXTRA_CSIS_GROUP_ID = "android.bluetooth.extra.CSIS_GROUP_ID";
+
+ /**
+ * Group size as int extra field in {@link #ACTION_CSIS_DEVICE_AVAILABLE} intent.
+ *
+ * @hide
+ */
+ public static final String EXTRA_CSIS_GROUP_SIZE = "android.bluetooth.extra.CSIS_GROUP_SIZE";
+
+ /**
+ * Group type uuid extra field in {@link #ACTION_CSIS_DEVICE_AVAILABLE} intent.
+ *
+ * @hide
+ */
+ public static final String EXTRA_CSIS_GROUP_TYPE_UUID =
+ "android.bluetooth.extra.CSIS_GROUP_TYPE_UUID";
+
+ /**
+ * Intent used to broadcast information about identified set member
+ * ready to connect.
+ *
+ * <p>This intent will have one extra:
+ * <ul>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+ * be null if no device is active. </li>
+ * <li> {@link #EXTRA_CSIS_GROUP_ID} - Group identifier. </li>
+ * </ul>
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_CSIS_SET_MEMBER_AVAILABLE =
+ "android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE";
+
+ /**
+ * This represents an invalid group ID.
+ *
+ * @hide
+ */
+ public static final int GROUP_ID_INVALID = IBluetoothCsipSetCoordinator.CSIS_GROUP_ID_INVALID;
+
+ /**
+ * Indicating that group was locked with success.
+ *
+ * @hide
+ */
+ public static final int GROUP_LOCK_SUCCESS = 0;
+
+ /**
+ * Indicating that group locked failed due to invalid group ID.
+ *
+ * @hide
+ */
+ public static final int GROUP_LOCK_FAILED_INVALID_GROUP = 1;
+
+ /**
+ * Indicating that group locked failed due to empty group.
+ *
+ * @hide
+ */
+ public static final int GROUP_LOCK_FAILED_GROUP_EMPTY = 2;
+
+ /**
+ * Indicating that group locked failed due to group members being disconnected.
+ *
+ * @hide
+ */
+ public static final int GROUP_LOCK_FAILED_GROUP_NOT_CONNECTED = 3;
+
+ /**
+ * Indicating that group locked failed due to group member being already locked.
+ *
+ * @hide
+ */
+ public static final int GROUP_LOCK_FAILED_LOCKED_BY_OTHER = 4;
+
+ /**
+ * Indicating that group locked failed due to other reason.
+ *
+ * @hide
+ */
+ public static final int GROUP_LOCK_FAILED_OTHER_REASON = 5;
+
+ /**
+ * Indicating that group member in locked state was lost.
+ *
+ * @hide
+ */
+ public static final int LOCKED_GROUP_MEMBER_LOST = 6;
+
+ private final BluetoothAdapter mAdapter;
+ private final AttributionSource mAttributionSource;
+ private final BluetoothProfileConnector<IBluetoothCsipSetCoordinator> mProfileConnector =
+ new BluetoothProfileConnector(this, BluetoothProfile.CSIP_SET_COORDINATOR, TAG,
+ IBluetoothCsipSetCoordinator.class.getName()) {
+ @Override
+ public IBluetoothCsipSetCoordinator getServiceInterface(IBinder service) {
+ return IBluetoothCsipSetCoordinator.Stub.asInterface(
+ Binder.allowBlocking(service));
+ }
+ };
+
+ /**
+ * Create a BluetoothCsipSetCoordinator proxy object for interacting with the local
+ * Bluetooth CSIS service.
+ */
+ /*package*/ BluetoothCsipSetCoordinator(Context context, ServiceListener listener, BluetoothAdapter adapter) {
+ mAdapter = adapter;
+ mAttributionSource = adapter.getAttributionSource();
+ mProfileConnector.connect(context, listener);
+ mCloseGuard = new CloseGuard();
+ mCloseGuard.open("close");
+ }
+
+ /**
+ * @hide
+ */
+ protected void finalize() {
+ if (mCloseGuard != null) {
+ mCloseGuard.warnIfOpen();
+ }
+ close();
+ }
+
+ /**
+ * @hide
+ */
+ public void close() {
+ mProfileConnector.disconnect();
+ }
+
+ private IBluetoothCsipSetCoordinator getService() {
+ return mProfileConnector.getService();
+ }
+
+ /**
+ * Lock the set.
+ * @param groupId group ID to lock,
+ * @param executor callback executor,
+ * @param cb callback to report lock and unlock events - stays valid until the app unlocks
+ * using the returned lock identifier or the lock timeouts on the remote side,
+ * as per CSIS specification,
+ * @return unique lock identifier used for unlocking or null if lock has failed.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public
+ @Nullable UUID groupLock(int groupId, @Nullable @CallbackExecutor Executor executor,
+ @Nullable ClientLockCallback cb) {
+ if (VDBG) {
+ log("groupLockSet()");
+ }
+ final IBluetoothCsipSetCoordinator service = getService();
+ try {
+ if (service != null && isEnabled()) {
+ IBluetoothCsipSetCoordinatorLockCallback delegate = null;
+ if ((executor != null) && (cb != null)) {
+ delegate = new BluetoothCsipSetCoordinatorLockCallbackDelegate(executor, cb);
+ }
+ return service.groupLock(groupId, delegate, mAttributionSource).getUuid();
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return null;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return null;
+ }
+ }
+
+ /**
+ * Unlock the set.
+ * @param lockUuid unique lock identifier
+ * @return true if unlocked, false on error
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public boolean groupUnlock(@NonNull UUID lockUuid) {
+ if (VDBG) {
+ log("groupLockSet()");
+ }
+ if (lockUuid == null) {
+ return false;
+ }
+
+ final IBluetoothCsipSetCoordinator service = getService();
+ try {
+ if (service != null && isEnabled()) {
+ service.groupUnlock(new ParcelUuid(lockUuid), mAttributionSource);
+ return true;
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+
+ /**
+ * Get device's groups.
+ * @param device the active device
+ * @return Map of groups ids and related UUIDs
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public @NonNull Map getGroupUuidMapByDevice(@Nullable BluetoothDevice device) {
+ if (VDBG) {
+ log("getGroupUuidMapByDevice()");
+ }
+ final IBluetoothCsipSetCoordinator service = getService();
+ try {
+ if (service != null && isEnabled()) {
+ return service.getGroupUuidMapByDevice(device, mAttributionSource);
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return new HashMap<>();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new HashMap<>();
+ }
+ }
+
+ /**
+ * Get group id for the given UUID
+ * @param uuid
+ * @return list of group IDs
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public @NonNull List<Integer> getAllGroupIds(@Nullable ParcelUuid uuid) {
+ if (VDBG) {
+ log("getAllGroupIds()");
+ }
+ final IBluetoothCsipSetCoordinator service = getService();
+ try {
+ if (service != null && isEnabled()) {
+ return service.getAllGroupIds(uuid, mAttributionSource);
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return new ArrayList<Integer>();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<Integer>();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public @NonNull List<BluetoothDevice> getConnectedDevices() {
+ if (VDBG) {
+ log("getConnectedDevices()");
+ }
+ final IBluetoothCsipSetCoordinator service = getService();
+ if (service != null && isEnabled()) {
+ try {
+ return service.getConnectedDevices(mAttributionSource);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public
+ @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ @NonNull int[] states) {
+ if (VDBG) {
+ log("getDevicesMatchingStates(states=" + Arrays.toString(states) + ")");
+ }
+ final IBluetoothCsipSetCoordinator service = getService();
+ if (service != null && isEnabled()) {
+ try {
+ return service.getDevicesMatchingConnectionStates(states, mAttributionSource);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public
+ @BluetoothProfile.BtProfileState int getConnectionState(
+ @Nullable BluetoothDevice device) {
+ if (VDBG) {
+ log("getState(" + device + ")");
+ }
+ final IBluetoothCsipSetCoordinator service = getService();
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ try {
+ return service.getConnectionState(device, mAttributionSource);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ /**
+ * Set connection policy of the profile
+ *
+ * <p> The device should already be paired.
+ * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+ * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Paired bluetooth device
+ * @param connectionPolicy is the connection policy to set to for this profile
+ * @return true if connectionPolicy is set, false on error
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public boolean setConnectionPolicy(
+ @Nullable BluetoothDevice device, @ConnectionPolicy int connectionPolicy) {
+ if (DBG) {
+ log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
+ }
+ final IBluetoothCsipSetCoordinator service = getService();
+ try {
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+ && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+ return false;
+ }
+ return service.setConnectionPolicy(device, connectionPolicy, mAttributionSource);
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+
+ /**
+ * Get the connection policy of the profile.
+ *
+ * <p> The connection policy can be any of:
+ * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+ * {@link #CONNECTION_POLICY_UNKNOWN}
+ *
+ * @param device Bluetooth device
+ * @return connection policy of the device
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) {
+ if (VDBG) {
+ log("getConnectionPolicy(" + device + ")");
+ }
+ final IBluetoothCsipSetCoordinator service = getService();
+ try {
+ if (service != null && isEnabled() && isValidDevice(device)) {
+ return service.getConnectionPolicy(device, mAttributionSource);
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+ }
+ }
+
+ private boolean isEnabled() {
+ return mAdapter.getState() == BluetoothAdapter.STATE_ON;
+ }
+
+ private static boolean isValidDevice(@Nullable BluetoothDevice device) {
+ return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index b594ae3..c046324 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -16,17 +16,16 @@
package android.bluetooth;
-import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
-import android.annotation.SuppressLint;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Attributable;
import android.content.AttributionSource;
@@ -1105,13 +1104,13 @@
* - binder is dead or Bluetooth is disabled or other error
* @hide
*/
+ @SystemApi
@RequiresLegacyBluetoothAdminPermission
@RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.MODIFY_PHONE_STATE,
})
- @UnsupportedAppUsage
public boolean startScoUsingVirtualVoiceCall() {
if (DBG) log("startScoUsingVirtualVoiceCall()");
final IBluetoothHeadset service = mService;
@@ -1140,13 +1139,13 @@
* - binder is dead or Bluetooth is disabled or other error
* @hide
*/
+ @SystemApi
@RequiresLegacyBluetoothAdminPermission
@RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.MODIFY_PHONE_STATE,
})
- @UnsupportedAppUsage
public boolean stopScoUsingVirtualVoiceCall() {
if (DBG) log("stopScoUsingVirtualVoiceCall()");
final IBluetoothHeadset service = mService;
@@ -1343,9 +1342,10 @@
* @return true if in-band ringing is enabled, false if in-band ringing is disabled
* @hide
*/
+ @SystemApi
@RequiresLegacyBluetoothPermission
@RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
public boolean isInbandRingingEnabled() {
if (DBG) {
log("isInbandRingingEnabled()");
diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
index a630873..37bd6d1 100644
--- a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
@@ -16,7 +16,6 @@
package android.companion;
-import android.companion.Association;
import android.companion.AssociationRequest;
import android.companion.IFindDeviceCallback;
import com.android.internal.infra.AndroidFuture;
@@ -28,5 +27,5 @@
in AssociationRequest request,
in String callingPackage,
in IFindDeviceCallback findCallback,
- in AndroidFuture<Association> serviceCallback);
+ in AndroidFuture<String> serviceCallback);
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 86030fd..df29249 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -818,4 +818,6 @@
ParceledListSlice queryProperty(String propertyName, int componentType);
void setKeepUninstalledPackages(in List<String> packageList);
+
+ boolean mayPackageQuery(String sourcePackageName, String targetPackageName, int userId);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 31b9c30..6b672ff 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -9330,6 +9330,31 @@
}
/**
+ * Returns {@code true} if the source package is able to query for details about the
+ * target package. Applications that share details about other applications should
+ * use this API to determine if those details should be withheld from callers that
+ * do not otherwise have visibility of them.
+ * <p>
+ * Note: The caller must be able to query for details about the source and target
+ * package. A {@link NameNotFoundException} is thrown if it isn't.
+ *
+ * @param sourcePackageName The source package that would receive details about the
+ * target package.
+ * @param targetPackageName The target package whose details would be shared with the
+ * source package.
+ * @return {@code true} if the source package is able to query for details about the
+ * target package.
+ * @throws NameNotFoundException if either a given package can not be found on the
+ * system, or if the caller is not able to query for details about the source or
+ * target package.
+ */
+ public boolean mayPackageQuery(@NonNull String sourcePackageName,
+ @NonNull String targetPackageName) throws NameNotFoundException {
+ throw new UnsupportedOperationException(
+ "mayPackageQuery not implemented in subclass");
+ }
+
+ /**
* Grants implicit visibility of the package that provides an authority to a querying UID.
*
* @throws SecurityException when called by a package other than the contacts provider
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 29ce397..1b34d9b 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -7971,12 +7971,9 @@
}
ai.enabledSetting = state.enabled;
if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
- ai.category = state.categoryHint;
- }
- if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
}
- ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
+ ai.seInfoUser = SELinuxUtil.getSeinfoUser(state);
final OverlayPaths overlayPaths = state.getAllOverlayPaths();
if (overlayPaths != null) {
ai.resourceDirs = overlayPaths.getResourceDirs().toArray(new String[0]);
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 84317b3..3fb1999 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -48,20 +48,26 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
/**
* Per-user state information about a package.
* @hide
*/
-public class PackageUserState {
+public class PackageUserState implements android.content.pm.pkg.PackageUserState {
private static final boolean DEBUG = false;
private static final String LOG_TAG = "PackageUserState";
@@ -77,7 +83,7 @@
public boolean virtualPreload;
public int enabled;
public String lastDisableAppCaller;
- public int categoryHint = ApplicationInfo.CATEGORY_UNDEFINED;
+ @PackageManager.InstallReason
public int installReason;
public @PackageManager.UninstallReason int uninstallReason;
public String harmfulAppWarning;
@@ -118,7 +124,6 @@
virtualPreload = o.virtualPreload;
enabled = o.enabled;
lastDisableAppCaller = o.lastDisableAppCaller;
- categoryHint = o.categoryHint;
installReason = o.installReason;
uninstallReason = o.uninstallReason;
disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
@@ -134,16 +139,6 @@
splashScreenTheme = o.splashScreenTheme;
}
- @Nullable
- public OverlayPaths getOverlayPaths() {
- return overlayPaths;
- }
-
- @Nullable
- public Map<String, OverlayPaths> getSharedLibraryOverlayPaths() {
- return sharedLibraryOverlayPaths;
- }
-
/**
* Sets the path of overlays currently enabled for this package and user combination.
* @return true if the path contents differ than what they were previously
@@ -443,9 +438,6 @@
&& !lastDisableAppCaller.equals(oldState.lastDisableAppCaller))) {
return false;
}
- if (categoryHint != oldState.categoryHint) {
- return false;
- }
if (installReason != oldState.installReason) {
return false;
}
@@ -506,7 +498,6 @@
hashCode = 31 * hashCode + Boolean.hashCode(virtualPreload);
hashCode = 31 * hashCode + enabled;
hashCode = 31 * hashCode + Objects.hashCode(lastDisableAppCaller);
- hashCode = 31 * hashCode + categoryHint;
hashCode = 31 * hashCode + installReason;
hashCode = 31 * hashCode + uninstallReason;
hashCode = 31 * hashCode + Objects.hashCode(disabledComponents);
@@ -516,6 +507,103 @@
return hashCode;
}
+ @Override
+ public long getCeDataInode() {
+ return ceDataInode;
+ }
+
+ @NonNull
+ @Override
+ public Set<String> getDisabledComponents() {
+ return disabledComponents;
+ }
+
+ @PackageManager.DistractionRestriction
+ @Override
+ public int getDistractionFlags() {
+ return distractionFlags;
+ }
+
+ @NonNull
+ @Override
+ public Set<String> getEnabledComponents() {
+ return enabledComponents;
+ }
+
+ @Override
+ public int getEnabledState() {
+ return enabled;
+ }
+
+ @Nullable
+ @Override
+ public String getHarmfulAppWarning() {
+ return harmfulAppWarning;
+ }
+
+ @Override
+ public int getInstallReason() {
+ return installReason;
+ }
+
+ @Nullable
+ @Override
+ public String getLastDisableAppCaller() {
+ return lastDisableAppCaller;
+ }
+
+ @Nullable
+ @Override
+ public OverlayPaths getOverlayPaths() {
+ return overlayPaths;
+ }
+
+ @Nullable
+ @Override
+ public Map<String, OverlayPaths> getSharedLibraryOverlayPaths() {
+ return sharedLibraryOverlayPaths;
+ }
+
+ @Override
+ public int getUninstallReason() {
+ return uninstallReason;
+ }
+
+ @Override
+ public boolean isHidden() {
+ return hidden;
+ }
+
+ @Override
+ public boolean isInstalled() {
+ return installed;
+ }
+
+ @Override
+ public boolean isInstantApp() {
+ return instantApp;
+ }
+
+ @Override
+ public boolean isNotLaunched() {
+ return notLaunched;
+ }
+
+ @Override
+ public boolean isStopped() {
+ return stopped;
+ }
+
+ @Override
+ public boolean isSuspended() {
+ return suspended;
+ }
+
+ @Override
+ public boolean isVirtualPreload() {
+ return virtualPreload;
+ }
+
/**
* Container to describe suspension parameters.
*/
diff --git a/core/java/android/content/pm/SELinuxUtil.java b/core/java/android/content/pm/SELinuxUtil.java
index 025c0fe..d8d52b7 100644
--- a/core/java/android/content/pm/SELinuxUtil.java
+++ b/core/java/android/content/pm/SELinuxUtil.java
@@ -16,8 +16,6 @@
package android.content.pm;
-import com.android.internal.util.ArrayUtils;
-
/**
* Utility methods that need to be used in application space.
* @hide
@@ -31,11 +29,10 @@
public static final String COMPLETE_STR = ":complete";
/** @hide */
- public static String assignSeinfoUser(PackageUserState userState) {
+ public static String getSeinfoUser(PackageUserState userState) {
if (userState.instantApp) {
return INSTANT_APP_STR + COMPLETE_STR;
}
return COMPLETE_STR;
}
-
}
diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
index dfc1886a..747015d 100644
--- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
+++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
@@ -213,8 +213,8 @@
PackageInfo pi = new PackageInfo();
pi.packageName = pkg.getPackageName();
pi.splitNames = pkg.getSplitNames();
- pi.versionCode = pkg.getVersionCode();
- pi.versionCodeMajor = pkg.getVersionCodeMajor();
+ pi.versionCode = ((ParsingPackageHidden) pkg).getVersionCode();
+ pi.versionCodeMajor = ((ParsingPackageHidden) pkg).getVersionCodeMajor();
pi.baseRevisionCode = pkg.getBaseRevisionCode();
pi.splitRevisionCodes = pkg.getSplitRevisionCodes();
pi.versionName = pkg.getVersionName();
@@ -229,7 +229,7 @@
pi.restrictedAccountType = pkg.getRestrictedAccountType();
pi.requiredAccountType = pkg.getRequiredAccountType();
pi.overlayTarget = pkg.getOverlayTarget();
- pi.targetOverlayableName = pkg.getOverlayTargetName();
+ pi.targetOverlayableName = pkg.getOverlayTargetOverlayableName();
pi.overlayCategory = pkg.getOverlayCategory();
pi.overlayPriority = pkg.getOverlayPriority();
pi.mOverlayIsStatic = pkg.isOverlayIsStatic();
@@ -246,10 +246,10 @@
pi.configPreferences = new ConfigurationInfo[size];
pkg.getConfigPreferences().toArray(pi.configPreferences);
}
- size = pkg.getReqFeatures().size();
+ size = pkg.getRequestedFeatures().size();
if (size > 0) {
pi.reqFeatures = new FeatureInfo[size];
- pkg.getReqFeatures().toArray(pi.reqFeatures);
+ pkg.getRequestedFeatures().toArray(pi.reqFeatures);
}
size = pkg.getFeatureGroups().size();
if (size > 0) {
@@ -389,10 +389,10 @@
*/
@NonNull
public static ApplicationInfo generateApplicationInfoUnchecked(@NonNull ParsingPackageRead pkg,
- @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId,
- boolean assignUserFields) {
+ @PackageManager.ApplicationInfoFlags int flags, @NonNull PackageUserState state,
+ int userId, boolean assignUserFields) {
// Make shallow copy so we can store the metadata/libraries safely
- ApplicationInfo ai = pkg.toAppInfoWithoutState();
+ ApplicationInfo ai = ((ParsingPackageHidden) pkg).toAppInfoWithoutState();
if (assignUserFields) {
assignUserFields(pkg, ai, userId);
@@ -435,12 +435,9 @@
}
ai.enabledSetting = state.enabled;
if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
- ai.category = state.categoryHint;
- }
- if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
}
- ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
+ ai.seInfoUser = SELinuxUtil.getSeinfoUser(state);
final OverlayPaths overlayPaths = state.getAllOverlayPaths();
if (overlayPaths != null) {
ai.resourceDirs = overlayPaths.getResourceDirs().toArray(new String[0]);
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index d6e1ac9..14d69cc 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -300,9 +300,7 @@
ParsingPackage setOverlayTarget(String overlayTarget);
- ParsingPackage setOverlayTargetName(String overlayTargetName);
-
- ParsingPackage setRealPackage(String realPackage);
+ ParsingPackage setOverlayTargetOverlayableName(String overlayTargetOverlayableName);
ParsingPackage setRequiredAccountType(String requiredAccountType);
diff --git a/core/java/android/content/pm/parsing/ParsingPackageHidden.java b/core/java/android/content/pm/parsing/ParsingPackageHidden.java
new file mode 100644
index 0000000..c49d11e
--- /dev/null
+++ b/core/java/android/content/pm/parsing/ParsingPackageHidden.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.parsing;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+
+/**
+ * Methods that normal consumers should not have access to. This usually means the field is stateful
+ * or deprecated and should be access through a utility class or a system manager class.
+ * <p>
+ * This is a separate interface, not implemented by the base {@link ParsingPackageRead} because Java
+ * doesn't support non-public interface methods. The class must be cast to this interface.
+ *
+ * @hide
+ */
+interface ParsingPackageHidden {
+
+ /**
+ * @see PackageInfo#versionCode
+ * @see ApplicationInfo#versionCode
+ */
+ int getVersionCode();
+
+ /**
+ * @see PackageInfo#versionCodeMajor
+ */
+ int getVersionCodeMajor();
+
+ // TODO(b/135203078): Hide and enforce going through PackageInfoUtils
+ ApplicationInfo toAppInfoWithoutState();
+}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index f0d95d9..5a5f6db 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -89,9 +89,7 @@
*
* @hide
*/
-public class ParsingPackageImpl implements ParsingPackage, Parcelable {
-
- private static final String TAG = "PackageImpl";
+public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, Parcelable {
public static ForBoolean sForBoolean = Parcelling.Cache.getOrCreate(ForBoolean.class);
public static ForInternedString sForInternedString = Parcelling.Cache.getOrCreate(
@@ -147,10 +145,6 @@
@DataClass.ParcelWith(ForInternedString.class)
protected String packageName;
- @Nullable
- @DataClass.ParcelWith(ForInternedString.class)
- private String realPackage;
-
@NonNull
protected String mBaseApkPath;
@@ -166,7 +160,7 @@
private String overlayTarget;
@Nullable
@DataClass.ParcelWith(ForInternedString.class)
- private String overlayTargetName;
+ private String overlayTargetOverlayableName;
@Nullable
@DataClass.ParcelWith(ForInternedString.class)
private String overlayCategory;
@@ -1019,7 +1013,6 @@
return appInfo;
}
- @Override
public ApplicationInfo toAppInfoWithoutStateWithoutFlags() {
ApplicationInfo appInfo = new ApplicationInfo();
@@ -1126,12 +1119,11 @@
dest.writeInt(this.compileSdkVersion);
dest.writeString(this.compileSdkVersionCodeName);
sForInternedString.parcel(this.packageName, dest, flags);
- dest.writeString(this.realPackage);
dest.writeString(this.mBaseApkPath);
dest.writeString(this.restrictedAccountType);
dest.writeString(this.requiredAccountType);
sForInternedString.parcel(this.overlayTarget, dest, flags);
- dest.writeString(this.overlayTargetName);
+ dest.writeString(this.overlayTargetOverlayableName);
dest.writeString(this.overlayCategory);
dest.writeInt(this.overlayPriority);
sForInternedStringValueMap.parcel(this.overlayables, dest, flags);
@@ -1250,12 +1242,11 @@
this.compileSdkVersion = in.readInt();
this.compileSdkVersionCodeName = in.readString();
this.packageName = sForInternedString.unparcel(in);
- this.realPackage = in.readString();
this.mBaseApkPath = in.readString();
this.restrictedAccountType = in.readString();
this.requiredAccountType = in.readString();
this.overlayTarget = sForInternedString.unparcel(in);
- this.overlayTargetName = in.readString();
+ this.overlayTargetOverlayableName = in.readString();
this.overlayCategory = in.readString();
this.overlayPriority = in.readInt();
this.overlayables = sForInternedStringValueMap.unparcel(in);
@@ -1384,6 +1375,11 @@
}
@Override
+ public long getLongVersionCode() {
+ return mLongVersionCode;
+ }
+
+ @Override
public int getBaseRevisionCode() {
return baseRevisionCode;
}
@@ -1411,12 +1407,6 @@
return packageName;
}
- @Nullable
- @Override
- public String getRealPackage() {
- return realPackage;
- }
-
@NonNull
@Override
public String getBaseApkPath() {
@@ -1448,8 +1438,8 @@
@Nullable
@Override
- public String getOverlayTargetName() {
- return overlayTargetName;
+ public String getOverlayTargetOverlayableName() {
+ return overlayTargetOverlayableName;
}
@Nullable
@@ -1552,7 +1542,7 @@
@NonNull
@Override
- public List<FeatureInfo> getReqFeatures() {
+ public List<FeatureInfo> getRequestedFeatures() {
return reqFeatures;
}
@@ -1939,13 +1929,13 @@
}
@Override
- public int getTargetSandboxVersion() {
- return targetSandboxVersion;
+ public int getTargetSdkVersion() {
+ return targetSdkVersion;
}
@Override
- public int getTargetSdkVersion() {
- return targetSdkVersion;
+ public int getTargetSandboxVersion() {
+ return targetSandboxVersion;
}
@Nullable
@@ -2698,20 +2688,15 @@
}
@Override
- public ParsingPackageImpl setRealPackage(@Nullable String realPackage) {
- this.realPackage = realPackage;
- return this;
- }
-
- @Override
public ParsingPackageImpl setRestrictedAccountType(@Nullable String restrictedAccountType) {
this.restrictedAccountType = restrictedAccountType;
return this;
}
@Override
- public ParsingPackageImpl setOverlayTargetName(@Nullable String overlayTargetName) {
- this.overlayTargetName = overlayTargetName;
+ public ParsingPackageImpl setOverlayTargetOverlayableName(
+ @Nullable String overlayTargetOverlayableName) {
+ this.overlayTargetOverlayableName = overlayTargetOverlayableName;
return this;
}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageInternal.java b/core/java/android/content/pm/parsing/ParsingPackageInternal.java
new file mode 100644
index 0000000..ca16fa2
--- /dev/null
+++ b/core/java/android/content/pm/parsing/ParsingPackageInternal.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.parsing;
+
+import android.annotation.Nullable;
+import android.content.pm.PackageInfo;
+
+import com.android.internal.R;
+
+/**
+ * Methods which would've been a part of {@link PkgWithoutStatePackageInfo} or {@link
+ * PkgWithoutStateAppInfo}, but are removed/deprecated.
+ * <p>
+ * This is different from {@link ParsingPackageHidden}. The methods in that interface cannot be
+ * accessed by anyone except the parsing utilities, whereas the methods in this interface are valid
+ * and can be accessed by any internal caller that needs it.
+ *
+ * @hide
+ */
+interface ParsingPackageInternal {
+
+ /**
+ * @see PackageInfo#overlayCategory
+ * @see R.styleable#AndroidManifestResourceOverlay_category
+ */
+ @Nullable
+ String getOverlayCategory();
+
+ /**
+ * @see PackageInfo#overlayPriority
+ * @see R.styleable#AndroidManifestResourceOverlay_priority
+ */
+ int getOverlayPriority();
+
+ /**
+ * @see PackageInfo#overlayTarget
+ * @see R.styleable#AndroidManifestResourceOverlay_targetPackage
+ */
+ @Nullable
+ String getOverlayTarget();
+
+ /**
+ * @see PackageInfo#targetOverlayableName
+ * @see R.styleable#AndroidManifestResourceOverlay_targetName
+ */
+ @Nullable
+ String getOverlayTargetOverlayableName();
+
+ /**
+ * @see PackageInfo#mOverlayIsStatic
+ */
+ boolean isOverlayIsStatic();
+}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageRead.java b/core/java/android/content/pm/parsing/ParsingPackageRead.java
index d5bd3a9..4a249bb 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageRead.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageRead.java
@@ -19,30 +19,18 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Intent;
-import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
-import android.content.pm.ConfigurationInfo;
-import android.content.pm.FeatureGroupInfo;
-import android.content.pm.FeatureInfo;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.Property;
-import android.content.pm.ServiceInfo;
+import android.content.pm.PackageParser;
import android.content.pm.SigningDetails;
-import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedAttribution;
-import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedIntentInfo;
-import android.content.pm.parsing.component.ParsedPermission;
import android.content.pm.parsing.component.ParsedPermissionGroup;
import android.content.pm.parsing.component.ParsedProcess;
-import android.content.pm.parsing.component.ParsedProvider;
-import android.content.pm.parsing.component.ParsedService;
import android.content.pm.parsing.component.ParsedUsesPermission;
import android.os.Bundle;
-import android.os.Parcelable;
import android.util.ArraySet;
import android.util.Pair;
-import android.util.SparseArray;
import android.util.SparseIntArray;
import java.security.PublicKey;
@@ -55,58 +43,35 @@
*
* @hide
*/
-@SuppressWarnings("UnusedReturnValue")
-public interface ParsingPackageRead extends Parcelable {
+public interface ParsingPackageRead extends PkgWithoutStateAppInfo, PkgWithoutStatePackageInfo,
+ ParsingPackageInternal {
/**
- * @see ActivityInfo
- * @see PackageInfo#activities
- */
- @NonNull
- List<ParsedActivity> getActivities();
-
- /**
- * The names of packages to adopt ownership of permissions from, parsed under
- * {@link ParsingPackageUtils#TAG_ADOPT_PERMISSIONS}.
+ * The names of packages to adopt ownership of permissions from, parsed under {@link
+ * PackageParser#TAG_ADOPT_PERMISSIONS}.
+ *
* @see R.styleable#AndroidManifestOriginalPackage_name
*/
@NonNull
List<String> getAdoptPermissions();
- /**
- * @see PackageInfo#configPreferences
- * @see R.styleable#AndroidManifestUsesConfiguration
- */
- @NonNull
- List<ConfigurationInfo> getConfigPreferences();
-
@NonNull
List<ParsedAttribution> getAttributions();
/**
- * @see PackageInfo#featureGroups
- * @see R.styleable#AndroidManifestUsesFeature
- */
- @NonNull
- List<FeatureGroupInfo> getFeatureGroups();
-
- /**
* Permissions requested but not in the manifest. These may have been split or migrated from
* previous versions/definitions.
*/
@NonNull
List<String> getImplicitPermissions();
- /**
- * @see android.content.pm.InstrumentationInfo
- * @see PackageInfo#instrumentation
- */
@NonNull
- List<ParsedInstrumentation> getInstrumentations();
+ List<ParsedUsesPermission> getUsesPermissions();
/**
- * For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in
- * {@link ParsingPackageUtils#TAG_KEY_SETS}.
+ * For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in {@link
+ * PackageParser#TAG_KEY_SETS}.
+ *
* @see R.styleable#AndroidManifestKeySet
* @see R.styleable#AndroidManifestPublicKey
*/
@@ -115,14 +80,31 @@
/**
* Library names this package is declared as, for use by other packages with "uses-library".
+ *
* @see R.styleable#AndroidManifestLibrary
*/
@NonNull
List<String> getLibraryNames();
/**
- * For system use to migrate from an old package name to a new one, moving over data
- * if available.
+ * TODO(b/135203078): Make all the Bundles immutable (and non-null by shared empty reference?)
+ */
+ @Nullable
+ Bundle getMetaData();
+
+ @Nullable
+ Set<String> getMimeGroups();
+
+ /**
+ * @see R.styleable#AndroidManifestExtensionSdk
+ */
+ @Nullable
+ SparseIntArray getMinExtensionVersions();
+
+ /**
+ * For system use to migrate from an old package name to a new one, moving over data if
+ * available.
+ *
* @see R.styleable#AndroidManifestOriginalPackage}
*/
@NonNull
@@ -135,13 +117,6 @@
Map<String, String> getOverlayables();
/**
- * @see android.content.pm.PermissionInfo
- * @see PackageInfo#permissions
- */
- @NonNull
- List<ParsedPermission> getPermissions();
-
- /**
* @see android.content.pm.PermissionGroupInfo
*/
@NonNull
@@ -149,131 +124,30 @@
/**
* Used to determine the default preferred handler of an {@link Intent}.
- *
- * Map of component className to intent info inside that component.
- * TODO(b/135203078): Is this actually used/working?
+ * <p>
+ * Map of component className to intent info inside that component. TODO(b/135203078): Is this
+ * actually used/working?
*/
@NonNull
List<Pair<String, ParsedIntentInfo>> getPreferredActivityFilters();
/**
- * System protected broadcasts.
- * @see R.styleable#AndroidManifestProtectedBroadcast
- */
- @NonNull
- List<String> getProtectedBroadcasts();
-
- /**
- * @see android.content.pm.ProviderInfo
- * @see PackageInfo#providers
- */
- @NonNull
- List<ParsedProvider> getProviders();
-
- /**
* @see android.content.pm.ProcessInfo
*/
@NonNull
Map<String, ParsedProcess> getProcesses();
/**
- * Since they share several attributes, receivers are parsed as {@link ParsedActivity}, even
- * though they represent different functionality.
- * TODO(b/135203078): Reconsider this and maybe make ParsedReceiver so it's not so confusing
- * @see ActivityInfo
- * @see PackageInfo#receivers
+ * System protected broadcasts.
+ *
+ * @see R.styleable#AndroidManifestProtectedBroadcast
*/
@NonNull
- List<ParsedActivity> getReceivers();
-
- /**
- * @see PackageInfo#reqFeatures
- * @see R.styleable#AndroidManifestUsesFeature
- */
- @NonNull
- List<FeatureInfo> getReqFeatures();
-
- /**
- * @deprecated consider migrating to {@link #getUsesPermissions} which has
- * more parsed details, such as flags
- */
- @NonNull
- @Deprecated
- List<String> getRequestedPermissions();
-
- /**
- * All the permissions declared. This is an effective set, and may include permissions
- * transformed from split/migrated permissions from previous versions, so may not be exactly
- * what the package declares in its manifest.
- * @see PackageInfo#requestedPermissions
- * @see R.styleable#AndroidManifestUsesPermission
- */
- @NonNull
- List<ParsedUsesPermission> getUsesPermissions();
-
- /**
- * Returns the properties set on the application
- */
- @NonNull
- Map<String, Property> getProperties();
-
- /**
- * Whether or not the app requested explicitly resizeable Activities.
- * A null value means nothing was explicitly requested.
- */
- @Nullable
- Boolean getResizeableActivity();
-
- /**
- * @see ServiceInfo
- * @see PackageInfo#services
- */
- @NonNull
- List<ParsedService> getServices();
-
- /** @see R.styleable#AndroidManifestUsesLibrary */
- @NonNull
- List<String> getUsesLibraries();
-
- /**
- * Like {@link #getUsesLibraries()}, but marked optional by setting
- * {@link R.styleable#AndroidManifestUsesLibrary_required} to false . Application is expected
- * to handle absence manually.
- * @see R.styleable#AndroidManifestUsesLibrary
- */
- @NonNull
- List<String> getUsesOptionalLibraries();
-
- /** @see R.styleabele#AndroidManifestUsesNativeLibrary */
- @NonNull
- List<String> getUsesNativeLibraries();
-
- /**
- * Like {@link #getUsesNativeLibraries()}, but marked optional by setting
- * {@link R.styleable#AndroidManifestUsesNativeLibrary_required} to false . Application is
- * expected to handle absence manually.
- * @see R.styleable#AndroidManifestUsesNativeLibrary
- */
- @NonNull
- List<String> getUsesOptionalNativeLibraries();
-
- /**
- * TODO(b/135203078): Move static library stuff to an inner data class
- * @see R.styleable#AndroidManifestUsesStaticLibrary
- */
- @NonNull
- List<String> getUsesStaticLibraries();
-
- /** @see R.styleable#AndroidManifestUsesStaticLibrary_certDigest */
- @Nullable
- String[][] getUsesStaticLibrariesCertDigests();
-
- /** @see R.styleable#AndroidManifestUsesStaticLibrary_version */
- @Nullable
- long[] getUsesStaticLibrariesVersions();
+ List<String> getProtectedBroadcasts();
/**
* Intents that this package may query or require and thus requires visibility into.
+ *
* @see R.styleable#AndroidManifestQueriesIntent
*/
@NonNull
@@ -281,6 +155,7 @@
/**
* Other packages that this package may query or require and thus requires visibility into.
+ *
* @see R.styleable#AndroidManifestQueriesPackage
*/
@NonNull
@@ -288,643 +163,138 @@
/**
* Authorities that this package may query or require and thus requires visibility into.
+ *
* @see R.styleable#AndroidManifestQueriesProvider
*/
@NonNull
Set<String> getQueriesProviders();
/**
- * We store the application meta-data independently to avoid multiple unwanted references
- * TODO(b/135203078): What does this comment mean?
- * TODO(b/135203078): Make all the Bundles immutable (and non-null by shared empty reference?)
- */
- @Nullable
- Bundle getMetaData();
-
- /** @see R.styleable#AndroidManifestApplication_forceQueryable */
- boolean isForceQueryable();
-
- /**
- * @see ApplicationInfo#maxAspectRatio
- * @see R.styleable#AndroidManifestApplication_maxAspectRatio
- */
- float getMaxAspectRatio();
-
- /**
- * @see ApplicationInfo#minAspectRatio
- * @see R.styleable#AndroidManifestApplication_minAspectRatio
- */
- float getMinAspectRatio();
-
- /**
- * @see ApplicationInfo#permission
- * @see R.styleable#AndroidManifestApplication_permission
- */
- @Nullable
- String getPermission();
-
- /**
- * @see ApplicationInfo#processName
- * @see R.styleable#AndroidManifestApplication_process
- */
- @NonNull
- String getProcessName();
-
- /**
- * @see PackageInfo#sharedUserId
- * @see R.styleable#AndroidManifest_sharedUserId
- */
- @Deprecated
- @Nullable
- String getSharedUserId();
-
- /** @see R.styleable#AndroidManifestStaticLibrary_name */
- @Nullable
- String getStaticSharedLibName();
-
- /**
- * @see ApplicationInfo#taskAffinity
- * @see R.styleable#AndroidManifestApplication_taskAffinity
- */
- @Nullable
- String getTaskAffinity();
-
- /**
- * @see ApplicationInfo#targetSdkVersion
- * @see R.styleable#AndroidManifestUsesSdk_targetSdkVersion
- */
- int getTargetSdkVersion();
-
- /**
- * @see ApplicationInfo#uiOptions
- * @see R.styleable#AndroidManifestApplication_uiOptions
- */
- int getUiOptions();
-
- boolean isCrossProfile();
-
- boolean isResizeableActivityViaSdkVersion();
-
- /** @see ApplicationInfo#FLAG_HARDWARE_ACCELERATED */
- boolean isBaseHardwareAccelerated();
-
- /**
- * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
- * {@link android.os.Build.VERSION_CODES#DONUT}.
- * @see R.styleable#AndroidManifestSupportsScreens_resizeable
- * @see ApplicationInfo#FLAG_RESIZEABLE_FOR_SCREENS
- */
- boolean isResizeable();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE */
- boolean isAllowAudioPlaybackCapture();
-
- /** @see ApplicationInfo#FLAG_ALLOW_BACKUP */
- boolean isAllowBackup();
-
- /** @see ApplicationInfo#FLAG_ALLOW_CLEAR_USER_DATA */
- boolean isAllowClearUserData();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE */
- boolean isAllowClearUserDataOnFailedRestore();
-
- /** @see ApplicationInfo#FLAG_ALLOW_TASK_REPARENTING */
- boolean isAllowTaskReparenting();
-
- /**
- * @see ApplicationInfo#PRIVATE_FLAG_IS_RESOURCE_OVERLAY
- * @see ApplicationInfo#isResourceOverlay()
- */
- boolean isOverlay();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_BACKUP_IN_FOREGROUND */
- boolean isBackupInForeground();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_CANT_SAVE_STATE */
- boolean isCantSaveState();
-
- /** @see ApplicationInfo#FLAG_DEBUGGABLE */
- boolean isDebuggable();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE */
- boolean isDefaultToDeviceProtectedStorage();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_DIRECT_BOOT_AWARE */
- boolean isDirectBootAware();
-
- /** @see ApplicationInfo#FLAG_EXTERNAL_STORAGE */
- boolean isExternalStorage();
-
- /** @see ApplicationInfo#FLAG_EXTRACT_NATIVE_LIBS */
- boolean isExtractNativeLibs();
-
- /** @see ApplicationInfo#FLAG_FULL_BACKUP_ONLY */
- boolean isFullBackupOnly();
-
- /** @see ApplicationInfo#FLAG_HAS_CODE */
- boolean isHasCode();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_HAS_FRAGILE_USER_DATA */
- boolean isHasFragileUserData();
-
- /** @see ApplicationInfo#FLAG_IS_GAME */
- @Deprecated
- boolean isGame();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_ISOLATED_SPLIT_LOADING */
- boolean isIsolatedSplitLoading();
-
- /** @see ApplicationInfo#FLAG_KILL_AFTER_RESTORE */
- boolean isKillAfterRestore();
-
- /** @see ApplicationInfo#FLAG_LARGE_HEAP */
- boolean isLargeHeap();
-
- /** @see ApplicationInfo#FLAG_MULTIARCH */
- boolean isMultiArch();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE */
- boolean isPartiallyDirectBootAware();
-
- /** @see ApplicationInfo#FLAG_PERSISTENT */
- boolean isPersistent();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_PROFILEABLE_BY_SHELL */
- boolean isProfileableByShell();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_EXT_PROFILEABLE */
- boolean isProfileable();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE */
- boolean isRequestLegacyExternalStorage();
-
- /** @see ApplicationInfo#FLAG_RESTORE_ANY_VERSION */
- boolean isRestoreAnyVersion();
-
- // ParsingPackageRead setSplitHasCode(int splitIndex, boolean splitHasCode);
-
- /** Flags of any split APKs; ordered by parsed splitName */
- @Nullable
- int[] getSplitFlags();
-
- /** @see ApplicationInfo#splitSourceDirs */
- @Nullable
- String[] getSplitCodePaths();
-
- /** @see ApplicationInfo#splitDependencies */
- @Nullable
- SparseArray<int[]> getSplitDependencies();
-
- /**
- * @see ApplicationInfo#splitNames
- * @see PackageInfo#splitNames
- */
- @Nullable
- String[] getSplitNames();
-
- /** @see PackageInfo#splitRevisionCodes */
- int[] getSplitRevisionCodes();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_STATIC_SHARED_LIBRARY */
- boolean isStaticSharedLibrary();
-
- /** @see ApplicationInfo#FLAG_SUPPORTS_RTL */
- boolean isSupportsRtl();
-
- /** @see ApplicationInfo#FLAG_TEST_ONLY */
- boolean isTestOnly();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_USE_EMBEDDED_DEX */
- boolean isUseEmbeddedDex();
-
- /** @see ApplicationInfo#FLAG_USES_CLEARTEXT_TRAFFIC */
- boolean isUsesCleartextTraffic();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_USES_NON_SDK_API */
- boolean isUsesNonSdkApi();
-
- /**
- * Set if the any of components are visible to instant applications.
- * @see R.styleable#AndroidManifestActivity_visibleToInstantApps
- * @see R.styleable#AndroidManifestProvider_visibleToInstantApps
- * @see R.styleable#AndroidManifestService_visibleToInstantApps
- */
- boolean isVisibleToInstantApps();
-
- /** @see ApplicationInfo#FLAG_VM_SAFE_MODE */
- boolean isVmSafeMode();
-
- /**
- * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
- * {@link android.os.Build.VERSION_CODES#DONUT}.
- * @see R.styleable#AndroidManifestSupportsScreens_anyDensity
- * @see ApplicationInfo#FLAG_SUPPORTS_SCREEN_DENSITIES
- */
- boolean isAnyDensity();
-
- /**
- * @see ApplicationInfo#appComponentFactory
- * @see R.styleable#AndroidManifestApplication_appComponentFactory
- */
- @Nullable
- String getAppComponentFactory();
-
- /**
- * @see ApplicationInfo#backupAgentName
- * @see R.styleable#AndroidManifestApplication_backupAgent
- */
- @Nullable
- String getBackupAgentName();
-
- /**
- * @see ApplicationInfo#banner
- * @see R.styleable#AndroidManifestApplication_banner
- */
- int getBanner();
-
- /**
- * @see ApplicationInfo#category
- * @see R.styleable#AndroidManifestApplication_appCategory
- */
- int getCategory();
-
- /**
- * @see ApplicationInfo#classLoaderName
- * @see R.styleable#AndroidManifestApplication_classLoader
- */
- @Nullable
- String getClassLoaderName();
-
- /**
- * @see ApplicationInfo#className
- * @see R.styleable#AndroidManifestApplication_name
- */
- @Nullable
- String getClassName();
-
- String getPackageName();
-
- /** Path of base APK */
- String getBaseApkPath();
-
- /**
- * Path where this package was found on disk. For monolithic packages
- * this is path to single base APK file; for cluster packages this is
- * path to the cluster directory.
- */
- @NonNull
- String getPath();
-
- /**
- * @see ApplicationInfo#compatibleWidthLimitDp
- * @see R.styleable#AndroidManifestSupportsScreens_compatibleWidthLimitDp
- */
- int getCompatibleWidthLimitDp();
-
- /**
- * @see ApplicationInfo#descriptionRes
- * @see R.styleable#AndroidManifestApplication_description
- */
- int getDescriptionRes();
-
- /**
- * @see ApplicationInfo#enabled
- * @see R.styleable#AndroidManifestApplication_enabled
- */
- boolean isEnabled();
-
- /**
- * @see ApplicationInfo#fullBackupContent
- * @see R.styleable#AndroidManifestApplication_fullBackupContent
- */
- int getFullBackupContent();
-
- /**
- * @see R.styleable#AndroidManifestApplication_dataExtractionRules
- */
- int getDataExtractionRules();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_HAS_DOMAIN_URLS */
- boolean isHasDomainUrls();
-
- /**
- * @see ApplicationInfo#iconRes
- * @see R.styleable#AndroidManifestApplication_icon
- */
- int getIconRes();
-
- /**
- * @see ApplicationInfo#installLocation
- * @see R.styleable#AndroidManifest_installLocation
- */
- int getInstallLocation();
-
- /**
- * @see ApplicationInfo#labelRes
- * @see R.styleable#AndroidManifestApplication_label
- */
- int getLabelRes();
-
- /**
- * @see ApplicationInfo#largestWidthLimitDp
- * @see R.styleable#AndroidManifestSupportsScreens_largestWidthLimitDp
- */
- int getLargestWidthLimitDp();
-
- /**
- * @see ApplicationInfo#logo
- * @see R.styleable#AndroidManifestApplication_logo
- */
- int getLogo();
-
- /**
- * @see ApplicationInfo#manageSpaceActivityName
- * @see R.styleable#AndroidManifestApplication_manageSpaceActivity
- */
- @Nullable
- String getManageSpaceActivityName();
-
- /**
- * @see ApplicationInfo#minExtensionVersions
- * @see R.styleable#AndroidManifestExtensionSdk
- */
- @Nullable
- SparseIntArray getMinExtensionVersions();
-
- /**
- * @see ApplicationInfo#minSdkVersion
- * @see R.styleable#AndroidManifestUsesSdk_minSdkVersion
- */
- int getMinSdkVersion();
-
- /**
- * @see ApplicationInfo#networkSecurityConfigRes
- * @see R.styleable#AndroidManifestApplication_networkSecurityConfig
- */
- int getNetworkSecurityConfigRes();
-
- /**
- * If {@link R.styleable#AndroidManifestApplication_label} is a string literal, this is it.
- * Otherwise, it's stored as {@link #getLabelRes()}.
- * @see ApplicationInfo#nonLocalizedLabel
- * @see R.styleable#AndroidManifestApplication_label
- */
- @Nullable
- CharSequence getNonLocalizedLabel();
-
- /**
- * @see PackageInfo#overlayCategory
- * @see R.styleable#AndroidManifestResourceOverlay_category
- */
- @Nullable
- String getOverlayCategory();
-
- /** @see PackageInfo#mOverlayIsStatic */
- boolean isOverlayIsStatic();
-
- /**
- * @see PackageInfo#overlayPriority
- * @see R.styleable#AndroidManifestResourceOverlay_priority
- */
- int getOverlayPriority();
-
- /**
- * @see PackageInfo#overlayTarget
- * @see R.styleable#AndroidManifestResourceOverlay_targetPackage
- */
- @Nullable
- String getOverlayTarget();
-
- /**
- * @see PackageInfo#targetOverlayableName
- * @see R.styleable#AndroidManifestResourceOverlay_targetName
- */
- @Nullable
- String getOverlayTargetName();
-
- /**
- * If a system app declares {@link #getOriginalPackages()}, and the app was previously installed
- * under one of those original package names, the {@link #getPackageName()} system identifier
- * will be changed to that previously installed name. This will then be non-null, set to the
- * manifest package name, for tracking the package under its true name.
- *
- * TODO(b/135203078): Remove this in favor of checking originalPackages.isEmpty and
- * getManifestPackageName
- */
- @Nullable
- String getRealPackage();
-
- /**
- * The required account type without which this application will not function.
- *
- * @see PackageInfo#requiredAccountType
- * @see R.styleable#AndroidManifestApplication_requiredAccountType
- */
- @Nullable
- String getRequiredAccountType();
-
- /**
- * @see PackageInfo#requiredForAllUsers
- * @see R.styleable#AndroidManifestApplication_requiredForAllUsers
- */
- boolean isRequiredForAllUsers();
-
- /**
- * @see ApplicationInfo#requiresSmallestWidthDp
- * @see R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp
- */
- int getRequiresSmallestWidthDp();
-
- /**
* SHA-512 hash of the only APK that can be used to update a system package.
+ *
* @see R.styleable#AndroidManifestRestrictUpdate
*/
@Nullable
byte[] getRestrictUpdateHash();
/**
- * The restricted account authenticator type that is used by this application
- *
- * @see PackageInfo#restrictedAccountType
- * @see R.styleable#AndroidManifestApplication_restrictedAccountType
- */
- @Nullable
- String getRestrictedAccountType();
-
- /**
- * @see ApplicationInfo#roundIconRes
- * @see R.styleable#AndroidManifestApplication_roundIcon
- */
- int getRoundIconRes();
-
- /**
- * @see PackageInfo#sharedUserLabel
- * @see R.styleable#AndroidManifest_sharedUserLabel
- */
- @Deprecated
- int getSharedUserLabel();
-
- /**
* The signature data of all APKs in this package, which must be exactly the same across the
* base and splits.
*/
SigningDetails getSigningDetails();
/**
- * @see ApplicationInfo#splitClassLoaderNames
- * @see R.styleable#AndroidManifestApplication_classLoader
+ * Returns the properties set on the application
+ */
+ @NonNull
+ Map<String, Property> getProperties();
+
+ /**
+ * Flags of any split APKs; ordered by parsed splitName
*/
@Nullable
- String[] getSplitClassLoaderNames();
+ int[] getSplitFlags();
- /** @see R.styleable#AndroidManifestStaticLibrary_version */
+ /**
+ * @see R.styleable#AndroidManifestStaticLibrary_name
+ */
+ @Nullable
+ String getStaticSharedLibName();
+
+ /**
+ * @see R.styleable#AndroidManifestStaticLibrary_version
+ */
long getStaticSharedLibVersion();
/**
- * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
- * {@link android.os.Build.VERSION_CODES#DONUT}.
- * @see R.styleable#AndroidManifestSupportsScreens_largeScreens
- * @see ApplicationInfo#FLAG_SUPPORTS_LARGE_SCREENS
- */
- boolean isSupportsLargeScreens();
-
- /**
- * If omitted from manifest, returns true.
- * @see R.styleable#AndroidManifestSupportsScreens_normalScreens
- * @see ApplicationInfo#FLAG_SUPPORTS_NORMAL_SCREENS
- */
- boolean isSupportsNormalScreens();
-
- /**
- * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
- * {@link android.os.Build.VERSION_CODES#DONUT}.
- * @see R.styleable#AndroidManifestSupportsScreens_smallScreens
- * @see ApplicationInfo#FLAG_SUPPORTS_SMALL_SCREENS
- */
- boolean isSupportsSmallScreens();
-
- /**
- * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
- * {@link android.os.Build.VERSION_CODES#GINGERBREAD}.
- * @see R.styleable#AndroidManifestSupportsScreens_xlargeScreens
- * @see ApplicationInfo#FLAG_SUPPORTS_XLARGE_SCREENS
- */
- boolean isSupportsExtraLargeScreens();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING */
- boolean isAllowNativeHeapPointerTagging();
-
- int getAutoRevokePermissions();
-
- boolean hasPreserveLegacyExternalStorage();
-
- /**
- * @see ApplicationInfo#targetSandboxVersion
- * @see R.styleable#AndroidManifest_targetSandboxVersion
- */
- @Deprecated
- int getTargetSandboxVersion();
-
- /**
- * @see ApplicationInfo#theme
- * @see R.styleable#AndroidManifestApplication_theme
- */
- int getTheme();
-
- /**
- * For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in
- * {@link ParsingPackageUtils#TAG_KEY_SETS}.
+ * For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in {@link
+ * PackageParser#TAG_KEY_SETS}.
+ *
* @see R.styleable#AndroidManifestUpgradeKeySet
*/
@NonNull
Set<String> getUpgradeKeySets();
/**
- * The install time abi override to choose 32bit abi's when multiple abi's
- * are present. This is only meaningfull for multiarch applications.
- * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
+ * @see R.styleable#AndroidManifestUsesLibrary
+ */
+ @NonNull
+ List<String> getUsesLibraries();
+
+ /**
+ * @see R.styleable#AndroidManifestUsesNativeLibrary
+ */
+ @NonNull
+ List<String> getUsesNativeLibraries();
+
+ /**
+ * Like {@link #getUsesLibraries()}, but marked optional by setting {@link
+ * R.styleable#AndroidManifestUsesLibrary_required} to false . Application is expected to handle
+ * absence manually.
+ *
+ * @see R.styleable#AndroidManifestUsesLibrary
+ */
+ @NonNull
+ List<String> getUsesOptionalLibraries();
+
+ /**
+ * Like {@link #getUsesNativeLibraries()}, but marked optional by setting {@link
+ * R.styleable#AndroidManifestUsesNativeLibrary_required} to false . Application is expected to
+ * handle absence manually.
+ *
+ * @see R.styleable#AndroidManifestUsesNativeLibrary
+ */
+ @NonNull
+ List<String> getUsesOptionalNativeLibraries();
+
+ /**
+ * TODO(b/135203078): Move static library stuff to an inner data class
+ *
+ * @see R.styleable#AndroidManifestUsesStaticLibrary
+ */
+ @NonNull
+ List<String> getUsesStaticLibraries();
+
+ /**
+ * @see R.styleable#AndroidManifestUsesStaticLibrary_certDigest
+ */
+ @Nullable
+ String[][] getUsesStaticLibrariesCertDigests();
+
+ /**
+ * @see R.styleable#AndroidManifestUsesStaticLibrary_version
+ */
+ @Nullable
+ long[] getUsesStaticLibrariesVersions();
+
+ boolean hasPreserveLegacyExternalStorage();
+
+ /**
+ * @see R.styleable#AndroidManifestApplication_forceQueryable
+ */
+ boolean isForceQueryable();
+
+ /**
+ * @see ApplicationInfo#FLAG_IS_GAME
+ */
+ @Deprecated
+ boolean isGame();
+
+ /**
+ * The install time abi override to choose 32bit abi's when multiple abi's are present. This is
+ * only meaningful for multiarch applications. The use32bitAbi attribute is ignored if
+ * cpuAbiOverride is also set.
+ *
+ * @see R.attr#use32bitAbi
*/
boolean isUse32BitAbi();
- /** @see ApplicationInfo#volumeUuid */
- @Nullable
- String getVolumeUuid();
-
- /** @see ApplicationInfo#zygotePreloadName */
- @Nullable
- String getZygotePreloadName();
-
- /** Revision code of base APK */
- int getBaseRevisionCode();
-
- /** @see PackageInfo#versionName */
- @Nullable
- String getVersionName();
-
- /** @see PackageInfo#versionCodeMajor */
- @Nullable
- int getVersionCode();
-
- /** @see PackageInfo#versionCodeMajor */
- @Nullable
- int getVersionCodeMajor();
-
/**
- * @see ApplicationInfo#compileSdkVersion
- * @see R.styleable#AndroidManifest_compileSdkVersion
+ * Set if the any of components are visible to instant applications.
+ *
+ * @see R.styleable#AndroidManifestActivity_visibleToInstantApps
+ * @see R.styleable#AndroidManifestProvider_visibleToInstantApps
+ * @see R.styleable#AndroidManifestService_visibleToInstantApps
*/
- int getCompileSdkVersion();
-
- /**
- * @see ApplicationInfo#compileSdkVersionCodename
- * @see R.styleable#AndroidManifest_compileSdkVersionCodename
- */
- @Nullable
- String getCompileSdkVersionCodeName();
-
- @Nullable
- Set<String> getMimeGroups();
-
- /**
- * @see ApplicationInfo#gwpAsanMode
- * @see R.styleable#AndroidManifest_gwpAsanMode
- */
- @ApplicationInfo.GwpAsanMode
- int getGwpAsanMode();
-
- /**
- * @see ApplicationInfo#memtagMode
- * @see R.styleable#AndroidManifest_memtagMode
- */
- @ApplicationInfo.MemtagMode
- int getMemtagMode();
-
- /**
- * @see ApplicationInfo#nativeHeapZeroInitialized
- * @see R.styleable#AndroidManifest_nativeHeapZeroInitialized
- */
- @ApplicationInfo.NativeHeapZeroInitialized
- int getNativeHeapZeroInitialized();
- @Nullable
- Boolean hasRequestRawExternalStorageAccess();
-
- /**
- * @see ApplicationInfo#hasRequestForegroundServiceExemption()
- * @see R.styleable#AndroidManifest_requestForegroundServiceExemption
- */
- boolean hasRequestForegroundServiceExemption();
-
- // TODO(b/135203078): Hide and enforce going through PackageInfoUtils
- ApplicationInfo toAppInfoWithoutState();
-
- /**
- * same as toAppInfoWithoutState except without flag computation.
- */
- ApplicationInfo toAppInfoWithoutStateWithoutFlags();
-
- /**
- * Whether or not the app has said its attribution tags can be made user-visible.
- * @see ApplicationInfo#areAttributionsUserVisible()
- */
- boolean areAttributionsUserVisible();
+ boolean isVisibleToInstantApps();
}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index 115ba50..69cf32f 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -2760,7 +2760,7 @@
return input.success(pkg.setOverlay(true)
.setOverlayTarget(target)
.setOverlayPriority(priority)
- .setOverlayTargetName(
+ .setOverlayTargetOverlayableName(
sa.getString(R.styleable.AndroidManifestResourceOverlay_targetName))
.setOverlayCategory(
sa.getString(R.styleable.AndroidManifestResourceOverlay_category))
@@ -2840,9 +2840,6 @@
R.styleable.AndroidManifestOriginalPackage_name,
0);
if (!pkg.getPackageName().equals(orig)) {
- if (pkg.getOriginalPackages().isEmpty()) {
- pkg.setRealPackage(pkg.getPackageName());
- }
pkg.addOriginalPackage(orig);
}
return input.success(pkg);
diff --git a/core/java/android/content/pm/parsing/PkgWithoutStateAppInfo.java b/core/java/android/content/pm/parsing/PkgWithoutStateAppInfo.java
new file mode 100644
index 0000000..fcad10c
--- /dev/null
+++ b/core/java/android/content/pm/parsing/PkgWithoutStateAppInfo.java
@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.parsing;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.ApplicationInfo;
+import android.util.SparseArray;
+
+import com.android.internal.R;
+
+/**
+ * Container for fields that are eventually exposed through {@link ApplicationInfo}.
+ * <p>
+ * The following are dependent on system state and explicitly removed from this interface. They must
+ * be accessed by other means:
+ * <ul>
+ * <li>{@link ApplicationInfo#credentialProtectedDataDir}</li>
+ * <li>{@link ApplicationInfo#dataDir}</li>
+ * <li>{@link ApplicationInfo#deviceProtectedDataDir}</li>
+ * <li>{@link ApplicationInfo#enabledSetting}</li>
+ * <li>{@link ApplicationInfo#enabled}</li>
+ * <li>{@link ApplicationInfo#FLAG_INSTALLED}</li>
+ * <li>{@link ApplicationInfo#FLAG_STOPPED}</li>
+ * <li>{@link ApplicationInfo#FLAG_SUSPENDED}</li>
+ * <li>{@link ApplicationInfo#FLAG_UPDATED_SYSTEM_APP}</li>
+ * <li>{@link ApplicationInfo#hiddenUntilInstalled}</li>
+ * <li>{@link ApplicationInfo#primaryCpuAbi}</li>
+ * <li>{@link ApplicationInfo#PRIVATE_FLAG_HIDDEN}</li>
+ * <li>{@link ApplicationInfo#PRIVATE_FLAG_INSTANT}</li>
+ * <li>{@link ApplicationInfo#PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER}</li>
+ * <li>{@link ApplicationInfo#PRIVATE_FLAG_VIRTUAL_PRELOAD}</li>
+ * <li>{@link ApplicationInfo#resourceDirs}</li>
+ * <li>{@link ApplicationInfo#secondaryCpuAbi}</li>
+ * <li>{@link ApplicationInfo#seInfoUser}</li>
+ * <li>{@link ApplicationInfo#seInfo}</li>
+ * <li>{@link ApplicationInfo#sharedLibraryFiles}</li>
+ * <li>{@link ApplicationInfo#sharedLibraryInfos}</li>
+ * <li>{@link ApplicationInfo#uid}</li>
+ * </ul>
+ * The following are derived from other fields and thus not provided specifically:
+ * <ul>
+ * <li>{@link ApplicationInfo#getBaseResourcePath}</li>
+ * <li>{@link ApplicationInfo#getResourcePath}</li>
+ * <li>{@link ApplicationInfo#getSplitResourcePaths}</li>
+ * <li>{@link ApplicationInfo#publicSourceDir}</li>
+ * <li>{@link ApplicationInfo#scanPublicSourceDir}</li>
+ * <li>{@link ApplicationInfo#splitPublicSourceDirs}</li>
+ * <li>{@link ApplicationInfo#storageUuid}</li>
+ * </ul>
+ * The following were deprecated at migration time and thus removed from this interface:
+ * <ul>
+ * <li>{@link ApplicationInfo#FLAG_IS_GAME}</li>
+ * <li>{@link ApplicationInfo#targetSandboxVersion}</li>
+ * <li>{@link ApplicationInfo#versionCode}</li>
+ * </ul>
+ * TODO: The following fields are just not available at all. Never filled, even by legacy parsing?
+ * <ul>
+ * <li>{@link ApplicationInfo#FLAG_IS_DATA_ONLY}</li>
+ * </ul>
+ *
+ * @hide
+ */
+public interface PkgWithoutStateAppInfo {
+
+ /**
+ * @see ApplicationInfo#areAttributionsUserVisible()
+ * @see R.styleable#AndroidManifestApplication_attributionsAreUserVisible
+ */
+ @Nullable
+ boolean areAttributionsUserVisible();
+
+ /**
+ * @see ApplicationInfo#appComponentFactory
+ * @see R.styleable#AndroidManifestApplication_appComponentFactory
+ */
+ @Nullable
+ String getAppComponentFactory();
+
+ /**
+ * @see ApplicationInfo#AUTO_REVOKE_ALLOWED
+ * @see ApplicationInfo#AUTO_REVOKE_DISCOURAGED
+ * @see ApplicationInfo#AUTO_REVOKE_DISALLOWED
+ */
+ int getAutoRevokePermissions();
+
+ /**
+ * @see ApplicationInfo#backupAgentName
+ * @see R.styleable#AndroidManifestApplication_backupAgent
+ */
+ @Nullable
+ String getBackupAgentName();
+
+ /**
+ * @see ApplicationInfo#banner
+ * @see R.styleable#AndroidManifestApplication_banner
+ */
+ int getBanner();
+
+ /**
+ * @see ApplicationInfo#sourceDir
+ * @see ApplicationInfo#getBaseCodePath
+ */
+ @NonNull
+ String getBaseApkPath();
+
+ /**
+ * @see ApplicationInfo#category
+ * @see R.styleable#AndroidManifestApplication_appCategory
+ */
+ int getCategory();
+
+ /**
+ * @see ApplicationInfo#classLoaderName
+ * @see R.styleable#AndroidManifestApplication_classLoader
+ */
+ @Nullable
+ String getClassLoaderName();
+
+ /**
+ * @see ApplicationInfo#className
+ * @see R.styleable#AndroidManifestApplication_name
+ */
+ @Nullable
+ String getClassName();
+
+ /**
+ * @see ApplicationInfo#compatibleWidthLimitDp
+ * @see R.styleable#AndroidManifestSupportsScreens_compatibleWidthLimitDp
+ */
+ int getCompatibleWidthLimitDp();
+
+ /**
+ * @see ApplicationInfo#compileSdkVersion
+ * @see R.styleable#AndroidManifest_compileSdkVersion
+ */
+ int getCompileSdkVersion();
+
+ /**
+ * @see ApplicationInfo#compileSdkVersionCodename
+ * @see R.styleable#AndroidManifest_compileSdkVersionCodename
+ */
+ @Nullable
+ String getCompileSdkVersionCodeName();
+
+ /**
+ * @see ApplicationInfo#dataExtractionRulesRes
+ * @see R.styleable#AndroidManifestApplication_dataExtractionRules
+ */
+ int getDataExtractionRules();
+
+ /**
+ * @see ApplicationInfo#descriptionRes
+ * @see R.styleable#AndroidManifestApplication_description
+ */
+ int getDescriptionRes();
+
+ /**
+ * @see ApplicationInfo#fullBackupContent
+ * @see R.styleable#AndroidManifestApplication_fullBackupContent
+ */
+ int getFullBackupContent();
+
+ /**
+ * @see ApplicationInfo#getGwpAsanMode()
+ * @see R.styleable#AndroidManifestApplication_gwpAsanMode
+ */
+ @ApplicationInfo.GwpAsanMode
+ int getGwpAsanMode();
+
+ /**
+ * @see ApplicationInfo#iconRes
+ * @see R.styleable#AndroidManifestApplication_icon
+ */
+ int getIconRes();
+
+ /**
+ * @see ApplicationInfo#installLocation
+ * @see R.styleable#AndroidManifest_installLocation
+ */
+ int getInstallLocation();
+
+ /**
+ * @see ApplicationInfo#labelRes
+ * @see R.styleable#AndroidManifestApplication_label
+ */
+ int getLabelRes();
+
+ /**
+ * @see ApplicationInfo#largestWidthLimitDp
+ * @see R.styleable#AndroidManifestSupportsScreens_largestWidthLimitDp
+ */
+ int getLargestWidthLimitDp();
+
+ /**
+ * @see ApplicationInfo#logo
+ * @see R.styleable#AndroidManifestApplication_logo
+ */
+ int getLogo();
+
+ /**
+ * @see ApplicationInfo#longVersionCode
+ */
+ long getLongVersionCode();
+
+ /**
+ * @see ApplicationInfo#manageSpaceActivityName
+ * @see R.styleable#AndroidManifestApplication_manageSpaceActivity
+ */
+ @Nullable
+ String getManageSpaceActivityName();
+
+ /**
+ * @see ApplicationInfo#maxAspectRatio
+ * @see R.styleable#AndroidManifestApplication_maxAspectRatio
+ */
+ float getMaxAspectRatio();
+
+ /**
+ * @see ApplicationInfo#getMemtagMode()
+ * @see R.styleable#AndroidManifestApplication_memtagMode
+ */
+ @ApplicationInfo.MemtagMode
+ int getMemtagMode();
+
+ /**
+ * @see ApplicationInfo#minAspectRatio
+ * @see R.styleable#AndroidManifestApplication_minAspectRatio
+ */
+ float getMinAspectRatio();
+
+ /**
+ * @see ApplicationInfo#minSdkVersion
+ * @see R.styleable#AndroidManifestUsesSdk_minSdkVersion
+ */
+ int getMinSdkVersion();
+
+ /**
+ * @see ApplicationInfo#getNativeHeapZeroInitialized()
+ * @see R.styleable#AndroidManifestApplication_nativeHeapZeroInitialized
+ */
+ @ApplicationInfo.NativeHeapZeroInitialized
+ int getNativeHeapZeroInitialized();
+
+ /**
+ * @see ApplicationInfo#networkSecurityConfigRes
+ * @see R.styleable#AndroidManifestApplication_networkSecurityConfig
+ */
+ int getNetworkSecurityConfigRes();
+
+ /**
+ * If {@link R.styleable#AndroidManifestApplication_label} is a string literal, this is it.
+ * Otherwise, it's stored as {@link #getLabelRes()}.
+ *
+ * @see ApplicationInfo#nonLocalizedLabel
+ * @see R.styleable#AndroidManifestApplication_label
+ */
+ @Nullable
+ CharSequence getNonLocalizedLabel();
+
+ /**
+ * @see ApplicationInfo#scanSourceDir
+ * @see ApplicationInfo#getCodePath
+ */
+ @NonNull
+ String getPath();
+
+ /**
+ * @see ApplicationInfo#permission
+ * @see R.styleable#AndroidManifestApplication_permission
+ */
+ @Nullable
+ String getPermission();
+
+ /**
+ * @see ApplicationInfo#processName
+ * @see R.styleable#AndroidManifestApplication_process
+ */
+ @NonNull
+ String getProcessName();
+
+ /**
+ * @see ApplicationInfo#requiresSmallestWidthDp
+ * @see R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp
+ */
+ int getRequiresSmallestWidthDp();
+
+ /**
+ * Whether or not the app requested explicitly resizeable Activities. Null value means nothing
+ * was explicitly requested.
+ *
+ * @see ApplicationInfo#PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
+ * @see ApplicationInfo#PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE
+ */
+ @Nullable
+ Boolean getResizeableActivity();
+
+ /**
+ * @see ApplicationInfo#roundIconRes
+ * @see R.styleable#AndroidManifestApplication_roundIcon
+ */
+ int getRoundIconRes();
+
+ /**
+ * @see ApplicationInfo#splitClassLoaderNames
+ * @see R.styleable#AndroidManifestApplication_classLoader
+ */
+ @Nullable
+ String[] getSplitClassLoaderNames();
+
+ /**
+ * @see ApplicationInfo#splitSourceDirs
+ * @see ApplicationInfo#getSplitCodePaths
+ */
+ @Nullable
+ String[] getSplitCodePaths();
+
+ /**
+ * @see ApplicationInfo#splitDependencies
+ */
+ @Nullable
+ SparseArray<int[]> getSplitDependencies();
+
+ /**
+ * @see ApplicationInfo#targetSdkVersion
+ * @see R.styleable#AndroidManifestUsesSdk_targetSdkVersion
+ */
+ int getTargetSdkVersion();
+
+ /**
+ * @see ApplicationInfo#targetSandboxVersion
+ * @see R.styleable#AndroidManifest_targetSandboxVersion
+ */
+ int getTargetSandboxVersion();
+
+ /**
+ * @see ApplicationInfo#taskAffinity
+ * @see R.styleable#AndroidManifestApplication_taskAffinity
+ */
+ @Nullable
+ String getTaskAffinity();
+
+ /**
+ * @see ApplicationInfo#theme
+ * @see R.styleable#AndroidManifestApplication_theme
+ */
+ int getTheme();
+
+ /**
+ * @see ApplicationInfo#uiOptions
+ * @see R.styleable#AndroidManifestApplication_uiOptions
+ */
+ int getUiOptions();
+
+ /**
+ * @see ApplicationInfo#volumeUuid
+ */
+ @Nullable
+ String getVolumeUuid();
+
+ /**
+ * @see ApplicationInfo#zygotePreloadName
+ */
+ @Nullable
+ String getZygotePreloadName();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_EXT_REQUEST_FOREGROUND_SERVICE_EXEMPTION
+ * @see R.styleable#AndroidManifestApplication_requestForegroundServiceExemption
+ */
+ boolean hasRequestForegroundServiceExemption();
+
+ /**
+ * @see ApplicationInfo#getRequestRawExternalStorageAccess()
+ * @see R.styleable#AndroidManifestApplication_requestRawExternalStorageAccess
+ */
+ Boolean hasRequestRawExternalStorageAccess();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE
+ */
+ boolean isAllowAudioPlaybackCapture();
+
+ /**
+ * @see ApplicationInfo#FLAG_ALLOW_BACKUP
+ */
+ boolean isAllowBackup();
+
+ /**
+ * @see ApplicationInfo#FLAG_ALLOW_CLEAR_USER_DATA
+ */
+ boolean isAllowClearUserData();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE
+ */
+ boolean isAllowClearUserDataOnFailedRestore();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING
+ */
+ boolean isAllowNativeHeapPointerTagging();
+
+ /**
+ * @see ApplicationInfo#FLAG_ALLOW_TASK_REPARENTING
+ */
+ boolean isAllowTaskReparenting();
+
+ /**
+ * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >= {@link
+ * android.os.Build.VERSION_CODES#DONUT}.
+ *
+ * @see R.styleable#AndroidManifestSupportsScreens_anyDensity
+ * @see ApplicationInfo#FLAG_SUPPORTS_SCREEN_DENSITIES
+ */
+ boolean isAnyDensity();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_BACKUP_IN_FOREGROUND
+ */
+ boolean isBackupInForeground();
+
+ /**
+ * @see ApplicationInfo#FLAG_HARDWARE_ACCELERATED
+ */
+ boolean isBaseHardwareAccelerated();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_CANT_SAVE_STATE
+ */
+ boolean isCantSaveState();
+
+ /**
+ * @see ApplicationInfo#crossProfile
+ */
+ boolean isCrossProfile();
+
+ /**
+ * @see ApplicationInfo#FLAG_DEBUGGABLE
+ */
+ boolean isDebuggable();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE
+ */
+ boolean isDefaultToDeviceProtectedStorage();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_DIRECT_BOOT_AWARE
+ */
+ boolean isDirectBootAware();
+
+ /**
+ * @see ApplicationInfo#enabled
+ * @see R.styleable#AndroidManifestApplication_enabled
+ */
+ boolean isEnabled();
+
+ /**
+ * @see ApplicationInfo#FLAG_EXTERNAL_STORAGE
+ */
+ boolean isExternalStorage();
+
+ /**
+ * @see ApplicationInfo#FLAG_EXTRACT_NATIVE_LIBS
+ */
+ boolean isExtractNativeLibs();
+
+ /**
+ * @see ApplicationInfo#FLAG_FULL_BACKUP_ONLY
+ */
+ boolean isFullBackupOnly();
+
+ /**
+ * @see ApplicationInfo#FLAG_HAS_CODE
+ */
+ boolean isHasCode();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_HAS_DOMAIN_URLS
+ */
+ boolean isHasDomainUrls();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_HAS_FRAGILE_USER_DATA
+ */
+ boolean isHasFragileUserData();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_ISOLATED_SPLIT_LOADING
+ */
+ boolean isIsolatedSplitLoading();
+
+ /**
+ * @see ApplicationInfo#FLAG_KILL_AFTER_RESTORE
+ */
+ boolean isKillAfterRestore();
+
+ /**
+ * @see ApplicationInfo#FLAG_LARGE_HEAP
+ */
+ boolean isLargeHeap();
+
+ /**
+ * @see ApplicationInfo#FLAG_MULTIARCH
+ */
+ boolean isMultiArch();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_IS_RESOURCE_OVERLAY
+ * @see ApplicationInfo#isResourceOverlay()
+ */
+ boolean isOverlay();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE
+ */
+ boolean isPartiallyDirectBootAware();
+
+ /**
+ * @see ApplicationInfo#FLAG_PERSISTENT
+ */
+ boolean isPersistent();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_EXT_PROFILEABLE
+ */
+ boolean isProfileable();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_PROFILEABLE_BY_SHELL
+ */
+ boolean isProfileableByShell();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE
+ */
+ boolean isRequestLegacyExternalStorage();
+
+ /**
+ * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >= {@link
+ * android.os.Build.VERSION_CODES#DONUT}.
+ *
+ * @see R.styleable#AndroidManifestSupportsScreens_resizeable
+ * @see ApplicationInfo#FLAG_RESIZEABLE_FOR_SCREENS
+ */
+ boolean isResizeable();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION
+ */
+ boolean isResizeableActivityViaSdkVersion();
+
+ /**
+ * @see ApplicationInfo#FLAG_RESTORE_ANY_VERSION
+ */
+ boolean isRestoreAnyVersion();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_STATIC_SHARED_LIBRARY
+ */
+ boolean isStaticSharedLibrary();
+
+ /**
+ * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >= {@link
+ * android.os.Build.VERSION_CODES#GINGERBREAD}.
+ *
+ * @see R.styleable#AndroidManifestSupportsScreens_xlargeScreens
+ * @see ApplicationInfo#FLAG_SUPPORTS_XLARGE_SCREENS
+ */
+ boolean isSupportsExtraLargeScreens();
+
+ /**
+ * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >= {@link
+ * android.os.Build.VERSION_CODES#DONUT}.
+ *
+ * @see R.styleable#AndroidManifestSupportsScreens_largeScreens
+ * @see ApplicationInfo#FLAG_SUPPORTS_LARGE_SCREENS
+ */
+ boolean isSupportsLargeScreens();
+
+ /**
+ * If omitted from manifest, returns true.
+ *
+ * @see R.styleable#AndroidManifestSupportsScreens_normalScreens
+ * @see ApplicationInfo#FLAG_SUPPORTS_NORMAL_SCREENS
+ */
+ boolean isSupportsNormalScreens();
+
+ /**
+ * @see ApplicationInfo#FLAG_SUPPORTS_RTL
+ */
+ boolean isSupportsRtl();
+
+ /**
+ * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >= {@link
+ * android.os.Build.VERSION_CODES#DONUT}.
+ *
+ * @see R.styleable#AndroidManifestSupportsScreens_smallScreens
+ * @see ApplicationInfo#FLAG_SUPPORTS_SMALL_SCREENS
+ */
+ boolean isSupportsSmallScreens();
+
+ /**
+ * @see ApplicationInfo#FLAG_TEST_ONLY
+ */
+ boolean isTestOnly();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_USE_EMBEDDED_DEX
+ */
+ boolean isUseEmbeddedDex();
+
+ /**
+ * @see ApplicationInfo#FLAG_USES_CLEARTEXT_TRAFFIC
+ */
+ boolean isUsesCleartextTraffic();
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_USES_NON_SDK_API
+ */
+ boolean isUsesNonSdkApi();
+
+ /**
+ * @see ApplicationInfo#FLAG_VM_SAFE_MODE
+ */
+ boolean isVmSafeMode();
+}
diff --git a/core/java/android/content/pm/parsing/PkgWithoutStatePackageInfo.java b/core/java/android/content/pm/parsing/PkgWithoutStatePackageInfo.java
new file mode 100644
index 0000000..b10e6fe5
--- /dev/null
+++ b/core/java/android/content/pm/parsing/PkgWithoutStatePackageInfo.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.parsing;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ConfigurationInfo;
+import android.content.pm.FeatureGroupInfo;
+import android.content.pm.FeatureInfo;
+import android.content.pm.InstrumentationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PermissionInfo;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ServiceInfo;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedInstrumentation;
+import android.content.pm.parsing.component.ParsedPermission;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedService;
+
+import com.android.internal.R;
+
+import java.util.List;
+
+/**
+ * Container for fields that are eventually exposed through {@link PackageInfo}.
+ * <p>
+ * The following are dependent on system state and explicitly removed from this interface. They must
+ * be accessed by other means:
+ * <ul>
+ * <li>{@link PackageInfo#firstInstallTime}</li>
+ * <li>{@link PackageInfo#lastUpdateTime}</li>
+ * <li>{@link PackageInfo#gids}</li>
+ * </ul>
+ * The following are derived from other fields and thus not provided specifically:
+ * <ul>
+ * <li>{@link PackageInfo#requestedPermissionsFlags}</li>
+ * </ul>
+ * The following were deprecated at migration time and thus removed from this interface:
+ * <ul>
+ * <li>{@link PackageInfo#mOverlayIsStatic}</li>
+ * <li>{@link PackageInfo#overlayCategory}</li>
+ * <li>{@link PackageInfo#overlayPriority}</li>
+ * <li>{@link PackageInfo#overlayTarget}</li>
+ * <li>{@link PackageInfo#signatures}</li>
+ * <li>{@link PackageInfo#targetOverlayableName}</li>
+ * <li>{@link PackageInfo#versionCodeMajor}</li>
+ * <li>{@link PackageInfo#versionCode}</li>
+ * </ul>
+ * The following are retrieved through other APIs:
+ * <ul>
+ * <li>{@link PackageInfo#signingInfo}</li>
+ * <li>{@link PackageInfo#isApex}</li>
+ * </ul>
+ *
+ * @hide
+ */
+public interface PkgWithoutStatePackageInfo {
+
+ /**
+ * @see ActivityInfo
+ * @see PackageInfo#activities
+ */
+ @NonNull
+ List<ParsedActivity> getActivities();
+
+ /**
+ * @see PackageInfo#baseRevisionCode
+ */
+ int getBaseRevisionCode();
+
+ /**
+ * @see PackageInfo#compileSdkVersion
+ * @see R.styleable#AndroidManifest_compileSdkVersion
+ */
+ int getCompileSdkVersion();
+
+ /**
+ * @see ApplicationInfo#compileSdkVersionCodename
+ * @see R.styleable#AndroidManifest_compileSdkVersionCodename
+ */
+ @Nullable
+ String getCompileSdkVersionCodeName();
+
+ /**
+ * @see PackageInfo#configPreferences
+ * @see R.styleable#AndroidManifestUsesConfiguration
+ */
+ @NonNull
+ List<ConfigurationInfo> getConfigPreferences();
+
+ /**
+ * @see PackageInfo#featureGroups
+ * @see R.styleable#AndroidManifestUsesFeature
+ */
+ @NonNull
+ List<FeatureGroupInfo> getFeatureGroups();
+
+ /**
+ * @see InstrumentationInfo
+ * @see PackageInfo#instrumentation
+ */
+ @NonNull
+ List<ParsedInstrumentation> getInstrumentations();
+
+ /**
+ * @see PackageInfo#getLongVersionCode()
+ */
+ long getLongVersionCode();
+
+ /**
+ * @see PackageInfo#packageName
+ */
+ String getPackageName();
+
+ /**
+ * @see PermissionInfo
+ * @see PackageInfo#permissions
+ */
+ @NonNull
+ List<ParsedPermission> getPermissions();
+
+ /**
+ * @see ProviderInfo
+ * @see PackageInfo#providers
+ */
+ @NonNull
+ List<ParsedProvider> getProviders();
+
+ /**
+ * Since they share several attributes, receivers are parsed as {@link ParsedActivity}, even
+ * though they represent different functionality. TODO(b/135203078): Reconsider this and maybe
+ * make ParsedReceiver so it's not so confusing
+ *
+ * @see ActivityInfo
+ * @see PackageInfo#receivers
+ */
+ @NonNull
+ List<ParsedActivity> getReceivers();
+
+ /**
+ * @see PackageInfo#reqFeatures
+ * @see R.styleable#AndroidManifestUsesFeature
+ */
+ @NonNull
+ List<FeatureInfo> getRequestedFeatures();
+
+ /**
+ * All the permissions declared. This is an effective set, and may include permissions
+ * transformed from split/migrated permissions from previous versions, so may not be exactly
+ * what the package declares in its manifest.
+ *
+ * @see PackageInfo#requestedPermissions
+ * @see R.styleable#AndroidManifestUsesPermission
+ */
+ @NonNull
+ List<String> getRequestedPermissions();
+
+ /**
+ * The required account type without which this application will not function.
+ *
+ * @see PackageInfo#requiredAccountType
+ * @see R.styleable#AndroidManifestApplication_requiredAccountType
+ */
+ @Nullable
+ String getRequiredAccountType();
+
+ /**
+ * The restricted account authenticator type that is used by this application
+ *
+ * @see PackageInfo#restrictedAccountType
+ * @see R.styleable#AndroidManifestApplication_restrictedAccountType
+ */
+ @Nullable
+ String getRestrictedAccountType();
+
+ /**
+ * @see ServiceInfo
+ * @see PackageInfo#services
+ */
+ @NonNull
+ List<ParsedService> getServices();
+
+ /**
+ * @see PackageInfo#sharedUserId
+ * @see R.styleable#AndroidManifest_sharedUserId
+ */
+ @Nullable
+ String getSharedUserId();
+
+ /**
+ * @see PackageInfo#sharedUserLabel
+ * @see R.styleable#AndroidManifest_sharedUserLabel
+ */
+ int getSharedUserLabel();
+
+ /**
+ * TODO(b/135203078): Move split stuff to an inner data class
+ *
+ * @see ApplicationInfo#splitNames
+ * @see PackageInfo#splitNames
+ */
+ @Nullable
+ String[] getSplitNames();
+
+ /**
+ * @see PackageInfo#splitRevisionCodes
+ */
+ int[] getSplitRevisionCodes();
+
+ /**
+ * @see PackageInfo#versionName
+ */
+ @Nullable
+ String getVersionName();
+
+ /**
+ * @see PackageInfo#requiredForAllUsers
+ * @see R.styleable#AndroidManifestApplication_requiredForAllUsers
+ */
+ boolean isRequiredForAllUsers();
+}
diff --git a/core/java/android/content/pm/pkg/PackageUserState.java b/core/java/android/content/pm/pkg/PackageUserState.java
new file mode 100644
index 0000000..e5853f0
--- /dev/null
+++ b/core/java/android/content/pm/pkg/PackageUserState.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.pkg;
+
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.pm.PackageManager;
+import android.content.pm.overlay.OverlayPaths;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The API surface for a {@link android.content.pm.PackageUserState}. Methods are expected to return
+ * immutable objects. This may mean copying data on each invocation until related classes are
+ * refactored to be immutable.
+ * <p>
+ * TODO: Replace implementation usage with the interface. Currently the name overlap is intentional.
+ * <p>
+ *
+ * @hide
+ */
+// TODO(b/173807334): Expose API
+//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+public interface PackageUserState {
+ /**
+ * Credential encrypted /data partition inode.
+ */
+ long getCeDataInode();
+
+ @NonNull
+ Set<String> getDisabledComponents();
+
+ @PackageManager.DistractionRestriction
+ int getDistractionFlags();
+
+ @NonNull
+ Set<String> getEnabledComponents();
+
+ int getEnabledState();
+
+ @Nullable
+ String getHarmfulAppWarning();
+
+ @PackageManager.InstallReason
+ int getInstallReason();
+
+ @Nullable
+ String getLastDisableAppCaller();
+
+ @Nullable
+ OverlayPaths getOverlayPaths();
+
+ @NonNull
+ Map<String, OverlayPaths> getSharedLibraryOverlayPaths();
+
+ @PackageManager.UninstallReason
+ int getUninstallReason();
+
+ boolean isHidden();
+
+ boolean isInstalled();
+
+ boolean isInstantApp();
+
+ boolean isNotLaunched();
+
+ boolean isStopped();
+
+ boolean isSuspended();
+
+ boolean isVirtualPreload();
+}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 73961ff..209ee40e 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -1113,6 +1113,44 @@
}
/**
+ * Sets the default display mode, according to the refresh rate and the resolution chosen by the
+ * user.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+ public void setUserPreferredDisplayMode(@NonNull Display.Mode mode) {
+ // Create a new object containing default values for the unused fields like mode ID and
+ // alternative refresh rates.
+ Display.Mode preferredMode = new Display.Mode(mode.getPhysicalWidth(),
+ mode.getPhysicalHeight(), mode.getRefreshRate());
+ mGlobal.setUserPreferredDisplayMode(preferredMode);
+ }
+
+ /**
+ * Removes the user preferred display mode.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+ public void clearUserPreferredDisplayMode() {
+ mGlobal.setUserPreferredDisplayMode(null);
+ }
+
+ /**
+ * Returns the user preferred display mode.
+ *
+ * @hide
+ */
+ @TestApi
+ @Nullable
+ public Display.Mode getUserPreferredDisplayMode() {
+ return mGlobal.getUserPreferredDisplayMode();
+ }
+
+ /**
* When enabled the app requested mode is always selected regardless of user settings and
* policies for low brightness, low battery, etc.
*
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 1fec3c9f..75155bb 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -877,6 +877,29 @@
}
/**
+ * Sets the default display mode, according to the refresh rate and the resolution chosen by the
+ * user.
+ */
+ public void setUserPreferredDisplayMode(Display.Mode mode) {
+ try {
+ mDm.setUserPreferredDisplayMode(mode);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the user preferred display mode.
+ */
+ public Display.Mode getUserPreferredDisplayMode() {
+ try {
+ return mDm.getUserPreferredDisplayMode();
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* When enabled the app requested display resolution and refresh rate is always selected
* in DisplayModeDirector regardless of user settings and policies for low brightness, low
* battery etc.
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 1162146..b3be9da 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -27,6 +27,7 @@
import android.hardware.display.WifiDisplay;
import android.hardware.display.WifiDisplayStatus;
import android.media.projection.IMediaProjection;
+import android.view.Display.Mode;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -162,6 +163,11 @@
// based on hardware capability.
int getPreferredWideGamutColorSpaceId();
+ // Sets the user preferred display mode.
+ // Requires WRITE_SECURE_SETTINGS permission.
+ void setUserPreferredDisplayMode(in Mode mode);
+ Mode getUserPreferredDisplayMode();
+
// When enabled the app requested display resolution and refresh rate is always selected
// in DisplayModeDirector regardless of user settings and policies for low brightness, low
// battery etc.
diff --git a/core/java/android/inputmethodservice/RemoteInputConnection.java b/core/java/android/inputmethodservice/RemoteInputConnection.java
index 464b421..589dd72 100644
--- a/core/java/android/inputmethodservice/RemoteInputConnection.java
+++ b/core/java/android/inputmethodservice/RemoteInputConnection.java
@@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Handler;
+import android.util.Log;
import android.view.KeyEvent;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
@@ -62,8 +63,29 @@
@NonNull
private final IInputContextInvoker mInvoker;
+ private static final class InputMethodServiceInternalHolder {
+ @NonNull
+ private final WeakReference<InputMethodServiceInternal> mServiceRef;
+
+ private InputMethodServiceInternalHolder(
+ @NonNull WeakReference<InputMethodServiceInternal> ims) {
+ mServiceRef = ims;
+ }
+
+ @AnyThread
+ @Nullable
+ public InputMethodServiceInternal getAndWarnIfNull() {
+ final InputMethodServiceInternal ims = mServiceRef.get();
+ if (ims == null) {
+ Log.e(TAG, "InputMethodService is already destroyed. InputConnection instances"
+ + " cannot be used beyond InputMethodService lifetime.", new Throwable());
+ }
+ return ims;
+ }
+ }
+
@NonNull
- private final WeakReference<InputMethodServiceInternal> mInputMethodService;
+ private final InputMethodServiceInternalHolder mImsInternal;
@MissingMethodFlags
private final int mMissingMethods;
@@ -81,7 +103,7 @@
@NonNull WeakReference<InputMethodServiceInternal> inputMethodService,
IInputContext inputContext, @MissingMethodFlags int missingMethods,
@NonNull CancellationGroup cancellationGroup) {
- mInputMethodService = inputMethodService;
+ mImsInternal = new InputMethodServiceInternalHolder(inputMethodService);
mInvoker = IInputContextInvoker.create(inputContext);
mMissingMethods = missingMethods;
mCancellationGroup = cancellationGroup;
@@ -101,11 +123,11 @@
final CharSequence result = CompletableFutureUtil.getResultOrNull(
value, TAG, "getTextAfterCursor()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
- final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
- if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
+ final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull();
+ if (imsInternal != null && ImeTracing.getInstance().isEnabled()) {
final byte[] icProto = InputConnectionProtoDumper.buildGetTextAfterCursorProto(length,
flags, result);
- inputMethodService.triggerServiceDump(TAG + "#getTextAfterCursor", icProto);
+ imsInternal.triggerServiceDump(TAG + "#getTextAfterCursor", icProto);
}
return result;
@@ -125,11 +147,11 @@
final CharSequence result = CompletableFutureUtil.getResultOrNull(
value, TAG, "getTextBeforeCursor()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
- final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
- if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
+ final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull();
+ if (imsInternal != null && ImeTracing.getInstance().isEnabled()) {
final byte[] icProto = InputConnectionProtoDumper.buildGetTextBeforeCursorProto(length,
flags, result);
- inputMethodService.triggerServiceDump(TAG + "#getTextBeforeCursor", icProto);
+ imsInternal.triggerServiceDump(TAG + "#getTextBeforeCursor", icProto);
}
return result;
@@ -149,11 +171,11 @@
final CharSequence result = CompletableFutureUtil.getResultOrNull(
value, TAG, "getSelectedText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
- final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
- if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
+ final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull();
+ if (imsInternal != null && ImeTracing.getInstance().isEnabled()) {
final byte[] icProto = InputConnectionProtoDumper.buildGetSelectedTextProto(flags,
result);
- inputMethodService.triggerServiceDump(TAG + "#getSelectedText", icProto);
+ imsInternal.triggerServiceDump(TAG + "#getSelectedText", icProto);
}
return result;
@@ -187,11 +209,11 @@
final SurroundingText result = CompletableFutureUtil.getResultOrNull(
value, TAG, "getSurroundingText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
- final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
- if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
+ final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull();
+ if (imsInternal != null && ImeTracing.getInstance().isEnabled()) {
final byte[] icProto = InputConnectionProtoDumper.buildGetSurroundingTextProto(
beforeLength, afterLength, flags, result);
- inputMethodService.triggerServiceDump(TAG + "#getSurroundingText", icProto);
+ imsInternal.triggerServiceDump(TAG + "#getSurroundingText", icProto);
}
return result;
@@ -207,11 +229,11 @@
final int result = CompletableFutureUtil.getResultOrZero(
value, TAG, "getCursorCapsMode()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
- final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
- if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
+ final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull();
+ if (imsInternal != null && ImeTracing.getInstance().isEnabled()) {
final byte[] icProto = InputConnectionProtoDumper.buildGetCursorCapsModeProto(
reqModes, result);
- inputMethodService.triggerServiceDump(TAG + "#getCursorCapsMode", icProto);
+ imsInternal.triggerServiceDump(TAG + "#getCursorCapsMode", icProto);
}
return result;
@@ -227,11 +249,11 @@
final ExtractedText result = CompletableFutureUtil.getResultOrNull(
value, TAG, "getExtractedText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
- final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
- if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
+ final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull();
+ if (imsInternal != null && ImeTracing.getInstance().isEnabled()) {
final byte[] icProto = InputConnectionProtoDumper.buildGetExtractedTextProto(
request, flags, result);
- inputMethodService.triggerServiceDump(TAG + "#getExtractedText", icProto);
+ imsInternal.triggerServiceDump(TAG + "#getExtractedText", icProto);
}
return result;
@@ -248,12 +270,11 @@
@AnyThread
private void notifyUserActionIfNecessary() {
- final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
- if (inputMethodService == null) {
- // This basically should not happen, because it's the the caller of this method.
+ final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull();
+ if (imsInternal == null) {
return;
}
- inputMethodService.notifyUserActionIfNecessary();
+ imsInternal.notifyUserActionIfNecessary();
}
@AnyThread
@@ -372,7 +393,15 @@
// This method is not implemented.
return false;
}
- final CompletableFuture<Boolean> value = mInvoker.requestCursorUpdates(cursorUpdateMode);
+
+ final InputMethodServiceInternal ims = mImsInternal.getAndWarnIfNull();
+ if (ims == null) {
+ return false;
+ }
+
+ final int displayId = ims.getContext().getDisplayId();
+ final CompletableFuture<Boolean> value =
+ mInvoker.requestCursorUpdates(cursorUpdateMode, displayId);
return CompletableFutureUtil.getResultOrFalse(value, TAG, "requestCursorUpdates()",
mCancellationGroup, MAX_WAIT_TIME_MILLIS);
}
@@ -400,12 +429,11 @@
}
if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
- final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
- if (inputMethodService == null) {
- // This basically should not happen, because it's the caller of this method.
+ final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull();
+ if (imsInternal == null) {
return false;
}
- inputMethodService.exposeContent(inputContentInfo, this);
+ imsInternal.exposeContent(inputContentInfo, this);
}
final CompletableFuture<Boolean> value =
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 98730c2..7002a38 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -14604,6 +14604,38 @@
public static final int HEADS_UP_ON = 1;
/**
+ * The refresh rate chosen by the user.
+ *
+ * @hide
+ */
+ @TestApi
+ @Readable
+ @SuppressLint("NoSettingsProvider")
+ public static final String USER_PREFERRED_REFRESH_RATE = "user_preferred_refresh_rate";
+
+ /**
+ * The resolution height chosen by the user.
+ *
+ * @hide
+ */
+ @TestApi
+ @Readable
+ @SuppressLint("NoSettingsProvider")
+ public static final String USER_PREFERRED_RESOLUTION_HEIGHT =
+ "user_preferred_resolution_height";
+
+ /**
+ * The resolution width chosen by the user.
+ *
+ * @hide
+ */
+ @TestApi
+ @Readable
+ @SuppressLint("NoSettingsProvider")
+ public static final String USER_PREFERRED_RESOLUTION_WIDTH =
+ "user_preferred_resolution_width";
+
+ /**
* The name of the device
*/
@Readable
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 4bf6049..cb5e51c 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -102,6 +102,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
@@ -158,6 +159,7 @@
private static final int MSG_REQUEST_WALLPAPER_COLORS = 10050;
private static final int MSG_ZOOM = 10100;
private static final int MSG_SCALE_PREVIEW = 10110;
+ private static final int MSG_REPORT_SHOWN = 10150;
private static final List<Float> PROHIBITED_STEPS = Arrays.asList(0f, Float.POSITIVE_INFINITY,
Float.NEGATIVE_INFINITY);
@@ -540,6 +542,35 @@
}
/**
+ * This will be called in the end of {@link #updateSurface(boolean, boolean, boolean)}.
+ * If true is returned, the engine will not report shown until rendering finished is
+ * reported. Otherwise, the engine will report shown immediately right after redraw phase
+ * in {@link #updateSurface(boolean, boolean, boolean)}.
+ *
+ * @hide
+ */
+ public boolean shouldWaitForEngineShown() {
+ return false;
+ }
+
+ /**
+ * Reports the rendering is finished, stops waiting, then invokes
+ * {@link IWallpaperEngineWrapper#reportShown()}.
+ *
+ * @hide
+ */
+ public void reportEngineShown(boolean waitForEngineShown) {
+ if (mIWallpaperEngine.mShownReported) return;
+ Message message = mCaller.obtainMessage(MSG_REPORT_SHOWN);
+ if (!waitForEngineShown) {
+ mCaller.removeMessages(MSG_REPORT_SHOWN);
+ mCaller.sendMessage(message);
+ } else {
+ mCaller.sendMessageDelayed(message, TimeUnit.SECONDS.toMillis(1));
+ }
+ }
+
+ /**
* Control whether this wallpaper will receive raw touch events
* from the window manager as the user interacts with the window
* that is currently displaying the wallpaper. By default they
@@ -943,7 +974,8 @@
void updateSurface(boolean forceRelayout, boolean forceReport, boolean redrawNeeded) {
if (mDestroyed) {
- Log.w(TAG, "Ignoring updateSurface: destroyed");
+ Log.w(TAG, "Ignoring updateSurface due to destroyed");
+ return;
}
boolean fixedSize = false;
@@ -1210,7 +1242,6 @@
+ this);
onVisibilityChanged(false);
}
-
} finally {
mIsCreating = false;
mSurfaceCreated = true;
@@ -1220,7 +1251,7 @@
processLocalColors(mPendingXOffset, mPendingXOffsetStep);
}
reposition();
- mIWallpaperEngine.reportShown();
+ reportEngineShown(shouldWaitForEngineShown());
}
} catch (RemoteException ex) {
}
@@ -2379,6 +2410,9 @@
// Connection went away, nothing to do in here.
}
} break;
+ case MSG_REPORT_SHOWN: {
+ reportShown();
+ } break;
default :
Log.w(TAG, "Unknown message type " + message.what);
}
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index f50b51b..5153aee 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -28,6 +28,7 @@
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
/**
* ArrayMap is a generic key->value mapping data structure that is
@@ -1024,6 +1025,36 @@
}
/**
+ * Replaces each entry's value with the result of invoking the given function on that entry
+ * until all entries have been processed or the function throws an exception. Exceptions thrown
+ * by the function are relayed to the caller. This implementation overrides
+ * the default implementation to avoid iterating using the {@link #entrySet()} and iterates in
+ * the key-value order consistent with {@link #keyAt(int)} and {@link #valueAt(int)}.
+ *
+ * @param function The function to apply to each entry
+ */
+ @Override
+ public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+ if (function == null) {
+ throw new NullPointerException("function must not be null");
+ }
+
+ final int size = mSize;
+ try {
+ for (int i = 0; i < size; ++i) {
+ final int valIndex = (i << 1) + 1;
+ //noinspection unchecked
+ mArray[valIndex] = function.apply((K) mArray[i << 1], (V) mArray[valIndex]);
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new ConcurrentModificationException();
+ }
+ if (size != mSize) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ /**
* Remove all keys in the array map that do <b>not</b> exist in the given collection.
* @param collection The collection whose contents are to be used to determine which
* keys to keep.
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index e7ff978..8259a9d 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1000,6 +1000,18 @@
}
/**
+ * Returns the default mode of the display.
+ * @hide
+ */
+ @TestApi
+ public @NonNull Mode getDefaultMode() {
+ synchronized (mLock) {
+ updateDisplayInfoLocked();
+ return mDisplayInfo.getDefaultMode();
+ }
+ }
+
+ /**
* Gets the supported modes of this display.
*/
public Mode[] getSupportedModes() {
@@ -1699,6 +1711,11 @@
*/
public static final Mode[] EMPTY_ARRAY = new Mode[0];
+ /**
+ * @hide
+ */
+ public static final int INVALID_MODE_ID = -1;
+
private final int mModeId;
private final int mWidth;
private final int mHeight;
@@ -1709,6 +1726,14 @@
/**
* @hide
*/
+ @TestApi
+ public Mode(int width, int height, float refreshRate) {
+ this(INVALID_MODE_ID, width, height, refreshRate, new float[0]);
+ }
+
+ /**
+ * @hide
+ */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public Mode(int modeId, int width, int height, float refreshRate) {
this(modeId, width, height, refreshRate, new float[0]);
@@ -1804,6 +1829,7 @@
*
* @hide
*/
+ @TestApi
public boolean matches(int width, int height, float refreshRate) {
return mWidth == width &&
mHeight == height &&
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 371d3d0..ae2eed8 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -33,6 +33,7 @@
import android.os.IRemoteCallback;
import android.os.ParcelFileDescriptor;
import android.view.DisplayCutout;
+import android.view.DisplayInfo;
import android.view.IApplicationToken;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.ICrossWindowBlurEnabledListener;
@@ -736,6 +737,17 @@
out InsetsState outInsetsState);
/**
+ * Returns a list of {@link android.view.DisplayInfo} for the logical display. This is not
+ * guaranteed to include all possible device states. The list items are unique.
+ *
+ * If invoked through a package other than a launcher app, returns an empty list.
+ *
+ * @param displayId the id of the logical display
+ * @param packageName the name of the calling package
+ */
+ List<DisplayInfo> getPossibleDisplayInfo(int displayId, String packageName);
+
+ /**
* Called to show global actions.
*/
void showGlobalActions();
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 75b69cb..3917279 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -202,7 +202,7 @@
@Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
Insets[] typeInsetsMap = new Insets[Type.SIZE];
Insets[] typeMaxInsetsMap = new Insets[Type.SIZE];
- boolean[] typeVisibilityMap = new boolean[SIZE];
+ boolean[] typeVisibilityMap = new boolean[Type.SIZE];
final Rect relativeFrame = new Rect(frame);
final Rect relativeFrameMax = new Rect(frame);
for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 9972eba..9e5d122 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1820,11 +1820,6 @@
* @hide
*/
public static final class DisplayMode {
- /**
- * Invalid display config id.
- */
- public static final int INVALID_DISPLAY_MODE_ID = -1;
-
public int id;
public int width;
public int height;
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index ddc532c..945758f 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1464,19 +1464,18 @@
@Override
public void positionChanged(long frameNumber, int left, int top, int right, int bottom) {
- if (mSurfaceControl == null) {
- return;
- }
-
- // TODO: This is teensy bit racey in that a brand new SurfaceView moving on
- // its 2nd frame if RenderThread is running slowly could potentially see
- // this as false, enter the branch, get pre-empted, then this comes along
- // and reports a new position, then the UI thread resumes and reports
- // its position. This could therefore be de-sync'd in that interval, but
- // the synchronization would violate the rule that RT must never block
- // on the UI thread which would open up potential deadlocks. The risk of
- // a single-frame desync is therefore preferable for now.
synchronized(mSurfaceControlLock) {
+ if (mSurfaceControl == null) {
+ return;
+ }
+ // TODO: This is teensy bit racey in that a brand new SurfaceView moving on
+ // its 2nd frame if RenderThread is running slowly could potentially see
+ // this as false, enter the branch, get pre-empted, then this comes along
+ // and reports a new position, then the UI thread resumes and reports
+ // its position. This could therefore be de-sync'd in that interval, but
+ // the synchronization would violate the rule that RT must never block
+ // on the UI thread which would open up potential deadlocks. The risk of
+ // a single-frame desync is therefore preferable for now.
mRtHandlingPositionUpdates = true;
}
if (mRTLastReportedPosition.left == left
@@ -1506,8 +1505,11 @@
if (mViewVisibility) {
mPositionChangedTransaction.show(mSurfaceControl);
}
- applyChildSurfaceTransaction_renderWorker(mPositionChangedTransaction,
- getViewRootImpl().mSurface, frameNumber);
+ final ViewRootImpl viewRoot = getViewRootImpl();
+ if (viewRoot != null) {
+ applyChildSurfaceTransaction_renderWorker(mPositionChangedTransaction,
+ viewRoot.mSurface, frameNumber);
+ }
applyOrMergeTransaction(mPositionChangedTransaction, frameNumber);
mPendingTransaction = false;
} catch (Exception ex) {
@@ -1528,7 +1530,7 @@
@Override
public void positionLost(long frameNumber) {
- if (DEBUG) {
+ if (DEBUG_POSITION) {
Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
System.identityHashCode(this), frameNumber));
}
@@ -1540,15 +1542,15 @@
mPositionChangedTransaction.clear();
mPendingTransaction = false;
}
- if (mSurfaceControl == null) {
- return;
- }
/**
* positionLost can be called while UI thread is un-paused so we
* need to hold the lock here.
*/
synchronized (mSurfaceControlLock) {
+ if (mSurfaceControl == null) {
+ return;
+ }
mRtTransaction.hide(mSurfaceControl);
if (mRtReleaseSurfaces) {
mRtReleaseSurfaces = false;
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 0f1a9d9..cde1cc7 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -903,6 +903,16 @@
result.append(mPrivacyIndicatorBounds != null ? "privacyIndicatorBounds="
+ mPrivacyIndicatorBounds : "");
result.append("\n ");
+ result.append("compatInsetsTypes=" + mCompatInsetsTypes);
+ result.append("\n ");
+ result.append("compatIgnoreVisibility=" + mCompatIgnoreVisibility);
+ result.append("\n ");
+ result.append("systemWindowInsetsConsumed=" + mSystemWindowInsetsConsumed);
+ result.append("\n ");
+ result.append("stableInsetsConsumed=" + mStableInsetsConsumed);
+ result.append("\n ");
+ result.append("displayCutoutConsumed=" + mDisplayCutoutConsumed);
+ result.append("\n ");
result.append(isRound() ? "round" : "");
result.append("}");
return result.toString();
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 9a57e74..d76f789 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -123,6 +123,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -714,6 +715,20 @@
}
/**
+ * Returns a set of {@link WindowMetrics} for the given display. Each WindowMetrics instance
+ * is the maximum WindowMetrics for a device state, including rotations. This is not guaranteed
+ * to include all possible device states.
+ *
+ * This API can only be used by Launcher.
+ *
+ * @param displayId the id of the logical display
+ * @hide
+ */
+ default @NonNull Set<WindowMetrics> getPossibleMaximumWindowMetrics(int displayId) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
* Used to asynchronously request Keyboard Shortcuts from the focused window.
*
* @hide
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 7bd156b..1f80f8a 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -17,12 +17,8 @@
package android.view;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
-import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import static android.window.WindowProviderService.isWindowProviderService;
@@ -47,7 +43,9 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.IResultReceiver;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -304,27 +302,38 @@
private WindowInsets computeWindowInsets(Rect bounds) {
// Initialize params which used for obtaining all system insets.
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
- params.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
final Context context = (mParentWindow != null) ? mParentWindow.getContext() : mContext;
params.token = Context.getToken(context);
- params.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
- params.setFitInsetsTypes(0);
- params.setFitInsetsSides(0);
-
- return getWindowInsetsFromServer(params, bounds);
+ return getWindowInsetsFromServerForCurrentDisplay(params, bounds);
}
- private WindowInsets getWindowInsetsFromServer(WindowManager.LayoutParams attrs, Rect bounds) {
+ private WindowInsets getWindowInsetsFromServerForCurrentDisplay(
+ WindowManager.LayoutParams attrs, Rect bounds) {
+ final Configuration config = mContext.getResources().getConfiguration();
+ return getWindowInsetsFromServerForDisplay(mContext.getDisplayId(), attrs, bounds,
+ config.isScreenRound(), config.windowConfiguration.getWindowingMode());
+ }
+
+ /**
+ * Retrieves WindowInsets for the given context and display, given the window bounds.
+ *
+ * @param displayId the ID of the logical display to calculate insets for
+ * @param attrs the LayoutParams for the calling app
+ * @param bounds the window bounds to calculate insets for
+ * @param isScreenRound if the display identified by displayId is round
+ * @param windowingMode the windowing mode of the window to calculate insets for
+ * @return WindowInsets calculated for the given window bounds, on the given display
+ */
+ private static WindowInsets getWindowInsetsFromServerForDisplay(int displayId,
+ WindowManager.LayoutParams attrs, Rect bounds, boolean isScreenRound,
+ int windowingMode) {
try {
final InsetsState insetsState = new InsetsState();
final boolean alwaysConsumeSystemBars = WindowManagerGlobal.getWindowManagerService()
- .getWindowInsets(attrs, mContext.getDisplayId(), insetsState);
- final Configuration config = mContext.getResources().getConfiguration();
- final boolean isScreenRound = config.isScreenRound();
+ .getWindowInsets(attrs, displayId, insetsState);
return insetsState.calculateInsets(bounds, null /* ignoringVisibilityState*/,
isScreenRound, alwaysConsumeSystemBars, SOFT_INPUT_ADJUST_NOTHING, attrs.flags,
- SYSTEM_UI_FLAG_VISIBLE, attrs.type, WINDOWING_MODE_FULLSCREEN,
+ SYSTEM_UI_FLAG_VISIBLE, attrs.type, windowingMode,
null /* typeSideMap */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -332,6 +341,50 @@
}
@Override
+ @NonNull
+ public Set<WindowMetrics> getPossibleMaximumWindowMetrics(int displayId) {
+ List<DisplayInfo> possibleDisplayInfos;
+ try {
+ possibleDisplayInfos = WindowManagerGlobal.getWindowManagerService()
+ .getPossibleDisplayInfo(displayId, mContext.getPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+
+ int size = possibleDisplayInfos.size();
+ DisplayInfo currentDisplayInfo;
+ WindowInsets windowInsets = null;
+ if (size > 0) {
+ currentDisplayInfo = possibleDisplayInfos.get(0);
+
+ final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+ final boolean isScreenRound = (currentDisplayInfo.flags & Display.FLAG_ROUND) != 0;
+ // TODO(181127261) not computing insets correctly - need to have underlying
+ // frame reflect the faked orientation.
+ windowInsets = getWindowInsetsFromServerForDisplay(
+ currentDisplayInfo.displayId, params,
+ new Rect(0, 0, currentDisplayInfo.getNaturalWidth(),
+ currentDisplayInfo.getNaturalHeight()), isScreenRound,
+ WINDOWING_MODE_FULLSCREEN);
+ }
+
+ Set<WindowMetrics> maxMetrics = new HashSet<>();
+ for (int i = 0; i < size; i++) {
+ currentDisplayInfo = possibleDisplayInfos.get(i);
+
+ // Calculate max bounds for this rotation and state.
+ Rect maxBounds = new Rect(0, 0, currentDisplayInfo.getNaturalWidth(),
+ currentDisplayInfo.getNaturalHeight());
+
+ // Calculate insets for the rotated max bounds.
+ // TODO(181127261) calculate insets for each display rotation and state.
+
+ maxMetrics.add(new WindowMetrics(maxBounds, windowInsets));
+ }
+ return maxMetrics;
+ }
+
+ @Override
public void holdLock(IBinder token, int durationMs) {
try {
WindowManagerGlobal.getWindowManagerService().holdLock(token, durationMs);
diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java
index 1019612..b571560 100644
--- a/core/java/android/view/translation/UiTranslationController.java
+++ b/core/java/android/view/translation/UiTranslationController.java
@@ -112,11 +112,10 @@
public void updateUiTranslationState(@UiTranslationState int state, TranslationSpec sourceSpec,
TranslationSpec targetSpec, List<AutofillId> views,
UiTranslationSpec uiTranslationSpec) {
- if (!mActivity.isResumed() && (state == STATE_UI_TRANSLATION_STARTED
- || state == STATE_UI_TRANSLATION_RESUMED)) {
+ if (mActivity.isDestroyed()) {
+ Log.i(TAG, "Cannot update " + stateToString(state) + " for destroyed " + mActivity);
return;
}
-
Log.i(TAG, "updateUiTranslationState state: " + stateToString(state)
+ (DEBUG ? (", views: " + views + ", spec: " + uiTranslationSpec) : ""));
synchronized (mLock) {
@@ -344,10 +343,8 @@
*/
private void onVirtualViewTranslationCompleted(
SparseArray<LongSparseArray<ViewTranslationResponse>> translatedResult) {
- if (!mActivity.isResumed()) {
- if (DEBUG) {
- Log.v(TAG, "onTranslationCompleted: Activity is not resumed.");
- }
+ if (mActivity.isDestroyed()) {
+ Log.v(TAG, "onTranslationCompleted:" + mActivity + "is destroyed.");
return;
}
synchronized (mLock) {
@@ -395,10 +392,8 @@
* The method is used to handle the translation result for non-vertual views.
*/
private void onTranslationCompleted(SparseArray<ViewTranslationResponse> translatedResult) {
- if (!mActivity.isResumed()) {
- if (DEBUG) {
- Log.v(TAG, "onTranslationCompleted: Activity is not resumed.");
- }
+ if (mActivity.isDestroyed()) {
+ Log.v(TAG, "onTranslationCompleted:" + mActivity + "is destroyed.");
return;
}
final int resultCount = translatedResult.size();
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index 387837d..9d6488d 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -512,17 +512,16 @@
* @param fragmentToken2 client assigned unique token to create TaskFragment with specified
* in {@link TaskFragmentCreationParams#getFragmentToken()}. If it is
* {@code null}, the transaction will reset the adjacent TaskFragment.
- * @hide
*/
@NonNull
public WindowContainerTransaction setAdjacentTaskFragments(
@NonNull IBinder fragmentToken1, @Nullable IBinder fragmentToken2,
- @Nullable TaskFragmentAdjacentOptions options) {
+ @Nullable TaskFragmentAdjacentParams params) {
final HierarchyOp hierarchyOp =
new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS)
.setContainer(fragmentToken1)
.setReparentContainer(fragmentToken2)
- .setLaunchOptions(options != null ? options.toBundle() : null)
+ .setLaunchOptions(params != null ? params.toBundle() : null)
.build();
mHierarchyOps.add(hierarchyOp);
return this;
@@ -1304,9 +1303,8 @@
/**
* Helper class for building an options Bundle that can be used to set adjacent rules of
* TaskFragments.
- * @hide
*/
- public static class TaskFragmentAdjacentOptions {
+ public static class TaskFragmentAdjacentParams {
private static final String DELAY_PRIMARY_LAST_ACTIVITY_REMOVAL =
"android:transaction.adjacent.option.delay_primary_removal";
private static final String DELAY_SECONDARY_LAST_ACTIVITY_REMOVAL =
@@ -1315,29 +1313,43 @@
private boolean mDelayPrimaryLastActivityRemoval;
private boolean mDelaySecondaryLastActivityRemoval;
- public TaskFragmentAdjacentOptions() {
+ public TaskFragmentAdjacentParams() {
}
- public TaskFragmentAdjacentOptions(@NonNull Bundle bundle) {
+ public TaskFragmentAdjacentParams(@NonNull Bundle bundle) {
mDelayPrimaryLastActivityRemoval = bundle.getBoolean(
DELAY_PRIMARY_LAST_ACTIVITY_REMOVAL);
mDelaySecondaryLastActivityRemoval = bundle.getBoolean(
DELAY_SECONDARY_LAST_ACTIVITY_REMOVAL);
}
- public void setDelayPrimaryLastActivityRemoval(boolean delay) {
+ /** @see #shouldDelayPrimaryLastActivityRemoval() */
+ public void setShouldDelayPrimaryLastActivityRemoval(boolean delay) {
mDelayPrimaryLastActivityRemoval = delay;
}
- public void setDelaySecondaryLastActivityRemoval(boolean delay) {
+ /** @see #shouldDelaySecondaryLastActivityRemoval() */
+ public void setShouldDelaySecondaryLastActivityRemoval(boolean delay) {
mDelaySecondaryLastActivityRemoval = delay;
}
- public boolean isDelayPrimaryLastActivityRemoval() {
+ /**
+ * Whether to delay the last activity of the primary adjacent TaskFragment being immediately
+ * removed while finishing.
+ * <p>
+ * It is usually set to {@code true} to give organizer an opportunity to perform other
+ * actions or animations. An example is to finish together with the adjacent TaskFragment.
+ * </p>
+ */
+ public boolean shouldDelayPrimaryLastActivityRemoval() {
return mDelayPrimaryLastActivityRemoval;
}
- public boolean isDelaySecondaryLastActivityRemoval() {
+ /**
+ * Similar to {@link #shouldDelayPrimaryLastActivityRemoval()}, but for the secondary
+ * TaskFragment.
+ */
+ public boolean shouldDelaySecondaryLastActivityRemoval() {
return mDelaySecondaryLastActivityRemoval;
}
diff --git a/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java b/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java
index 0b92b93..874e3f4 100644
--- a/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java
+++ b/core/java/com/android/internal/accessibility/dialog/AccessibilityShortcutChooserActivity.java
@@ -47,6 +47,8 @@
public class AccessibilityShortcutChooserActivity extends Activity {
@ShortcutType
private final int mShortcutType = ACCESSIBILITY_SHORTCUT_KEY;
+ private static final String KEY_ACCESSIBILITY_SHORTCUT_MENU_MODE =
+ "accessibility_shortcut_menu_mode";
private final List<AccessibilityTarget> mTargets = new ArrayList<>();
private AlertDialog mMenuDialog;
private AlertDialog mPermissionDialog;
@@ -66,14 +68,30 @@
mMenuDialog = createMenuDialog();
mMenuDialog.setOnShowListener(dialog -> updateDialogListeners());
mMenuDialog.show();
+
+ if (savedInstanceState != null) {
+ final int restoreShortcutMenuMode =
+ savedInstanceState.getInt(KEY_ACCESSIBILITY_SHORTCUT_MENU_MODE,
+ ShortcutMenuMode.LAUNCH);
+ if (restoreShortcutMenuMode == ShortcutMenuMode.EDIT) {
+ onEditButtonClicked();
+ }
+ }
}
@Override
protected void onDestroy() {
+ mMenuDialog.setOnDismissListener(null);
mMenuDialog.dismiss();
super.onDestroy();
}
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(KEY_ACCESSIBILITY_SHORTCUT_MENU_MODE, mTargetAdapter.getShortcutMenuMode());
+ }
+
private void onTargetSelected(AdapterView<?> parent, View view, int position, long id) {
final AccessibilityTarget target = mTargets.get(position);
target.onSelected();
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index 7d2cb50..41efe28 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -838,6 +838,12 @@
// check if subLabel matches label before final display
return mRi.loadLabel(mPm).toString();
}
+
+ @Override
+ String getAppLabelForSubstitutePermission() {
+ // Will default to app name if no activity label set
+ return mRi.getComponentInfo().loadLabel(mPm).toString();
+ }
}
/**
@@ -877,6 +883,11 @@
// matches label before final display
return (String) mActivityInfo.loadLabel(mPm);
}
+
+ @Override
+ String getAppLabelForSubstitutePermission() {
+ return getAppSubLabelInternal();
+ }
}
/**
@@ -889,6 +900,7 @@
private abstract static class TargetPresentationGetter {
@Nullable abstract Drawable getIconSubstituteInternal();
@Nullable abstract String getAppSubLabelInternal();
+ @Nullable abstract String getAppLabelForSubstitutePermission();
private Context mCtx;
private final int mIconDpi;
@@ -940,9 +952,10 @@
public String getLabel() {
String label = null;
- // Apps with the substitute permission will always show the sublabel as their label
+ // Apps with the substitute permission will always show the activity label as the
+ // app label if provided
if (mHasSubstitutePermission) {
- label = getAppSubLabelInternal();
+ label = getAppLabelForSubstitutePermission();
}
if (label == null) {
@@ -953,8 +966,17 @@
}
public String getSubLabel() {
- // Apps with the substitute permission will never have a sublabel
- if (mHasSubstitutePermission) return null;
+ // Apps with the substitute permission will always show the resolve info label as the
+ // sublabel if provided
+ if (mHasSubstitutePermission){
+ String appSubLabel = getAppSubLabelInternal();
+ // Use the resolve info label as sublabel if it is set
+ if(!TextUtils.isEmpty(appSubLabel)
+ && !TextUtils.equals(appSubLabel, getLabel())){
+ return appSubLabel;
+ }
+ return null;
+ }
return getAppSubLabelInternal();
}
diff --git a/core/java/com/android/internal/inputmethod/IInputContextInvoker.java b/core/java/com/android/internal/inputmethod/IInputContextInvoker.java
index 0cbdc13..2fde981 100644
--- a/core/java/com/android/internal/inputmethod/IInputContextInvoker.java
+++ b/core/java/com/android/internal/inputmethod/IInputContextInvoker.java
@@ -477,15 +477,16 @@
* Invokes {@link IInputContext#requestCursorUpdates(int, IIntResultCallback)}.
*
* @param cursorUpdateMode {@code cursorUpdateMode} parameter to be passed.
+ * @param imeDisplayId the display ID that is associated with the IME.
* @return {@link AndroidFuture<Boolean>} that can be used to retrieve the invocation
* result. {@link RemoteException} will be treated as an error.
*/
@AnyThread
@NonNull
- public AndroidFuture<Boolean> requestCursorUpdates(int cursorUpdateMode) {
+ public AndroidFuture<Boolean> requestCursorUpdates(int cursorUpdateMode, int imeDisplayId) {
final AndroidFuture<Boolean> future = new AndroidFuture<>();
try {
- mIInputContext.requestCursorUpdates(cursorUpdateMode, future);
+ mIInputContext.requestCursorUpdates(cursorUpdateMode, imeDisplayId, future);
} catch (RemoteException e) {
future.completeExceptionally(e);
}
diff --git a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
index 662bd28..c2e5636 100644
--- a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
+++ b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java
@@ -567,13 +567,18 @@
}
@Override
- public void requestCursorUpdates(int cursorUpdateMode, AndroidFuture future /* T=Boolean */) {
+ public void requestCursorUpdates(int cursorUpdateMode, int imeDisplayId,
+ AndroidFuture future /* T=Boolean */) {
dispatchWithTracing("requestCursorUpdates", future, () -> {
final InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
return false;
}
+ if (mParentInputMethodManager.getDisplayId() != imeDisplayId) {
+ // requestCursorUpdates() is not currently supported across displays.
+ return false;
+ }
return ic.requestCursorUpdates(cursorUpdateMode);
});
}
diff --git a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
index fc0ce6f..31952eb 100644
--- a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
+++ b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
@@ -24,6 +24,8 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import dalvik.annotation.optimization.CriticalNative;
+
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -248,6 +250,32 @@
}
public native long[] readBpfData(int uid);
+
+ /**
+ * Reads CPU time-in-state data for the specified UID and adds the delta since the
+ * previous call to the current state stats in the LongArrayMultiStateCounter.
+ */
+ public boolean addDelta(int uid, LongArrayMultiStateCounter counter, long timestampMs) {
+ return addDeltaFromBpf(uid, counter.mNativeObject, timestampMs);
+ }
+
+ @CriticalNative
+ private static native boolean addDeltaFromBpf(int uid,
+ long longArrayMultiStateCounterNativePointer, long timestampMs);
+
+ /**
+ * Used for testing.
+ *
+ * Takes mock cpu-time-in-frequency data and uses it the same way eBPF data would be used.
+ */
+ public boolean addDeltaForTest(int uid, LongArrayMultiStateCounter counter,
+ long timestampMs, long[][] timeInFreqDataNanos) {
+ return addDeltaForTest(uid, counter.mNativeObject, timestampMs, timeInFreqDataNanos);
+ }
+
+ private static native boolean addDeltaForTest(int uid,
+ long longArrayMultiStateCounterNativePointer, long timestampMs,
+ long[][] timeInFreqDataNanos);
}
@VisibleForTesting
diff --git a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
index 1a3b29d..46e6ba0 100644
--- a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
@@ -31,7 +31,7 @@
* // At 1000 ms, the state changes to 1
* counter.setState(1, 1000);
*
- * // At 3000 ms, the tracked values are updated to {100, 200}
+ * // At 3000 ms, the tracked values are updated to {30, 300}
* arrayContainer.setValues(new long[]{{30, 300}};
* counter.updateValues(arrayContainer, 3000);
*
@@ -107,7 +107,10 @@
private final int mStateCount;
private final int mLength;
- private final long mNativeObject;
+
+ // Visible to other objects in this package so that it can be passed to @CriticalNative
+ // methods.
+ final long mNativeObject;
public LongArrayMultiStateCounter(int stateCount, int arrayLength, int initialState,
long timestampMs) {
diff --git a/core/java/com/android/internal/os/OWNERS b/core/java/com/android/internal/os/OWNERS
index ea3b3a7..7766b77 100644
--- a/core/java/com/android/internal/os/OWNERS
+++ b/core/java/com/android/internal/os/OWNERS
@@ -10,4 +10,6 @@
per-file *ChargeCalculator* = file:/BATTERY_STATS_OWNERS
per-file *PowerCalculator* = file:/BATTERY_STATS_OWNERS
per-file *PowerEstimator* = file:/BATTERY_STATS_OWNERS
+per-file *Kernel* = file:/BATTERY_STATS_OWNERS
+per-file *MultiState* = file:/BATTERY_STATS_OWNERS
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index c6fd6ee..9bdcddf 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -891,4 +891,18 @@
public static @Nullable <T> T firstOrNull(T[] items) {
return items.length > 0 ? items[0] : null;
}
+
+ /**
+ * Creates a {@link List} from an array. Different from {@link Arrays#asList(Object[])} as that
+ * will use the parameter as the backing array, meaning changes are not isolated.
+ */
+ public static <T> List<T> toList(T[] array) {
+ List<T> list = new ArrayList<>(array.length);
+ //noinspection ManualArrayToCollectionCopy
+ for (T item : array) {
+ //noinspection UseBulkOperation
+ list.add(item);
+ }
+ return list;
+ }
}
diff --git a/core/java/com/android/internal/util/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java
index c6a040c..b87027c 100644
--- a/core/java/com/android/internal/util/CollectionUtils.java
+++ b/core/java/com/android/internal/util/CollectionUtils.java
@@ -227,6 +227,13 @@
}
/**
+ * Returns whether the given map {@link Map#isEmpty is empty} or {@code null}
+ */
+ public static boolean isEmpty(@Nullable Map<?, ?> cur) {
+ return size(cur) == 0;
+ }
+
+ /**
* Returns the elements of the given list that are of type {@code c}
*/
public static @NonNull <T> List<T> filter(@Nullable List<?> list, Class<T> c) {
diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl
index 12a98c1..2e6f9e5 100644
--- a/core/java/com/android/internal/view/IInputContext.aidl
+++ b/core/java/com/android/internal/view/IInputContext.aidl
@@ -75,7 +75,8 @@
void getSelectedText(int flags, in AndroidFuture future /* T=CharSequence */);
- void requestCursorUpdates(int cursorUpdateMode, in AndroidFuture future /* T=Boolean */);
+ void requestCursorUpdates(int cursorUpdateMode, int imeDisplayId,
+ in AndroidFuture future /* T=Boolean */);
void commitContent(in InputContentInfo inputContentInfo, int flags, in Bundle opts,
in AndroidFuture future /* T=Boolean */);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index dbf4528..5a03277 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -17,6 +17,7 @@
package com.android.internal.widget;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
@@ -1264,6 +1265,14 @@
}
/**
+ * Whether the user is not allowed to set any credentials via PASSWORD_QUALITY_MANAGED.
+ */
+ public boolean isCredentialsDisabledForUser(int userId) {
+ return getDevicePolicyManager().getPasswordQuality(/* admin= */ null, userId)
+ == PASSWORD_QUALITY_MANAGED;
+ }
+
+ /**
* @see StrongAuthTracker#isTrustAllowedForUser
*/
public boolean isTrustAllowedForUser(int userId) {
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 4bee976..6cea8bf 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -76,3 +76,7 @@
# VINTF
per-file android_os_VintfObject* = file:platform/system/libvintf:/OWNERS
per-file android_os_VintfRuntimeInfo* = file:platform/system/libvintf:/OWNERS
+
+# Battery
+per-file com_android_internal_os_Kernel* = file:/BATTERY_STATS_OWNERS
+per-file com_android_internal_os_*MultiStateCounter* = file:/BATTERY_STATS_OWNERS
diff --git a/core/jni/com_android_internal_os_KernelSingleUidTimeReader.cpp b/core/jni/com_android_internal_os_KernelSingleUidTimeReader.cpp
index c0ecf33..689b259 100644
--- a/core/jni/com_android_internal_os_KernelSingleUidTimeReader.cpp
+++ b/core/jni/com_android_internal_os_KernelSingleUidTimeReader.cpp
@@ -14,9 +14,11 @@
* limitations under the License.
*/
-#include "core_jni_helpers.h"
-
#include <cputimeinstate.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+
+#include "LongArrayMultiStateCounter.h"
+#include "core_jni_helpers.h"
namespace android {
@@ -42,8 +44,70 @@
return copyVecsToArray(env, out.value());
}
+/**
+ * Computes delta of CPU time-in-freq from the previously supplied counts and adds the delta
+ * to the supplied multi-state counter in accordance with the counter's state.
+ */
+static jboolean addCpuTimeInFreqDelta(
+ jint uid, jlong counterNativePtr, jlong timestampMs,
+ std::optional<std::vector<std::vector<uint64_t>>> timeInFreqDataNanos) {
+ if (!timeInFreqDataNanos) {
+ return false;
+ }
+
+ battery::LongArrayMultiStateCounter *counter =
+ reinterpret_cast<battery::LongArrayMultiStateCounter *>(counterNativePtr);
+ size_t s = 0;
+ for (const auto &cluster : *timeInFreqDataNanos) s += cluster.size();
+
+ std::vector<uint64_t> flattened;
+ flattened.reserve(s);
+ auto offset = flattened.begin();
+ for (const auto &cluster : *timeInFreqDataNanos) {
+ flattened.insert(offset, cluster.begin(), cluster.end());
+ offset += cluster.size();
+ }
+ for (size_t i = 0; i < s; ++i) {
+ flattened[i] /= NSEC_PER_MSEC;
+ }
+ counter->updateValue(flattened, timestampMs);
+ return true;
+}
+
+static jboolean addDeltaFromBpf(jint uid, jlong counterNativePtr, jlong timestampMs) {
+ return addCpuTimeInFreqDelta(uid, counterNativePtr, timestampMs,
+ android::bpf::getUidCpuFreqTimes(uid));
+}
+
+static jboolean addDeltaForTest(JNIEnv *env, jclass, jint uid, jlong counterNativePtr,
+ jlong timestampMs, jobjectArray timeInFreqDataNanos) {
+ if (!timeInFreqDataNanos) {
+ return addCpuTimeInFreqDelta(uid, counterNativePtr, timestampMs,
+ std::optional<std::vector<std::vector<uint64_t>>>());
+ }
+
+ std::vector<std::vector<uint64_t>> timeInFreqData;
+ jsize len = env->GetArrayLength(timeInFreqDataNanos);
+ for (jsize i = 0; i < len; i++) {
+ std::vector<uint64_t> cluster;
+ ScopedLongArrayRO row(env, (jlongArray)env->GetObjectArrayElement(timeInFreqDataNanos, i));
+ cluster.reserve(row.size());
+ for (size_t j = 0; j < row.size(); j++) {
+ cluster.push_back(row[j]);
+ }
+ timeInFreqData.push_back(cluster);
+ }
+ return addCpuTimeInFreqDelta(uid, counterNativePtr, timestampMs, std::optional(timeInFreqData));
+}
+
static const JNINativeMethod g_single_methods[] = {
- {"readBpfData", "(I)[J", (void *)getUidCpuFreqTimeMs},
+ {"readBpfData", "(I)[J", (void *)getUidCpuFreqTimeMs},
+
+ // @CriticalNative
+ {"addDeltaFromBpf", "(IJJ)Z", (void *)addDeltaFromBpf},
+
+ // Used for testing
+ {"addDeltaForTest", "(IJJ[[J)Z", (void *)addDeltaForTest},
};
int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *env) {
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 4af9d75..8e33561 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -211,6 +211,8 @@
optional DisplayRotationProto display_rotation = 33;
optional int32 ime_policy = 34;
+
+ repeated InsetsSourceProviderProto insets_source_providers = 35;
}
/* represents DisplayArea object */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8c28aec..e655fab 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -201,6 +201,9 @@
android:name="android.bluetooth.hearingaid.profile.action.PLAYING_STATE_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.CSIS_CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.CSIS_DEVICE_AVAILABLE" />
+ <protected-broadcast android:name="android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE" />
<protected-broadcast
android:name="android.bluetooth.volume-control.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
@@ -5884,7 +5887,6 @@
android:excludeFromRecents="true"
android:documentLaunchMode="never"
android:relinquishTaskIdentity="true"
- android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
android:process=":ui"
android:visibleToInstantApps="true">
<intent-filter>
diff --git a/core/res/res/layout/accessibility_shortcut_chooser_item.xml b/core/res/res/layout/accessibility_shortcut_chooser_item.xml
index 7cca129..4d7946b 100644
--- a/core/res/res/layout/accessibility_shortcut_chooser_item.xml
+++ b/core/res/res/layout/accessibility_shortcut_chooser_item.xml
@@ -39,15 +39,20 @@
android:layout_height="48dp"
android:scaleType="fitCenter"/>
- <TextView
- android:id="@+id/accessibility_shortcut_target_label"
+ <LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
- android:layout_weight="1"
- android:textSize="20sp"
- android:textColor="?attr/textColorPrimary"
- android:fontFamily="sans-serif-medium"/>
+ android:layout_weight="1">
+
+ <TextView
+ android:id="@+id/accessibility_shortcut_target_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="20sp"
+ android:textColor="?attr/textColorPrimary"
+ android:fontFamily="sans-serif-medium"/>
+ </LinearLayout>
<TextView
android:id="@+id/accessibility_shortcut_target_status"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 3666f48..bf8180b 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gebruik jou vingerafdruk of skermslot om voort te gaan"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Iets is fout. Probeer weer."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Vingerafdrukikoon"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Gesigslot"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Kwessie met Gesigslot"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gebruik jou gesig of skermslot om voort te gaan"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Iets is fout. Probeer weer."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Gesig-ikoon"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"lees sinkroniseer-instellings"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Laat die program toe om die sinkroniseringinstellings van \'n rekening te lees. Byvoorbeeld, dit kan bepaal of die People-program met \'n rekening gesinkroniseer is."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Wanneer die kortpad aan is, sal \'n toeganklikheidkenmerk begin word as albei volumeknoppies 3 sekondes lank gedruk word."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Skakel kortpad vir toeganklikheidskenmerke aan?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"As jy albei volumesleutels vir \'n paar sekondes hou, skakel dit toeganklikheidkenmerke aan. Dit kan verander hoe jou toestel werk.\n\nHuidige kenmerke:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nJy kan geselekteerde kenmerke in Instellings en Toeganklikheid verander."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Skakel <xliff:g id="SERVICE">%1$s</xliff:g>-kortpad aan?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"As jy albei volumesleutels vir \'n paar sekondes hou, skakel dit <xliff:g id="SERVICE">%1$s</xliff:g>, \'n toeganklikheidkenmerk, aan. Dit kan verander hoe jou toestel werk.\n\nJy kan hierdie kortpad na \'n ander kenmerk in Instellings en Toeganklikheid verander."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Skakel aan"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index fb4669c..8f84dd2 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ለመቀጠል የጣት አሻራዎን ወይም የማያ ገጽ ቁልፍዎን ይጠቀሙ"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"የሆነ ችግር ተፈጥሯል። እንደገና ይሞክሩ።"</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"የጣት አሻራ አዶ"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"በመልክ መክፈት"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ከመልክ መክፈት ጋር በተያያዘ ችግር"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ለመቀጠል መልክዎን ወይም የማያ ገጽዎን መቆለፊያ ይጠቀሙ"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"የሆነ ችግር ተፈጥሯል። እንደገና ይሞክሩ።"</string>
<string name="face_icon_content_description" msgid="465030547475916280">"የፊት አዶ"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"የሥምሪያ ቅንብሮች አንብብ"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"መተግበሪያው የአንድ መለያ የማመሳሰል ቅንብሮችን እንዲያነብ ይፈቅድለታል። ለምሳሌ ይህ የሰዎች መተግበሪያ ከመለያ ጋር መመሳሰሉን አለመመሳሰሉን ሊወስን ይችላል።"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"አቋራጩ ሲበራ ሁለቱንም የድምጽ አዝራሮች ለ3 ሰከንዶች ተጭኖ መቆየት የተደራሽነት ባህሪን ያስጀምረዋል።"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"የተደራሽነት ባህሪዎች አቋራጭ ይብራ?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ሁለቱንም የድምፅ ቁልፎች ወደ ታች ለጥቂት ሰከንዶች መያዝ የተደራሽነት ባሕሪያትን ያበራል። ይህ የእርስዎ መሣሪያ እንዴት እንደሚሠራ ሊለውጥ ይችላል።\n\nየአሁን ባሕሪያት፦\n<xliff:g id="SERVICE">%1$s</xliff:g>\nበቅንብሮች > ተደራሽነት ውስጥ የተመረጡትን ባሕሪያት መለወጥ ይችላሉ።"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"የ<xliff:g id="SERVICE">%1$s</xliff:g> አቋራጭ ይብራ?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ሁለቱንም የድምፅ ቁልፎች ወደ ታች ለጥቂት ሰከንዶች መያዝ የተደራሽነት ባሕሪያትን <xliff:g id="SERVICE">%1$s</xliff:g> ያበራል። ይህ የእርስዎ መሣሪያ እንዴት እንደሚሠራ ሊለውጥ ይችላል።\n\nበቅንብሮች > ተደራሽነት ውስጥ ወደ ሌላ ባሕሪ ይህን አቋራጭ መለወጥ ይችላሉ።"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"አብራ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index a7aefa7..54821d8 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -621,8 +621,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"استخدام بصمة الإصبع أو قفل الشاشة للمتابعة"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"حدث خطأ، يُرجى إعادة المحاولة."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"رمز بصمة الإصبع"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"فتح الجهاز بالتعرف على الوجه"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"مشكلة متعلّقة بميزة \"فتح الجهاز بالتعرف على الوجه\""</string>
@@ -675,8 +674,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"استخدام ميزة \"فتح القفل بالوجه\" أو ميزة \"قفل الشاشة\" للمتابعة"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"حدث خطأ، يُرجى إعادة المحاولة."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"رمز الوجه"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"قراءة إعدادات المزامنة"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"للسماح للتطبيق بقراءة الإعدادات المتزامنة لحساب ما. على سبيل المثال، يمكن أن يؤدي هذا إلى تحديد ما إذا تمت مزامنة تطبيق \"الأشخاص\" مع حساب ما."</string>
@@ -1784,8 +1782,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"عند تفعيل الاختصار، يؤدي الضغط على زرّي التحكّم في مستوى الصوت معًا لمدة 3 ثوانٍ إلى تفعيل إحدى ميزات إمكانية الوصول."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"هل تريد تفعيل الاختصار لميزات إمكانية الوصول؟"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"يؤدي الضغط مع الاستمرار على كلا مفتاحَي التحكّم في مستوى الصوت لبضع ثوانٍ إلى تفعيل ميزات إمكانية الوصول. قد يؤدي هذا الإجراء إلى تغيير طريقة عمل جهازك.\n\nالميزات الحالية:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nيمكنك تغيير الميزات المحددة في الإعدادات > إمكانية الوصول."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"هل تريد تفعيل اختصار <xliff:g id="SERVICE">%1$s</xliff:g>؟"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"يؤدي الضغط مع الاستمرار لبضع ثوانٍ على كلا مفتاحَي التحكّم في مستوى الصوت إلى تفعيل <xliff:g id="SERVICE">%1$s</xliff:g> وهي إحدى ميزات إمكانية الوصول. يمكن أن يؤدي هذا الإجراء إلى تغيير كيفية عمل جهازك.\n\nيمكنك تغيير هذا الاختصار لاستخدامه مع ميزة أخرى في الإعدادات > أدوات تمكين الوصول."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"تفعيل"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 7ea0542..456bcf7 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -242,7 +242,7 @@
<string name="global_actions" product="tablet" msgid="4412132498517933867">"টে\'বলেটৰ বিকল্পসমূহ"</string>
<string name="global_actions" product="tv" msgid="3871763739487450369">"Android TVৰ বিকল্পসমূহ"</string>
<string name="global_actions" product="default" msgid="6410072189971495460">"ফ\'নৰ বিকল্পসমূহ"</string>
- <string name="global_action_lock" msgid="6949357274257655383">"স্ক্ৰীণ ল\'ক"</string>
+ <string name="global_action_lock" msgid="6949357274257655383">"স্ক্ৰীন লক"</string>
<string name="global_action_power_off" msgid="4404936470711393203">"পাৱাৰ অফ"</string>
<string name="global_action_power_options" msgid="1185286119330160073">"পাৱাৰ"</string>
<string name="global_action_restart" msgid="4678451019561687074">"ৰিষ্টাৰ্ট কৰক"</string>
@@ -329,7 +329,7 @@
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"ৱিণ্ড’ সমল বিচাৰি উলিওৱাৰ"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"আপুনি চাই থকা ৱিণ্ড’খনৰ সমল পৰীক্ষা কৰাৰ।"</string>
<string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"স্পৰ্শৰ দ্বাৰা অন্বেষণ কৰাৰ সুবিধা অন কৰাৰ"</string>
- <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"আঙুলিৰে টিপা বস্তুসমূহ ডাঙৰকৈ কৈ শুনোৱা হ’ব আৰু আঙুলিৰ স্পৰ্শেৰে নিৰ্দেশ দি স্ক্ৰীণ অন্বেষণ কৰিব পাৰিব।"</string>
+ <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"আঙুলিৰে টিপা বস্তুসমূহ ডাঙৰকৈ কৈ শুনোৱা হ’ব আৰু আঙুলিৰ স্পৰ্শেৰে নিৰ্দেশ দি স্ক্ৰীন অন্বেষণ কৰিব পাৰিব।"</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"আপুনি লিখা পাঠ নিৰীক্ষণ কৰাৰ"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"ক্ৰেডিট কাৰ্ডৰ নম্বৰ আৰু পাছৱৰ্ডৰ দৰে ব্যক্তিগত ডেটা ইয়াত অন্তৰ্ভুক্ত।"</string>
<string name="capability_title_canControlMagnification" msgid="7701572187333415795">"ডিছপ্লে’ৰ বিবৰ্ধন নিয়ন্ত্ৰণ কৰাৰ"</string>
@@ -387,7 +387,7 @@
<string name="permlab_killBackgroundProcesses" msgid="6559320515561928348">"অন্য এপবোৰ বন্ধ কৰক"</string>
<string name="permdesc_killBackgroundProcesses" msgid="2357013583055434685">"এপটোক অন্য এপসমূহৰ নেপথ্যৰ প্ৰক্ৰিয়াসমূহ শেষ কৰিবলৈ অনুমতি দিয়ে৷ এই কার্যৰ বাবে অন্য এপসমূহ চলাটো বন্ধ হ\'ব পাৰে৷"</string>
<string name="permlab_systemAlertWindow" msgid="5757218350944719065">"এই এপটো অইন এপৰ ওপৰত প্ৰদৰ্শিত হ\'ব পাৰে"</string>
- <string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"এই এপটো অইন এপৰ ওপৰত বা স্ক্ৰীণৰ অইন অংশত প্ৰদৰ্শিত হ\'ব পাৰে। এই কাৰ্যই এপসমূহৰ স্বাভাৱিক কাৰ্যকলাপত ব্যাঘাত জন্মাব পাৰে আৰু অইন এপসমূহক স্ক্ৰীণত কেনেকৈ দেখা পোৱা যায় সেইটো সলনি কৰিব পাৰে।"</string>
+ <string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"এই এপ্টো অন্য এপৰ ওপৰত বা স্ক্ৰীনৰ অন্য অংশত প্ৰদৰ্শিত হ\'ব পাৰে। এই কাৰ্যই এপৰ স্বাভাৱিক ব্যৱহাৰত ব্যাঘাত জন্মাব পাৰে আৰু অন্য এপ্সমূহক স্ক্ৰীনত কেনেকৈ দেখা পোৱা যায় সেইটো সলনি কৰিব পাৰে।"</string>
<string name="permlab_runInBackground" msgid="541863968571682785">"নেপথ্যত চলিব পাৰে"</string>
<string name="permdesc_runInBackground" msgid="4344539472115495141">"এই এপটো নেপথ্যত চলিব পাৰে। ইয়াৰ ফলত বেটাৰি সোনকালে শেষ হ\'ব পাৰে।"</string>
<string name="permlab_useDataInBackground" msgid="783415807623038947">"নেপথ্যত ডেটা ব্যৱহাৰ কৰিব পাৰে"</string>
@@ -545,10 +545,10 @@
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"এপ্টোক অগ্ৰাধিকাৰ দিয়া nfc পৰিশোধ সেৱাৰ পঞ্জীকৃত সহায়কসমূহ আৰু পৰিশোধ কৰিব লগা লক্ষ্যস্থান দৰে তথ্য পাবলৈ অনুমতি দিয়ে।"</string>
<string name="permlab_nfc" msgid="1904455246837674977">"নিয়েৰ ফিল্ড কমিউনিকেশ্বন নিয়ন্ত্ৰণ কৰক"</string>
<string name="permdesc_nfc" msgid="8352737680695296741">"এপটোক নিয়েৰ ফিল্ড কমিউনিকেশ্বন (NFC) টেগ, কাৰ্ড আৰু ৰিডাৰসমূহৰ সৈতে যোগাযোগ কৰিবলৈ অনুমতি দিয়ে।"</string>
- <string name="permlab_disableKeyguard" msgid="3605253559020928505">"আপোনাৰ স্ক্ৰীণ ল\'ক অক্ষম কৰক"</string>
+ <string name="permlab_disableKeyguard" msgid="3605253559020928505">"আপোনাৰ স্ক্ৰীন লক অক্ষম কৰক"</string>
<string name="permdesc_disableKeyguard" msgid="3223710003098573038">"এপটোক কী ল\'ক আৰু জড়িত হোৱা যিকোনো পাছৱৰ্ডৰ সুৰক্ষা অক্ষম কৰিব দিয়ে৷ উদাহৰণস্বৰূপে, কোনো অন্তৰ্গামী ফ\'ন কল উঠোৱাৰ সময়ত ফ\'নটোৱে কী-লকটো অক্ষম কৰে, তাৰ পিছত কল শেষ হ\'লেই কী লকটো পুনৰ সক্ষম কৰে৷"</string>
<string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"স্ক্ৰীণ লকৰ জটিলতাৰ অনুৰোধ"</string>
- <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"এপটোক স্ক্ৰীণ লকৰ জটিলতাৰ স্তৰ (উচ্চ, মধ্যম, নিম্ন বা একেবাৰে নাই) শিকিবলৈ অনুমতি দিয়ে ই স্ক্ৰীণ লকৰ সম্ভাব্য দৈৰ্ঘ্য বা স্ক্ৰীণ লকৰ প্ৰকাৰ দৰ্শায়। লগতে এপটোৱে ব্যৱহাৰকাৰীক স্ক্ৰীণ লকটো এটা নিৰ্দিষ্ট স্তৰলৈ আপডে’ট কৰিবলৈ পৰামৰ্শ দিব পাৰে যিটো ব্যৱহাৰকাৰীয়ে অৱজ্ঞা কৰি পৰৱর্তী পৃষ্ঠালৈ যাব পাৰে। মনত ৰাখিব যে স্ক্ৰীণ লকটো সাধাৰণ পাঠ হিচাপে সঞ্চয় কৰা নহয় সেয়ে এপ্টোৱে সঠিক পাছৱৰ্ডটো জানিব নোৱাৰে।"</string>
+ <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"এপ্টোক স্ক্ৰীন লকৰ জটিলতাৰ স্তৰ (উচ্চ, মধ্যম, নিম্ন বা একেবাৰে নাই)ৰ বিষয়ে জানিবলৈ অনুমতি দিয়ে, যিয়ে স্ক্ৰীন লকৰ সম্ভাব্য দৈৰ্ঘ্য বা স্ক্ৰীন লকৰ প্ৰকাৰ দৰ্শায়। লগতে এপ্টোৱে ব্যৱহাৰকাৰীক স্ক্ৰীন লকটো এটা নিৰ্দিষ্ট স্তৰলৈ আপডে’ট কৰিবলৈ পৰামৰ্শ দিব পাৰে যিটো ব্যৱহাৰকাৰীয়ে অৱজ্ঞা কৰি পৰৱর্তী পৃষ্ঠালৈ যাব পাৰে। মনত ৰাখিব যে স্ক্ৰীন লকটো সাধাৰণ পাঠ হিচাপে ষ্ট\'ৰ কৰা নহয়; সেয়েহে, এপ্টোৱে সঠিক পাছৱৰ্ডটো জানিব নোৱাৰে।"</string>
<string name="permlab_useBiometric" msgid="6314741124749633786">"বায়োমেট্ৰিক হাৰ্ডৱেৰ ব্য়ৱহাৰ কৰক"</string>
<string name="permdesc_useBiometric" msgid="7502858732677143410">"বিশ্বাসযোগ্য়তা প্ৰমাণীকৰণৰ বাবে এপক বায়োমেট্ৰিক হাৰ্ডৱেৰ ব্য়ৱহাৰ কৰিবলৈ অনুমতি দিয়ে"</string>
<string name="permlab_manageFingerprint" msgid="7432667156322821178">"ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ পৰিচালনা কৰিব পাৰে"</string>
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"অব্যাহত ৰাখিবলৈ আপোনাৰ ফিংগাৰপ্ৰিণ্ট অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"কিবা ভুল হ’ল। পুনৰ চেষ্টা কৰক।"</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ফিংগাৰপ্ৰিণ্ট আইকন"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ফেচ আনলক"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ফেচ আনলক ব্যৱহাৰ কৰোঁতে সমস্যা হৈছে"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"অব্যাহত ৰাখিবলৈ আপোনাৰ মুখাৱয়ব অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰক"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"কিবা ভুল হ’ল। পুনৰ চেষ্টা কৰক।"</string>
<string name="face_icon_content_description" msgid="465030547475916280">"মুখমণ্ডলৰ আইকন"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"ছিংকৰ ছেটিংসমূহ পঢ়ক"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"একাউণ্টৰ ছিংক ছেটিংবোৰ পঢ়িবলৈ এপক অনুমতি দিয়ে। যেনে, People এপ কোনো একাউণ্টত ছিংক কৰা হৈছে নে নাই সেয়া নির্ধাৰণ কৰিব পাৰে।"</string>
@@ -684,8 +682,8 @@
<string name="permdesc_register_call_provider" msgid="4201429251459068613">"এপটোক নতুন টেলিকম সংযোগ পঞ্জীয়ন কৰিবলৈ অনুমতি দিয়ে।"</string>
<string name="permlab_connection_manager" msgid="3179365584691166915">"টেলিকম সংযোগ পৰিচালনা কৰা"</string>
<string name="permdesc_connection_manager" msgid="1426093604238937733">"এপটোক টেলিকম সংযোগ পৰিচালনা কৰিবলৈ অনুমতি দিয়ে।"</string>
- <string name="permlab_bind_incall_service" msgid="5990625112603493016">"ইন-কল স্ক্ৰীণৰ সৈতে সংযোগ স্থাপন"</string>
- <string name="permdesc_bind_incall_service" msgid="4124917526967765162">"ব্যৱহাৰকাৰীয়ে কেতিয়া আৰু কেনেদৰে ইন-কল-স্ক্ৰীণ চাব, তাক নিয়ন্ত্ৰণ কৰিবলৈ এপক অনুমতি দিয়ে।"</string>
+ <string name="permlab_bind_incall_service" msgid="5990625112603493016">"ইন-কল স্ক্ৰীনৰ সৈতে সংযোগ স্থাপন"</string>
+ <string name="permdesc_bind_incall_service" msgid="4124917526967765162">"ব্যৱহাৰকাৰীগৰাকীয়ে কেতিয়া আৰু কেনেদৰে ইন-কল-স্ক্ৰীন চায় সেয়া নিয়ন্ত্ৰণ কৰিবলৈ এপ্টোক অনুমতি দিয়ে।"</string>
<string name="permlab_bind_connection_service" msgid="5409268245525024736">"টেলিফ\'নী সেৱাসমূহৰ সৈতে সংযোগ স্থাপন"</string>
<string name="permdesc_bind_connection_service" msgid="6261796725253264518">"কল কৰিবলৈ/লাভ কৰিবলৈ টেলিফ\'নী সেৱাসমূহৰ সৈতে এপক সংযোগ স্থাপনৰ বাবে অনুমতি দিয়ে।"</string>
<string name="permlab_control_incall_experience" msgid="6436863486094352987">"ইন-কল ব্যৱহাৰকাৰীৰ অভিজ্ঞতা প্ৰদান কৰা"</string>
@@ -709,7 +707,7 @@
<string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"নেটৱৰ্ক অৱস্থাসমূহৰ ওপৰত নিৰীক্ষণৰ বাবে শুনিব পাৰে"</string>
<string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"এটা এপ্লিকেশ্বনক নেটৱৰ্ক অৱস্থাসমূহত নিৰীক্ষণৰ বাবে শুনিবলৈ অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে সাধাৰণতে প্ৰয়োজন নহয়।"</string>
<string name="permlab_setInputCalibration" msgid="932069700285223434">"ইনপুট ডিভাইচ কেলিব্ৰেশ্বন সলনি কৰিব পাৰে"</string>
- <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"টাচ্চ স্ক্ৰীণৰ কেলিব্ৰেশ্বন পেৰামিটাৰ সংশোধন কৰিবলৈ এপক অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে সাধাৰণতে প্ৰয়োজন নহয়।"</string>
+ <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"টাচ্চ স্ক্ৰীনৰ কেলিব্ৰেশ্বন পেৰামিটাৰ সংশোধন কৰিবলৈ এপক অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে কেতিয়াও প্ৰয়োজন হোৱা উচিত নহয়।"</string>
<string name="permlab_accessDrmCertificates" msgid="6473765454472436597">"DRM প্ৰমাণপত্ৰসমূহলৈ প্ৰৱেশ"</string>
<string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"এটা এপ্লিকেশ্বনক DRM প্ৰমাণপত্ৰ গোটাবলৈ আৰু ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়ে। সাধাৰণ এপসমূহৰ বাবে সাধাৰণতে প্ৰয়োজন নহয়।"</string>
<string name="permlab_handoverStatus" msgid="7620438488137057281">"Android বীম স্থানান্তৰণৰ স্থিতি লাভ কৰিব পাৰে"</string>
@@ -727,18 +725,18 @@
<string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"এটা উচ্চ ছেম্পলিঙৰ হাৰত ছেন্সৰৰ ডেটা এক্সেছ কৰে"</string>
<string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"এপ্টোক ২০০ হাৰ্টজতকৈ অধিক হাৰত ছেন্সৰৰ ডেটাৰ নমুনা ল’বলৈ অনুমতি দিয়ে"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"পাছৱর্ডৰ নিয়ম ছেট কৰক"</string>
- <string name="policydesc_limitPassword" msgid="4105491021115793793">"স্ক্ৰীণ লক পাছৱৰ্ড আৰু পিনৰ দৈর্ঘ্য আৰু কি কি আখৰ ব্যৱহাৰ কৰিব পাৰে তাক নিয়ন্ত্ৰণ কৰক।"</string>
- <string name="policylab_watchLogin" msgid="7599669460083719504">"স্ক্ৰীণ আনলক কৰা প্ৰয়াসবোৰ পৰ্যবেক্ষণ কৰিব পাৰে"</string>
+ <string name="policydesc_limitPassword" msgid="4105491021115793793">"স্ক্ৰীন লক পাছৱৰ্ড আৰু পিনত অনুমোদিত দৈৰ্ঘ্য আৰু বৰ্ণবোৰ নিয়ন্ত্ৰণ কৰক।।"</string>
+ <string name="policylab_watchLogin" msgid="7599669460083719504">"স্ক্ৰীন আনলক কৰা প্ৰয়াসবোৰ নিৰীক্ষণ কৰক"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"স্ক্ৰীণ আনলক কৰোতে লিখা অশুদ্ধ পাছৱৰ্ডৰ হিচাপ ৰাখক, আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড লিখা হয় তেন্তে টে\'বলেটটো লক কৰক বা টে\'বলেটটোৰ সকলো ডেটা মোহাৰক।"</string>
<string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"স্ক্ৰীণ আনলক কৰোঁতে দিয়া ভুল পাছৱৰ্ডবোৰৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ ভুল পাছৱৰ্ড দিয়া হয় তেন্তে Android TV ডিভাইচটো লক কৰক অথবা আপোনাৰ Android TV ডিভাইচৰ সকলো ডেটা মচক।"</string>
<string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"স্ক্ৰীণ আনলক কৰোতে লিখা অশুদ্ধ পাছৱৰ্ডৰ হিচাপ ৰাখক, আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড লিখা হয় তেন্তে ফ\'নটো লক কৰক বা ফ\'নটোৰ সকলো ডেটা মোহাৰক।"</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"স্ক্ৰীণ আনলক কৰোতে লিখা অশুদ্ধ পাছৱৰ্ডৰ হিচাপ নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড দিয়া হয় তেন্তে টে\'বলেটটো লক কৰক বা এই ব্যৱহাৰকাৰীৰ সকলো ডেটা মচক।"</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"স্ক্ৰীণখন আনলক কৰোঁতে টাইপ কৰা ভুল পাছৱৰ্ডবোৰৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ ভুল পাছৱৰ্ড টাইপ কৰা হয় তেন্তে Android TV ডিভাইচটো লক কৰক অথবা এই ব্যৱহাৰকাৰীৰ সকলো ডেটা মচক।"</string>
- <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"স্ক্ৰীণ আনলক কৰোতে দিয়া অশুদ্ধ পাছৱৰ্ডৰ হিচাপ নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড দিয়া হয় তেন্তে ফ\'নটো লক কৰক বা এই ব্যৱহাৰকাৰীৰ সকলো ডেটা মচক।"</string>
- <string name="policylab_resetPassword" msgid="214556238645096520">"স্ক্ৰীণ লক সলনি কৰক"</string>
- <string name="policydesc_resetPassword" msgid="4626419138439341851">"স্ক্ৰীণ লক সলনি কৰক।"</string>
- <string name="policylab_forceLock" msgid="7360335502968476434">"স্ক্ৰীণখন লক কৰক"</string>
- <string name="policydesc_forceLock" msgid="1008844760853899693">"স্ক্ৰীণ কেনেকৈ আৰু কেতিয়া ল\'ক হ\'ব লাগে সেয়া নিয়ন্ত্ৰণ কৰক।"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"স্ক্ৰীন আনলক কৰোঁতে টাইপ কৰা অশুদ্ধ পাছৱৰ্ডৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে টেবলেটটো লক কৰক বা এই ব্যৱহাৰকাৰীৰ আটাইখিনি ডেটা মচক।"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"স্ক্ৰীনখন আনলক কৰোঁতে টাইপ কৰা ভুল পাছৱৰ্ডবোৰৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ ভুল পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে Android TV ডিভাইচটো লক কৰক অথবা এই ব্যৱহাৰকাৰীৰ আটাইখিনি ডেটা মচক।"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"স্ক্ৰীনখন আনলক কৰোঁতে টাইপ কৰা ভুল পাছৱৰ্ডবোৰৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ ভুল পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে ফ\'নটো লক কৰক অথবা এই ব্যৱহাৰকাৰীৰ আটাইখিনি ডেটা মচক।"</string>
+ <string name="policylab_resetPassword" msgid="214556238645096520">"স্ক্ৰীন লক সলনি কৰক"</string>
+ <string name="policydesc_resetPassword" msgid="4626419138439341851">"স্ক্ৰীন লক সলনি কৰক।"</string>
+ <string name="policylab_forceLock" msgid="7360335502968476434">"স্ক্ৰীনখন লক কৰক"</string>
+ <string name="policydesc_forceLock" msgid="1008844760853899693">"স্ক্ৰীন কেনেকৈ আৰু কেতিয়া লক হয় সেয়া নিয়ন্ত্ৰণ কৰক।"</string>
<string name="policylab_wipeData" msgid="1359485247727537311">"সকলো ডেটা মচক"</string>
<string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"সতৰ্কবাণী প্ৰেৰণ নকৰাকৈয়ে ফেক্টৰী ডেটা ৰিছেট কৰি টেবলেটৰ ডেটা মচক।"</string>
<string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"কোনো সতর্কবার্তা নপঠিওৱাকৈ ফেক্টৰী ডেটা ৰিছেট কৰি আপোনাৰ Android TV ডিভাইচৰ ডেটা মচক।"</string>
@@ -749,13 +747,13 @@
<string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"এই ফ\'নটোত থকা এই ব্যৱহাৰকাৰীৰ তথ্য কোনো সর্তকবাণী নিদিয়াকৈ মচি পেলাওক।"</string>
<string name="policylab_setGlobalProxy" msgid="215332221188670221">"ডিভাইচৰ বাবে গ্ল\'বেল প্ৰক্সী ছেট কৰক"</string>
<string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"নীতি সক্ষম কৰি থোৱা অৱস্থাত ব্য়ৱহাৰ কৰিবৰ বাবে ডিভাইচৰ বাবে গ্ল\'বেল প্ৰক্সী ছেট কৰক। কেৱল ডিভাইচৰ গৰাকীয়েহে গ্ল\'বেল প্ৰক্সী ছেট কৰিব পাৰে।"</string>
- <string name="policylab_expirePassword" msgid="6015404400532459169">"স্ক্ৰীণ লক পাছৱৰ্ডৰ ম্যাদ ওকলাৰ দিন ছেট কৰক"</string>
- <string name="policydesc_expirePassword" msgid="9136524319325960675">"স্ক্ৰীণ লকৰ পাছৱৰ্ড, পিন বা আর্হি কিমান ঘনাই সলনি কৰিব লাগিব তাক সলনি কৰক।"</string>
+ <string name="policylab_expirePassword" msgid="6015404400532459169">"স্ক্ৰীন লক পাছৱৰ্ডৰ ম্যাদ ওকলাৰ দিন ছেট কৰক"</string>
+ <string name="policydesc_expirePassword" msgid="9136524319325960675">"স্ক্ৰীন লকৰ পাছৱৰ্ড, পিন বা আর্হি কিমান ঘনাই সলনি কৰিব লাগিব তাক সলনি কৰক।"</string>
<string name="policylab_encryptedStorage" msgid="9012936958126670110">"সঞ্চয়াগাৰৰ এনক্ৰিপশ্বন ছেট কৰক"</string>
<string name="policydesc_encryptedStorage" msgid="1102516950740375617">"সঞ্চয় কৰি ৰখা ডেটাক এনক্ৰিপ্ট কৰাৰ প্ৰয়োজন।"</string>
<string name="policylab_disableCamera" msgid="5749486347810162018">"কেমেৰাবোৰ অক্ষম কৰক"</string>
<string name="policydesc_disableCamera" msgid="3204405908799676104">"সকলো ডিভাইচৰ কেমেৰাবোৰ ব্যৱহাৰ কৰাত বাধা দিয়ক।"</string>
- <string name="policylab_disableKeyguardFeatures" msgid="5071855750149949741">"স্ক্ৰীণ লকৰ কিছুমান সুবিধা অক্ষম কৰক"</string>
+ <string name="policylab_disableKeyguardFeatures" msgid="5071855750149949741">"স্ক্ৰীন লকৰ কিছুমান সুবিধা অক্ষম কৰক"</string>
<string name="policydesc_disableKeyguardFeatures" msgid="6641673177041195957">"স্ক্ৰীণ লকৰ কিছুমান সুবিধা ব্যৱহাৰ হোৱাত বাধা দিয়ক।"</string>
<string-array name="phoneTypes">
<item msgid="8996339953292723951">"ঘৰ"</item>
@@ -882,7 +880,7 @@
<string name="keyguard_label_text" msgid="3841953694564168384">"আনলক কৰিবলৈ মেনু টিপাৰ পিছত ০ টিপক।"</string>
<string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"জৰুৰীকালীন নম্বৰ"</string>
<string name="lockscreen_carrier_default" msgid="6192313772955399160">"কোনো সেৱা নাই"</string>
- <string name="lockscreen_screen_locked" msgid="7364905540516041817">"স্ক্ৰীণ লক কৰা হ’ল।"</string>
+ <string name="lockscreen_screen_locked" msgid="7364905540516041817">"স্ক্ৰীন লক কৰা হ’ল।"</string>
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"আনলক কৰিবলৈ বা জৰুৰীকালীন কল কৰিবলৈ মেনু টিপক।"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"আনলক কৰিবলৈ মেনু টিপক।"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"আনলক কৰিবলৈ আর্হি আঁকক"</string>
@@ -1396,7 +1394,7 @@
<string name="share_remote_bugreport_action" msgid="7630880678785123682">"শ্বেয়াৰ কৰক"</string>
<string name="decline_remote_bugreport_action" msgid="4040894777519784346">"প্ৰত্যাখ্যান কৰক"</string>
<string name="select_input_method" msgid="3971267998568587025">"ইনপুট পদ্ধতি বাছনি কৰক"</string>
- <string name="show_ime" msgid="6406112007347443383">"কায়িক কীব’ৰ্ড সক্ৰিয় হৈ থাকোঁতে ইয়াক স্ক্ৰীণত ৰাখিব"</string>
+ <string name="show_ime" msgid="6406112007347443383">"কায়িক কীব’ৰ্ড সক্ৰিয় হৈ থাকোঁতে ইয়াক স্ক্ৰীনত ৰাখক"</string>
<string name="hardware" msgid="1800597768237606953">"ভাৰ্শ্বুৱল কীব\'ৰ্ড দেখুৱাওক"</string>
<string name="select_keyboard_layout_notification_title" msgid="4427643867639774118">"কায়িক কীব’ৰ্ড কনফিগাৰ কৰক"</string>
<string name="select_keyboard_layout_notification_message" msgid="8835158247369158154">"ভাষা আৰু চানেকি বাছনি কৰিবলৈ ইয়াত টিপক"</string>
@@ -1634,7 +1632,7 @@
<string name="wireless_display_route_description" msgid="8297563323032966831">"ৱায়াৰলেচ ডিছপ্লে’"</string>
<string name="media_route_button_content_description" msgid="2299223698196869956">"কাষ্ট"</string>
<string name="media_route_chooser_title" msgid="6646594924991269208">"ডিভাইচৰ লগত সংযোগ কৰক"</string>
- <string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"ডিভাইচত স্ক্ৰীণ কাষ্ট কৰক"</string>
+ <string name="media_route_chooser_title_for_remote_display" msgid="3105906508794326446">"ডিভাইচত স্ক্ৰীন কাষ্ট কৰক"</string>
<string name="media_route_chooser_searching" msgid="6119673534251329535">"ডিভাইচৰ সন্ধান কৰক…"</string>
<string name="media_route_chooser_extended_settings" msgid="2506352159381327741">"ছেটিংসমূহ"</string>
<string name="media_route_controller_disconnect" msgid="7362617572732576959">"বিচ্ছিন্ন কৰক"</string>
@@ -1643,8 +1641,8 @@
<string name="media_route_status_available" msgid="1477537663492007608">"উপলব্ধ"</string>
<string name="media_route_status_not_available" msgid="480912417977515261">"উপলব্ধ নহয়"</string>
<string name="media_route_status_in_use" msgid="6684112905244944724">"ব্যৱহাৰ হৈ আছে"</string>
- <string name="display_manager_built_in_display_name" msgid="1015775198829722440">"অন্তৰ্নিমিত স্ক্ৰীণ"</string>
- <string name="display_manager_hdmi_display_name" msgid="1022758026251534975">"HDMI স্ক্ৰীণ"</string>
+ <string name="display_manager_built_in_display_name" msgid="1015775198829722440">"বিল্ট-ইন স্ক্ৰীন"</string>
+ <string name="display_manager_hdmi_display_name" msgid="1022758026251534975">"HDMI স্ক্ৰীন"</string>
<string name="display_manager_overlay_display_name" msgid="5306088205181005861">"অ\'ভাৰলে\' #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="1480158037150469170">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
<string name="display_manager_overlay_display_secure_suffix" msgid="2810034719482834679">", সুৰক্ষিত"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"শ্বৰ্টকাটটো অন হৈ থকাৰ সময়ত দুয়োটা ভলিউম বুটাম ৩ ছেকেণ্ডৰ বাবে হেঁচি ধৰি ৰাখিলে এটা সাধ্য সুবিধা আৰম্ভ হ’ব।"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"সাধ্য সুবিধাসমূহৰ বাবে শ্বৰ্টকাট অন কৰিবনে?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"দুয়োটা ভলিউম কী কিছুসময়ৰ বাবে ধৰি থাকিলে সাধ্য-সুবিধাসমূহ অন কৰে। এইটোৱে আপোনাৰ ডিভাইচটোৱে কাম কৰাৰ ধৰণ সলনি কৰিব পাৰে।\n\nবর্তমানৰ সুবিধাসমূহ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nআপুনি ছেটিংসমূহ > সাধ্য-সুবিধাত কিছুমান নিৰ্দিষ্ট সুবিধা সলনি কৰিব পাৰে।"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g>ৰ শ্বৰ্টকাট অন কৰিবনে?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"দুয়োটা ভলিউম কী কিছুসময়ৰ বাবে ধৰি থাকিলে এটা সাধ্য- সুবিধা <xliff:g id="SERVICE">%1$s</xliff:g> অন কৰে। এইটোৱে আপোনাৰ ডিভাইচটোৱে কাম কৰাৰ ধৰণ সলনি কৰিব পাৰে।\n\nআপুনি ছেটিংসমূহ > সাধ্য-সুবিধাসমূহত এই শ্বৰ্টকাটটো অন্য এটা সুবিধালৈ সলনি কৰিব পাৰে।"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"অন কৰক"</string>
@@ -2094,7 +2091,7 @@
<string name="notification_app_name_settings" msgid="9088548800899952531">"ছেটিংসমূহ"</string>
<string name="notification_appops_camera_active" msgid="8177643089272352083">"কেমেৰা"</string>
<string name="notification_appops_microphone_active" msgid="581333393214739332">"মাইক্ৰ\'ফ\'ন"</string>
- <string name="notification_appops_overlay_active" msgid="5571732753262836481">"স্ক্ৰীণত অইন এপৰ ওপৰত দেখুৱাওক"</string>
+ <string name="notification_appops_overlay_active" msgid="5571732753262836481">"আপোনাৰ স্ক্ৰীনত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ আছে"</string>
<string name="notification_feedback_indicator" msgid="663476517711323016">"মতামত দিয়ক"</string>
<string name="notification_feedback_indicator_alerted" msgid="6552871804121942099">"এই জাননীটোৰ গুৰুত্ব ডিফ’ল্টলৈ বৃদ্ধি কৰা হৈছে। মতামত দিবলৈ টিপক।"</string>
<string name="notification_feedback_indicator_silenced" msgid="3799442124723177262">"এই জাননীটোৰ গুৰুত্ব নীৰৱলৈ হ্ৰাস কৰা হৈছে। মতামত দিবলৈ টিপক।"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 24ea7fc..646175c 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Davam etmək üçün barmaq izi və ya ekran kilidinizdən istifadə edin"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Xəta oldu. Yenə cəhd edin."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Barmaq izi ikonası"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Üz ilə kiliddən çıxarma"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Üz ilə kiliddən çıxarma problemi"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Davam etmək üçün üz və ya ekran kilidinizdən istifadə edin"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Xəta oldu. Yenə cəhd edin."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Üz işarəsi"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"sinx ayarlarını oxu"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Tətbiqə hesablar üçün sinxronizasiya nizamlarını oxuma icazəsi verir. Məsələn, bu Şəxslər tətbiqinin sinxronizə olunub-olunmadığını təyin edə bilər."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Qısayol aktiv olduqda, hər iki səs düyməsinə 3 saniyə basıb saxlamaqla əlçatımlılıq funksiyası başladılacaq."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Əlçatımlılıq funksiyaları üçün qısayol aktiv edilsin?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Hər iki səs səviyyəsi düyməsinə bir neçə saniyə basıb saxladıqda əlçatımlılıq funksiyaları aktiv olur. Cihazınızın işləmə qaydasını dəyişə bilər.\n\nCari funksiyalar:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nAyarlar və Əlçatımlılıq bölməsində seçilmiş funksiyaları dəyişə bilərsiniz."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> qısayolu aktiv edilsin?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Hər iki səs səviyyəsi düyməsinə bir neçə saniyə basıb saxladıqda əlçatımlılıq funksiyası olan <xliff:g id="SERVICE">%1$s</xliff:g> aktiv olur. Cihazınızın işləmə qaydasını dəyişə bilər.\n\nAyarlar və Əlçatımlılıq bölməsində bu qısayolu başqa bir funksiyaya dəyişə bilərsiniz."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktiv edin"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 80b3a3a..3944c1a 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -612,8 +612,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Koristite otisak prsta ili zaključavanje ekrana da biste nastavili"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Došlo je do problema. Probajte ponovo."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona otiska prsta"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Otključavanje licem"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem sa otključavanje licem"</string>
@@ -666,8 +665,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Koristite lice ili zaključavanje ekrana da biste nastavili"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Došlo je do problema. Probajte ponovo."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ikona lica"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"čitanje podešavanja sinhronizacije"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Dozvoljava aplikaciji da čita podešavanja sinhronizacije za nalog. Na primer, ovako može da se utvrdi da li je aplikacija Ljudi sinhronizovana sa nalogom."</string>
@@ -1718,8 +1716,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kada je prečica uključena, pritisnite oba dugmeta za jačinu zvuka da biste pokrenuli funkciju pristupačnosti."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Želite da uključite prečicu za funkcije pristupačnosti?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ako zadržite oba tastera za jačinu zvuka par sekundi, uključiće se funkcije pristupačnosti. To može da promeni način rada uređaja.\n\nPostojeće funkcije:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nMožete da promenite izabrane funkcije u odeljku Podešavanja > Pristupačnost."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Želite da uključite prečicu za uslugu <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ako zadržite oba tastera za jačinu zvuka par sekundi, uključuje se <xliff:g id="SERVICE">%1$s</xliff:g>, funkcija pristupačnosti. To može da promeni način rada uređaja.\n\nMožete da promenite funkciju na koju se odnosi ova prečica u odeljku Podešavanja > Pristupačnost."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Uključi"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 8f74705..a61ea16 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -615,8 +615,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Каб працягнуць, скарыстайце адбітак пальца ці сродак разблакіроўкі экрана"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Нешта пайшло не так. Паўтарыце спробу."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Значок адбіткаў пальцаў"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Распазнаванне твару"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Праблема з распазнаваннем твару"</string>
@@ -669,8 +668,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Каб працягнуць, скарыстайце распазнаванне твару ці сродак разблакіроўкі экрана"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Нешта пайшло не так. Паўтарыце спробу."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Значок твару"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"чытаць параметры сінхранізацыі"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Дазваляе прыкладанням чытаць параметры сінхранізацыі для ўліковага запісу. Напрыклад, яны могуць вызначыць, цi сiнхранiзавана з улiковым запiсам прыкладанне \"Кантакты\"."</string>
@@ -1740,8 +1738,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Калі хуткі доступ уключаны, вы можаце націснуць абедзве кнопкі гучнасці і ўтрымліваць іх 3 секунды, каб запусціць функцыю спецыяльных магчымасцей."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Уключыць хуткі доступ да спецыяльных магчымасцей?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Утрымліванне націснутымі абедзвюх клавіш гучнасці на працягу некалькіх секунд уключае спецыяльныя магчымасці. У выніку ваша прылада можа пачаць працаваць па-іншаму.\n\nБягучыя функцыі:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nВыбраныя функцыі можна змяніць у меню \"Налады > Спецыяльныя магчымасці\"."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Уключыць хуткі доступ да сэрвісу \"<xliff:g id="SERVICE">%1$s</xliff:g>\"?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Утрымліванне націснутымі абедзвюх клавіш гучнасці на працягу некалькіх секунд уключае службу \"<xliff:g id="SERVICE">%1$s</xliff:g>\", якая з\'яўляецца спецыяльнай магчымасцю. У выніку ваша прылада можа пачаць працаваць па-іншаму.\n\nВы можаце задаць гэта спалучэнне клавіш для іншай функцыі ў меню \"Налады > Спецыяльныя магчымасці\"."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Уключыць"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 01b2379..43a2a7d 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Използвайте отпечатъка си или опцията за заключване на екрана, за да продължите"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Нещо се обърка. Опитайте отново."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Икона за отпечатък"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Отключване с лице"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Проблем с отключването с лице"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Използвайте лицето си или опцията за заключване на екрана, за да продължите"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Нещо се обърка. Опитайте отново."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Икона на лице"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"четене на настройките за синхронизиране"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Разрешава на приложението да чете настройките за синхронизиране на профил. Например това може да определи дали приложението Хора е синхронизирано с даден профил."</string>
@@ -865,7 +863,7 @@
<string name="relationTypeReferredBy" msgid="5285082289602849400">"Препоръчан/а от"</string>
<string name="relationTypeRelative" msgid="3396498519818009134">"Роднина"</string>
<string name="relationTypeSister" msgid="3721676005094140671">"Сестра"</string>
- <string name="relationTypeSpouse" msgid="6916682664436031703">"Съпруг/а"</string>
+ <string name="relationTypeSpouse" msgid="6916682664436031703">"Съпруг(а)"</string>
<string name="sipAddressTypeCustom" msgid="6283889809842649336">"Персонализиран"</string>
<string name="sipAddressTypeHome" msgid="5918441930656878367">"Домашен"</string>
<string name="sipAddressTypeWork" msgid="7873967986701216770">"Служебен"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Когато прекият път е включен, можете да стартирате дадена функция за достъпност, като натиснете двата бутона за силата на звука и ги задържите за 3 секунди."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Искате ли да включите прекия път за функциите за достъпност?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Натиснете двата бутона за силата на звука и ги задръжте за няколко секунди, за да включите функциите за достъпност. Това може да промени начина, по който работи устройството ви.\n\nТекущи функции:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nМожете да промените избраните функции от „Настройки“ > „Достъпност“."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Искате ли да включите прекия път за <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Натиснете двата бутона за силата на звука и ги задръжте за няколко секунди, за да включите функцията за достъпност <xliff:g id="SERVICE">%1$s</xliff:g>. Това може да промени начина, по който работи устройството ви.\n\nМожете да зададете друга функция за този пряк път от „Настройки“ > „Достъпност“."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Включване"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 5253e41..5a7c0f9 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"চালিয়ে যেতে আপনার আঙুলের ছাপ বা স্ক্রিন লক ব্য়বহার করুন"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"কোনও সমস্যা হয়েছে। আবার করে দেখুন।"</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"আঙ্গুলের ছাপ আইকন"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ফেস আনলক"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"\'ফেস আনলক\' ফিচার ব্যবহার করার ক্ষেত্রে হওয়া সমস্যা"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"চালিয়ে যেতে আপনার ফেস বা স্ক্রিন লক ব্যবহার করুন"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"কোনও সমস্যা হয়েছে। আবার করে দেখুন।"</string>
<string name="face_icon_content_description" msgid="465030547475916280">"ফেস আইকন"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"সিঙ্ক সেটিংস পড়ে"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"অ্যাপ্লিকেশানটিকে একটি অ্যাকাউন্টের জন্য সিঙ্ক সেটিংস পড়ার অনুমতি দেয়৷ উদাহরণস্বরূপ, \'পিপল\' অ্যাপ্লিকেশানটি কোনো অ্যাকাউন্টের সাথে সিঙ্ক করা আছে কিনা তা নির্ধারণ করতে পারে৷"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"শর্টকাট চালু করা থাকাকালীন দুটি ভলিউম বোতাম একসাথে ৩ সেকেন্ড টিপে ধরে রাখলে একটি অ্যাকসেসিবিলিটি ফিচার চালু হবে।"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"অ্যাক্সেসিবিলিটি ফিচারের শর্টকাট বন্ধ করতে চান?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"উভয় ভলিউম কী কয়েক সেকেন্ড ধরে থাকলে অ্যাক্সেসিবিলিটি ফিচার চালু হয়ে যাবে। এর ফলে, আপনার ডিভাইস কীভাবে কাজ করবে সেটিতে পরিবর্তন হতে পারে।\n\nবর্তমান ফিচার:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nসেটিংস > অ্যাক্সেসিবিলিটি বিকল্প থেকে আপনি বাছাই করা ফিচার পরিবর্তন করতে পারবেন।"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> শর্টকাট চালু করতে চান?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"উভয় ভলিউম কী কয়েক সেকেন্ড ধরে থাকলে <xliff:g id="SERVICE">%1$s</xliff:g> চালু হয়ে যাবে। এটি একটি অ্যাক্সেসিবিলিটি ফিচার। এর ফলে, আপনার ডিভাইস কীভাবে কাজ করবে সেটিতে পরিবর্তন হতে পারে।\n\nসেটিংস > অ্যাক্সেসিবিলিটি থেকে আপনি এই শর্টকাট পরিবর্তন করতে পারবেন।"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"চালু করুন"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 2995f3c..f9157ae 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -612,8 +612,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Koristite otisak prsta ili zaključavanje ekrana da nastavite"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Nešto nije uredu. Pokušajte ponovo."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona za otisak prsta"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Otključavanje licem"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem s otključavanjem licem"</string>
@@ -666,8 +665,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Koristite lice ili zaključavanje ekrana da nastavite"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Nešto nije uredu. Pokušajte ponovo."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ikona lica"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"čitanje postavki za sinhroniziranje"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Omogućava aplikaciji čitanje postavki sinhroniziranja za račun. Naprimjer, ovim se može utvrditi da li je aplikacija People sinhronizirana sa računom."</string>
@@ -1718,8 +1716,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kada je prečica uključena, pritiskom i držanjem oba dugmeta za jačinu zvuka u trajanju od 3 sekunde pokrenut će se funkcija pristupačnosti."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Uključiti prečicu za funkcije pristupačnosti?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ako nekoliko sekundi držite pritisnute obje tipke za jačinu zvuka, uključit ćete funkcije pristupačnosti. Ovo može uticati na način rada uređaja.\n\nTrenutne funkcije:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nOdabrane funkcije možete promijeniti u odjeljku Postavke > Pristupačnost."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Uključiti prečicu za uslugu <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ako nekoliko sekundi držite pritisnute obje tipke za jačinu zvuka, uključit ćete funkciju pristupačnosti <xliff:g id="SERVICE">%1$s</xliff:g>. Ovo može promijeniti način rada uređaja.\n\nOvu prečicu možete zamijeniti drugom funkcijom u odjeljku Postavke > Pristupačnost."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Uključi"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index a182585..168b066 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Utilitza l\'empremta digital o el bloqueig de pantalla per continuar"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"S\'ha produït un error. Torna-ho a provar."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona d\'empremta digital"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueig facial"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema amb Desbloqueig facial"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilitza la cara o el bloqueig de pantalla per continuar"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"S\'ha produït un error. Torna-ho a provar."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Icona facial"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"llegir la configuració de sincronització"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permet que l\'aplicació llegeixi la configuració de sincronització d\'un compte. Per exemple, això pot determinar que l\'aplicació Contactes estigui sincronitzada amb un compte."</string>
@@ -911,7 +909,7 @@
<string name="emergency_calls_only" msgid="3057351206678279851">"Només trucades d\'emergència"</string>
<string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Xarxa bloquejada"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"La targeta SIM està bloquejada pel PUK."</string>
- <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Consulta la guia de l\'usuari o posa\'t en contacte amb el servei d\'atenció al client."</string>
+ <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"Consulta la guia d\'usuari o posa\'t en contacte amb el servei d\'atenció al client."</string>
<string name="lockscreen_sim_locked_message" msgid="3160196135801185938">"La targeta SIM està bloquejada."</string>
<string name="lockscreen_sim_unlock_progress_dialog_message" msgid="2286497117428409709">"S\'està desbloquejant la targeta SIM..."</string>
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"Has dibuixat el patró de desbloqueig de manera incorrecta <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Si la drecera està activada, prem els dos botons de volum durant 3 segons per iniciar una funció d\'accessibilitat."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vols desactivar la drecera de les funcions d\'accessibilitat?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Si mantens premudes les dues tecles de volum durant uns segons, s\'activaran les funcions d\'accessibilitat. Això podria canviar el funcionament del teu dispositiu.\n\nFuncions actuals:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPots canviar les funcions seleccionades a Configuració > Accessibilitat."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Vols activar la drecera de <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Si mantens premudes les dues tecles de volum durant uns segons, la funció d\'accessibilitat <xliff:g id="SERVICE">%1$s</xliff:g> s\'activarà. Això podria canviar el funcionament del teu dispositiu.\n\nPots canviar la funció d\'aquesta drecera a Configuració > Accessibilitat."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activa"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 75528bb..7f0f977 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -615,8 +615,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Pokračujte ověřením pomocí otisku prstu nebo zámku obrazovky"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Došlo k chybě. Zkuste to znovu."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona otisku prstů"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Odemknutí obličejem"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problém s odemykáním obličejem"</string>
@@ -669,8 +668,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Pokračujte ověřením pomocí obličeje nebo zámku obrazovky"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Došlo k chybě. Zkuste to znovu."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ikona obličeje"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"čtení nastavení synchronizace"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Umožňuje aplikaci číst nastavení synchronizace v účtu. Může například určit, zda je s účtem synchronizována aplikace Lidé."</string>
@@ -1740,8 +1738,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Když je tato zkratka zapnutá, můžete funkci přístupnosti spustit tím, že na tři sekundy podržíte obě tlačítka hlasitosti."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Zapnout zkratku funkcí pro usnadnění přístupu?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Podržením obou tlačítek hlasitosti po dobu několika sekund zapnete funkce pro usnadnění přístupu. Tato funkce může změnit fungování zařízení.\n\nAktuální funkce:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nVybrané funkce můžete změnit v Nastavení > Přístupnost."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Zapnout zkratku služby <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Podržením obou tlačítek hlasitosti po dobu několika sekund zapnete funkci pro usnadnění přístupu <xliff:g id="SERVICE">%1$s</xliff:g>. Tato funkce může změnit fungování zařízení.\n\nZkratku můžete nastavit na jinou funkci v Nastavení > Přístupnost."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Zapnout"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index f504cc7..c0a1d28 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -194,11 +194,11 @@
<string name="device_ownership_relinquished" msgid="4080886992183195724">"Administratoren har gjort personlig brug af enheden utilgængelig"</string>
<string name="network_logging_notification_title" msgid="554983187553845004">"Dette er en administreret enhed"</string>
<string name="network_logging_notification_text" msgid="1327373071132562512">"Din organisation administrerer denne enhed og kan overvåge netværkstrafik. Tryk for at se info."</string>
- <string name="location_changed_notification_title" msgid="3620158742816699316">"Apps kan få adgang til din placering"</string>
+ <string name="location_changed_notification_title" msgid="3620158742816699316">"Apps kan få adgang til din lokation"</string>
<string name="location_changed_notification_text" msgid="7158423339982706912">"Kontakt din it-administrator for at få flere oplysninger"</string>
- <string name="geofencing_service" msgid="3826902410740315456">"Geografisk placeringstjeneste"</string>
+ <string name="geofencing_service" msgid="3826902410740315456">"Tjeneste til geografisk afgrænsning"</string>
<string name="country_detector" msgid="7023275114706088854">"Landeregistrering"</string>
- <string name="location_service" msgid="2439187616018455546">"Placeringstjeneste"</string>
+ <string name="location_service" msgid="2439187616018455546">"Lokationstjeneste"</string>
<string name="gnss_service" msgid="8907781262179951385">"GNSS-tjeneste"</string>
<string name="sensor_notification_service" msgid="7474531979178682676">"Tjenesten Sensor Notification"</string>
<string name="twilight_service" msgid="8964898045693187224">"Tjenesten Twilight"</string>
@@ -304,8 +304,8 @@
<string name="managed_profile_label" msgid="7316778766973512382">"Skift til arbejdsprofil"</string>
<string name="permgrouplab_contacts" msgid="4254143639307316920">"Kontakter"</string>
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"have adgang til dine kontakter"</string>
- <string name="permgrouplab_location" msgid="1858277002233964394">"Placering"</string>
- <string name="permgroupdesc_location" msgid="1995955142118450685">"få adgang til enhedens placering"</string>
+ <string name="permgrouplab_location" msgid="1858277002233964394">"Lokation"</string>
+ <string name="permgroupdesc_location" msgid="1995955142118450685">"få adgang til enhedens lokation"</string>
<string name="permgrouplab_calendar" msgid="6426860926123033230">"Kalender"</string>
<string name="permgroupdesc_calendar" msgid="6762751063361489379">"have adgang til din kalender"</string>
<string name="permgrouplab_sms" msgid="795737735126084874">"Sms"</string>
@@ -434,14 +434,14 @@
<string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"Denne app kan tilføje, fjerne eller ændre kalenderbegivenheder på din tablet. Denne app kan sende meddelelser, der kan se ud, som om de kommer fra kalenderejere, eller ændre begivenheder uden at give ejeren besked."</string>
<string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"Denne app kan tilføje, fjerne eller ændre kalenderbegivenheder på din Android TV-enhed. Denne app kan sende meddelelser, der lader til at stamme fra kalenderejere, eller ændre begivenheder uden at give ejeren besked."</string>
<string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"Denne app kan tilføje, fjerne eller ændre kalenderbegivenheder på din telefon. Denne app kan sende meddelelser, der kan se ud, som om de kommer fra kalenderejere, eller ændre begivenheder uden at give ejeren besked."</string>
- <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"få adgang til yderligere kommandoer for placeringsudbyder"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Tillader, at appen kan få adgang til yderligere kommandoer for placeringsudbydere. Dette kan gøre det muligt for appen at forstyrre GPS-funktionen eller andre placeringskilder."</string>
- <string name="permlab_accessFineLocation" msgid="6426318438195622966">"få kun adgang til nøjagtig placering i forgrunden"</string>
- <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"Denne app kan finde din nøjagtige placering via placeringstjenester, når appen er i brug. Placeringstjenester skal være aktiveret på din enhed, før appen kan finde din placering. Dette kan øge batteriforbruget."</string>
- <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"få kun adgang til omtrentlig placering i forgrunden"</string>
- <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"Denne app kan finde din omtrentlige placering via placeringstjenester, når appen er i brug. Placeringstjenester skal være aktiveret på din enhed, før appen kan finde din placering."</string>
- <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"adgang til placering i baggrunden"</string>
- <string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"Denne app kan til enhver tid få adgang til din placering, selv når den ikke er i brug."</string>
+ <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"få adgang til yderligere kommandoer for lokationsudbyder"</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Tillader, at appen kan få adgang til yderligere kommandoer for lokationsudbydere. Dette kan gøre det muligt for appen at forstyrre GPS-funktionen eller andre lokationskilder."</string>
+ <string name="permlab_accessFineLocation" msgid="6426318438195622966">"få kun adgang til nøjagtig lokation i forgrunden"</string>
+ <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"Denne app kan finde din nøjagtige lokation via lokationstjenester, når appen er i brug. Lokationstjenester skal være aktiveret på din enhed, før appen kan finde din lokation. Dette kan øge batteriforbruget."</string>
+ <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"få kun adgang til omtrentlig lokation i forgrunden"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"Denne app kan finde din omtrentlige lokation via lokationstjenester, når appen er i brug. Lokationstjenester skal være aktiveret på din enhed, før appen kan finde din lokation."</string>
+ <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"adgang til lokation i baggrunden"</string>
+ <string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"Denne app kan til enhver tid få adgang til din lokation, selv når den ikke er i brug."</string>
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"skifte dine lydindstillinger"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Tillader, at appen kan ændre globale lydindstillinger, som f.eks. lydstyrke og hvilken højttaler der bruges til output."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"optage lyd"</string>
@@ -561,8 +561,8 @@
<string name="permdesc_videoWrite" msgid="6124731210613317051">"Tillader, at appen kan ændre din videosamling."</string>
<string name="permlab_imagesWrite" msgid="1774555086984985578">"ændre din billedsamling"</string>
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"Tillader, at appen kan ændre din billedsamling."</string>
- <string name="permlab_mediaLocation" msgid="7368098373378598066">"læse placeringer fra din mediesamling"</string>
- <string name="permdesc_mediaLocation" msgid="597912899423578138">"Tillader, at appen kan læse placeringer fra din mediesamling."</string>
+ <string name="permlab_mediaLocation" msgid="7368098373378598066">"læse lokationer fra din mediesamling"</string>
+ <string name="permdesc_mediaLocation" msgid="597912899423578138">"Tillader, at appen kan læse lokationer fra din mediesamling."</string>
<string name="biometric_app_setting_name" msgid="3339209978734534457">"Brug biometri"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Brug biometri eller skærmlås"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"Bekræft, at det er dig"</string>
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Brug dit fingeraftryk eller din skærmlås for at fortsætte"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Noget gik galt. Prøv igen."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon for fingeraftryk"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ansigtslås"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Der er et problem med Ansigtslås"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Brug din ansigts- eller skærmlås for at fortsætte"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Noget gik galt. Prøv igen."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ansigt"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"læse indstillinger for synkronisering"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Tillader, at appen kan læse synkroniseringsindstillingerne for en konto. Denne tilladelse kan f.eks. fastslå, om appen Personer er synkroniseret med en konto."</string>
@@ -1530,8 +1528,8 @@
<string name="websearch" msgid="5624340204512793290">"Websøgning"</string>
<string name="find_next" msgid="5341217051549648153">"Find næste"</string>
<string name="find_previous" msgid="4405898398141275532">"Find forrige"</string>
- <string name="gpsNotifTicker" msgid="3207361857637620780">"Placeringsanmodning fra <xliff:g id="NAME">%s</xliff:g>"</string>
- <string name="gpsNotifTitle" msgid="1590033371665669570">"Placeringsanmodning"</string>
+ <string name="gpsNotifTicker" msgid="3207361857637620780">"Lokationsanmodning fra <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="gpsNotifTitle" msgid="1590033371665669570">"Lokationsanmodning"</string>
<string name="gpsNotifMessage" msgid="7346649122793758032">"Anmodet om af <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="3719843080744112940">"Ja"</string>
<string name="gpsVerifNo" msgid="1671201856091564741">"Nej"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Når genvejen er aktiveret, kan du starte en hjælpefunktion ved at trykke på begge lydstyrkeknapper i tre sekunder."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vil du aktivere genvejen til hjælpefunktioner?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Hvis du holder begge lydstyrkeknapperne nede i et par sekunder, aktiveres hjælpefunktionerne. Det kan ændre på, hvordan din enhed fungerer.\n\nAktuelle funktioner:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nDu kan ændre de valgte funktioner i Indstillinger > Hjælpefunktioner."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Vil du aktivere <xliff:g id="SERVICE">%1$s</xliff:g>-genvejen?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Hvis du holder begge lydstyrkeknapperne nede i et par sekunder, aktiveres hjælpefunktionen <xliff:g id="SERVICE">%1$s</xliff:g>. Det kan ændre på, hvordan din enhed fungerer.\n\nDu kan ændre denne genvej til en anden funktion i Indstillinger > Hjælpefunktioner."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktivér"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 831a66b..a2b90e4 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Verwende deinen Fingerabdruck oder deine Display-Entsperrmethode, um fortzufahren"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Ein Problem ist aufgetreten. Versuch es noch einmal."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingerabdruck-Symbol"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Entsperrung per Gesichtserkennung"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem bei der Entsperrung per Gesichtserkennung"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Verwende die Gesichtserkennung oder deine Display-Entsperrmethode, um fortzufahren"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Ein Problem ist aufgetreten. Versuch es noch einmal."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Gesichtssymbol"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"Synchronisierungseinstellungen lesen"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Ermöglicht der App, die Synchronisierungseinstellungen eines Kontos zu lesen. Beispielsweise kann damit festgestellt werden, ob Kontakte mit einem Konto synchronisiert werden."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Wenn die Verknüpfung aktiviert ist, kannst du die beiden Lautstärketasten drei Sekunden lang gedrückt halten, um eine Bedienungshilfe zu starten."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Verknüpfung für Bedienungshilfen aktivieren?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Wenn du beide Lautstärketasten einige Sekunden lang gedrückt hältst, aktivierst du die Bedienungshilfen. Dadurch kann sich die Funktionsweise deines Geräts ändern.\n\nAktuelle Funktionen:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nDu kannst ausgewählte Funktionen unter \"Einstellungen\" > \"Bedienungshilfen\" ändern."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Verknüpfung für <xliff:g id="SERVICE">%1$s</xliff:g> aktivieren?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Wenn du beide Lautstärketasten einige Sekunden lang gedrückt hältst, aktivierst du die Bedienungshilfe \"<xliff:g id="SERVICE">%1$s</xliff:g>\". Dadurch kann sich die Funktionsweise deines Geräts ändern.\n\nUnter \"Einstellungen > \"Bedienungshilfen\" kannst du dieser Verknüpfung eine andere Funktion zuweisen."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktivieren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index beffc46..ac16e64 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Χρησιμοποιήστε το δακτυλικό σας αποτύπωμα ή το κλείδωμα οθόνης για να συνεχίσετε"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Παρουσιάστηκε κάποιο πρόβλημα. Δοκιμάστε ξανά."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Εικονίδιο δακτυλικών αποτυπωμάτων"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ξεκλείδωμα με το πρόσωπο"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Πρόβλημα με το Ξεκλείδωμα με το πρόσωπο"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Χρησιμοποιήστε το πρόσωπό σας ή το κλείδωμα οθόνης για συνέχεια"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Παρουσιάστηκε κάποιο πρόβλημα. Δοκιμάστε ξανά."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Εικ. προσ."</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"διαβάζει τις ρυθμίσεις συγχρονισμού"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Επιτρέπει στην εφαρμογή την ανάγνωση των ρυθμίσεων συγχρονισμού για έναν λογαριασμό. Για παράδειγμα, αυτό μπορεί να καθορίσει εάν η εφαρμογή \"Άτομα\" είναι συγχρονισμένη με έναν λογαριασμό."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Όταν η συντόμευση είναι ενεργοποιημένη, το πάτημα και των δύο κουμπιών έντασης ήχου για 3 δευτερόλεπτα θα ξεκινήσει μια λειτουργία προσβασιμότητας."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Ενεργοποίηση συντόμευσης για λειτουργίες προσβασιμότητας;"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Για να ενεργοποιήσετε τις λειτουργίες προσβασιμότητας, πατήστε παρατεταμένα τα δύο πλήκτρα έντασης για μερικά δευτερόλεπτα. Αυτό ενδέχεται να αλλάξει τον τρόπο λειτουργίας της συσκευής σας.\n\nΤρέχουσες λειτουργίες:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nΜπορείτε να αλλάξετε τις επιλεγμένες λειτουργίες στις Ρυθμίσεις > Προσβασιμότητα."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Ενεργοποίηση συντόμευσης <xliff:g id="SERVICE">%1$s</xliff:g>;"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Μπορείτε να ενεργοποιήσετε τη λειτουργία <xliff:g id="SERVICE">%1$s</xliff:g>, η οποία είναι μία από τις λειτουργίες προσβασιμότητας, πατώντας παρατεταμένα ταυτόχρονα τα δύο πλήκτρα έντασης ήχου για μερικά δευτερόλεπτα. Αυτό ενδέχεται να αλλάξει τον τρόπο λειτουργίας της συσκευής σας.\n\nΜπορείτε να αλλάξετε αυτή τη συντόμευση σε μια άλλη λειτουργία στις Ρυθμίσεις > Προσβασιμότητα."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Ενεργοποίηση"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 3de374d..d066657 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Usa tu huella dactilar o bloqueo de pantalla para continuar"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Se produjo un error. Vuelve a intentarlo."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ícono de huella dactilar"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueo facial"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problema con el Desbloqueo facial"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Usa tu rostro o bloqueo de pantalla para continuar"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Se produjo un error. Vuelve a intentarlo."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ícono cara"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"leer la configuración de sincronización"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Este permiso permite que la aplicación consulte la configuración de sincronización de una cuenta. Esto permite, por ejemplo, determinar si la aplicación Personas está sincronizada con una cuenta."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Cuando la combinación de teclas está activada, puedes presionar los botones de volumen durante 3 segundos para iniciar una función de accesibilidad."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"¿Quieres activar la combinación de teclas para las funciones de accesibilidad?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Si mantienes presionadas las dos teclas de volumen durante unos segundos, se activarán las funciones de accesibilidad. Esto puede cambiar el funcionamiento de tu dispositivo.\n\nFunciones actuales:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPuedes cambiar las funciones seleccionadas en Configuración > Accesibilidad."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"¿Quieres activar el acceso directo de <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Si mantienes presionadas ambas teclas de volumen durante unos segundos, se activará la función de accesibilidad <xliff:g id="SERVICE">%1$s</xliff:g>. Esto podría cambiar la forma en que funciona tu dispositivo.\n\nPuedes cambiar este acceso directo a otra función en Configuración > Accesibilidad."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activar"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index e549d45..63066f5 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Jätkamiseks kasutage oma sõrmejälge või ekraanilukku"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Midagi läks valesti. Proovige uuesti."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Sõrmejälje ikoon"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Näoga avamine"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Probleem funktsiooniga Näoga avamine"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Jätkamiseks kasutage oma nägu või ekraanilukku"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Midagi läks valesti. Proovige uuesti."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Näoikoon"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"loe sünkroonimisseadeid"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Võimaldab rakendusel lugeda konto sünkroonimisseadeid. Näiteks võib see määrata, kas rakendus Inimesed on kontoga sünkroonitud."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kui otsetee on sisse lülitatud, käivitab mõlema helitugevuse nupu kolm sekundit all hoidmine juurdepääsetavuse funktsiooni."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Kas lülitada juurdepääsufunktsioonide otsetee sisse?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Hoidke juurdepääsufunktsioonide sisselülitamiseks mõlemat helitugevuse klahvi mõni sekund all. See võib teie seadme tööviisi muuta.\n\nPraegused funktsioonid:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nValitud funktsioone saab muuta jaotises Seaded > Juurdepääsetavus."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Kas lülitada teenuse <xliff:g id="SERVICE">%1$s</xliff:g> otsetee sisse?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Kui hoiate mõlemat helitugevuse klahvi mõni sekund all, lülitatakse juurdepääsufunktsioon <xliff:g id="SERVICE">%1$s</xliff:g> sisse. See võib teie seadme tööviisi muuta.\n\nSelle otsetee saab asendada muu otseteega jaotises Seaded > Juurdepääsetavus."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Lülita sisse"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 01d191d..ca187cb 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Aurrera egiteko, erabili hatz-marka edo pantailaren blokeoa"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Arazoren bat izan da. Saiatu berriro."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Hatz-markaren ikonoa"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Aurpegi bidez desblokeatzeko eginbidea"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Arazoak ditugu aurpegi bidez desblokeatzeko eginbidearekin"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Aurrera egiteko, erabili aurpegia edo pantailaren blokeoa"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Arazoren bat izan da. Saiatu berriro."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Aurpegiaren ikonoa"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"irakurri sinkronizazio-ezarpenak"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Kontu baten sinkronizazio-ezarpenak irakurtzeko baimena ematen die aplikazioei. Adibidez, Jendea aplikazioa konturen batekin sinkronizatuta dagoen zehatz dezake."</string>
@@ -1317,7 +1315,7 @@
<string name="network_partial_connectivity" msgid="4791024923851432291">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> sareak konektagarritasun murriztua du"</string>
<string name="network_partial_connectivity_detailed" msgid="5741329444564575840">"Sakatu hala ere konektatzeko"</string>
<string name="network_switch_metered" msgid="1531869544142283384">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> erabiltzen ari zara orain"</string>
- <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> Internetera konektatzeko gauza ez denean, <xliff:g id="NEW_NETWORK">%1$s</xliff:g> erabiltzen du gailuak. Agian kostuak ordaindu beharko dituzu."</string>
+ <string name="network_switch_metered_detail" msgid="1358296010128405906">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> Internetera konektatzeko gauza ez denean, <xliff:g id="NEW_NETWORK">%1$s</xliff:g> erabiltzen du gailuak. Baliteke zerbait ordaindu behar izatea."</string>
<string name="network_switch_metered_toast" msgid="501662047275723743">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> erabiltzen ari zinen, baina <xliff:g id="NEW_NETWORK">%2$s</xliff:g> erabiltzen ari zara orain"</string>
<string-array name="network_switch_type_name">
<item msgid="2255670471736226365">"datu-konexioa"</item>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Lasterbidea aktibatuta dagoenean, bi bolumen-botoiak hiru segundoz sakatuta abiaraziko da erabilerraztasun-eginbidea."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Erabilerraztasun-eginbideetarako lasterbidea aktibatu nahi duzu?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Eduki sakatuta bolumen-botoiak segundo batzuez erabilerraztasun-eginbideak aktibatzeko. Hori eginez gero, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nEginbideak:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nHautatutako eginbideak aldatzeko, joan Ezarpenak > Erabilerraztasuna atalera."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> zerbitzuaren lasterbidea aktibatu nahi duzu?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Eduki sakatuta bolumen-botoiak segundo batzuez <xliff:g id="SERVICE">%1$s</xliff:g> izeneko erabilerraztasun-eginbidea aktibatzeko. Honen bidez, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nLasterbide hau beste eginbide batengatik aldatzeko, joan Ezarpenak > Erabilerraztasuna atalera."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktibatu"</string>
@@ -1991,7 +1988,7 @@
<string name="deprecated_target_sdk_message" msgid="5203207875657579953">"Aplikazioa Android-en bertsio zaharrago baterako sortu zenez, baliteke behar bezala ez funtzionatzea. Bilatu eguneratzerik baden, edo jarri garatzailearekin harremanetan."</string>
<string name="deprecated_target_sdk_app_store" msgid="8456784048558808909">"Bilatu eguneratzeak"</string>
<string name="new_sms_notification_title" msgid="6528758221319927107">"Mezu berriak dituzu"</string>
- <string name="new_sms_notification_content" msgid="3197949934153460639">"Mezuak ikusteko, ireki SMS mezuetarako aplikazioa"</string>
+ <string name="new_sms_notification_content" msgid="3197949934153460639">"Mezuak ikusteko, ireki SMSetarako aplikazioa"</string>
<string name="profile_encrypted_title" msgid="9001208667521266472">"Baliteke funtzio batzuk mugatuta egotea"</string>
<string name="profile_encrypted_detail" msgid="5279730442756849055">"Blokeatuta dago laneko profila"</string>
<string name="profile_encrypted_message" msgid="1128512616293157802">"Sakatu profila desblokeatzeko"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 393382a..a99aaeee 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"برای ادامه، از اثر انگشت یا قفل صفحه استفاده کنید"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"مشکلی پیش آمد. دوباره امتحان کنید."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"نماد اثر انگشت"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"قفلگشایی با چهره"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"مشکل در «قفلگشایی با چهره»"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"برای ادامه، از تشخیص چهره یا قفل صفحه استفاده کنید"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"مشکلی پیش آمد. دوباره امتحان کنید."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"نماد چهره"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"خواندن تنظیمات همگامسازی"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"به برنامه اجازه میدهد تنظیمات را برای یک حساب بخواند. بهعنوان مثال، این ویژگی میتواند تعیین کند آیا حساب «افراد» شما با یک حساب همگامسازی شده است."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"وقتی میانبر روشن باشد، با فشار دادن هردو دکمه صدا بهمدت ۳ ثانیه ویژگی دسترسپذیری فعال میشود."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"میانبر برای ویژگیهای دسترسپذیری روشن شود؟"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"با پایین نگه داشتن هردو کلید میزان صدا بهمدت چند ثانیه، ویژگیهای دسترسپذیری روشن میشود. با این کار نحوه عملکرد دستگاهتان تغییر میکند.\n\nویژگیهای فعلی:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nمیتوانید ویژگیهای انتخابی را در «تنظیمات > دسترسپذیری» تغییر دهید."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"میانبر <xliff:g id="SERVICE">%1$s</xliff:g> روشن شود؟"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"با پایین نگه داشتن هردو کلید میزان صدا بهمدت چند ثانیه، <xliff:g id="SERVICE">%1$s</xliff:g> (یکی از ویژگیهای دسترسپذیری) روشن میشود. با این کار نحوه عملکرد دستگاهتان تغییر میکند.\n\nمیتوانید در «تنظیمات > دسترسپذیری»،این میانبر را به ویژگی دیگری تغییر دهید."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"روشن شود"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 4ce9a323..bf7eb9d 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Jatka sormenjäljen tai näytön lukituksen avulla"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Jotain meni vikaan. Yritä uudelleen."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Sormenjälkikuvake"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Kasvojentunnistusavaus"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Face Unlockiin liittyvä ongelma"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Jatka kasvojentunnistuksen tai näytön lukituksen avulla"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Jotain meni vikaan. Yritä uudelleen."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Kasvokuvake"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"lue synkronointiasetuksia"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Antaa sovelluksen lukea tilien synkronointiasetuksia. Sovellus voi esimerkiksi määrittää, onko Henkilöt-sovellus synkronoitu tilin kanssa."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kun pikanäppäin on käytössä, voit käynnistää esteettömyystoiminnon pitämällä molempia äänenvoimakkuuspainikkeita painettuna kolmen sekunnin ajan."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Laitetaanko esteettömyysominaisuuksien pikavalinta päälle?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Molempien äänenvoimakkuuspainikkeiden painaminen muutaman sekunnin ajan laittaa esteettömyysominaisuudet päälle. Tämä voi muuttaa laitteesi toimintaa.\n\nNykyiset ominaisuudet:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nVoit muuttaa valittuja ominaisuuksia kohdassa Asetukset > Esteettömyys."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Laitetaanko pikavalinta (<xliff:g id="SERVICE">%1$s</xliff:g>) päälle?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Molempien äänenvoimakkuuspainikkeiden pitkään painaminen laittaa päälle esteettömyysominaisuuden <xliff:g id="SERVICE">%1$s</xliff:g>. Tämä voi muuttaa laitteesi toimintaa.\n\nVoit muuttaa tätä pikanäppäintä kohdassa Asetukset > Esteettömyys."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Laita päälle"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 9b16ba7..a3ea558 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Utilisez votre empreinte digitale ou le verrouillage de l\'écran pour continuer"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Un problème est survenu. Réessayez."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icône d\'empreinte digitale"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Déverrouillage par reconnaissance faciale"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problème avec la fonctionnalité de déverrouillage par reconnaissance faciale"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilisez votre visage ou le verrouillage de l\'écran pour continuer"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Un problème est survenu. Réessayez."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Icône visage"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"lire les paramètres de synchronisation"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permet à l\'application d\'accéder aux paramètres de synchronisation d\'un compte. Par exemple, cette autorisation peut permettre de déterminer si l\'application Contacts est synchronisée avec un compte ou non."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour lancer une fonctionnalité d\'accessibilité."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Activer le raccourci pour les fonctionnalités d\'accessibilité?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Si vous maintenez enfoncées les deux touches de volume pendant quelques secondes, vous activez les fonctionnalités d\'accessibilité. Cela peut modifier le fonctionnement de votre appareil.\n\nFonctionnalités actuellement utilisées :\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPour les modifier, sélectionnez Paramètres > Accessibilité."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Activer le raccourci pour <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Si vous maintenez enfoncées les deux touches de volume pendant quelques secondes, vous activez la fonctionnalité d\'accessibilité <xliff:g id="SERVICE">%1$s</xliff:g>. Cela peut modifier le fonctionnement de votre appareil.\n\nPour attribuer ce raccourci à une autre fonctionnalité, sélectionnez Paramètres > Accessibilité."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activer"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 08394ad..0ff73f8 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Utilisez votre empreinte digitale ou le verrouillage de l\'écran pour continuer"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Un problème est survenu. Réessayez."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icône d\'empreinte digitale"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Déverrouillage par reconnaissance faciale"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problème lié au déverrouillage par reconnaissance faciale"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Utilisez la reconnaissance faciale ou le verrouillage de l\'écran pour continuer"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Un problème est survenu. Réessayez."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Icône visage"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"lire les paramètres de synchronisation"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permet à l\'application d\'accéder aux paramètres de synchronisation d\'un compte. Par exemple, cette autorisation peut permettre de déterminer si l\'application Contacts est synchronisée avec un compte ou non."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour démarrer une fonctionnalité d\'accessibilité."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Activer le raccourci pour accéder aux fonctionnalités d\'accessibilité ?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Si vous appuyez sur les deux touches de volume pendant quelques secondes, vous activez des fonctionnalités d\'accessibilité. Cela peut affecter le fonctionnement de votre appareil.\n\nFonctionnalités actuellement utilisées :\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPour les modifier, accédez à Paramètres > Accessibilité."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Activer le raccourci <xliff:g id="SERVICE">%1$s</xliff:g> ?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Si vous appuyez sur les deux touches de volume pendant quelques secondes, vous activez la fonctionnalité d\'accessibilité <xliff:g id="SERVICE">%1$s</xliff:g>. Cela peut affecter le fonctionnement de votre appareil.\n\nPour attribuer ce raccourci à une autre fonctionnalité, accédez à Paramètres > Accessibilité."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activer"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 47ca329..6da942d 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Para continuar, utiliza a impresión dixital ou o bloqueo de pantalla"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Produciuse un erro. Téntao de novo."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icona de impresión dixital"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Desbloqueo facial"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Produciuse un problema co desbloqueo facial"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Para continuar, utiliza o desbloqueo facial ou a credencial do dispositivo"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Produciuse un erro. Téntao de novo."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Icona cara"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"ler a configuración de vinculación"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite á aplicación ler a configuración de vinculación dunha conta. Por exemplo, esta acción pode determinar se a aplicación Contactos se vincula cunha conta."</string>
@@ -985,7 +983,7 @@
<string name="js_dialog_before_unload_title" msgid="7012587995876771246">"Confirmar navegación"</string>
<string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"Abandonar esta páxina"</string>
<string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"Permanecer nesta páxina"</string>
- <string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nEstás seguro de que queres saír desta páxina?"</string>
+ <string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nSeguro que queres saír desta páxina?"</string>
<string name="save_password_label" msgid="9161712335355510035">"Confirmar"</string>
<string name="double_tap_toast" msgid="7065519579174882778">"Consello: Toca dúas veces para achegar e afastar o zoom."</string>
<string name="autofill_this_form" msgid="3187132440451621492">"Encher"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Cando o atallo está activado, podes premer os dous botóns de volume durante 3 segundos para iniciar unha función de accesibilidade."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Queres activar as funcións de accesibilidade?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ao manter as dúas teclas de volume premidas durante uns segundos actívanse as funcións de accesibilidade. Esta acción pode cambiar o funcionamento do dispositivo.\n\nFuncións activadas actualmente:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPodes cambiar as funcións seleccionadas en Configuración > Accesibilidade."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Queres activar o atallo a <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ao manter as dúas teclas de volume premidas durante uns segundos actívase <xliff:g id="SERVICE">%1$s</xliff:g>, unha función de accesibilidade. Esta acción pode cambiar o funcionamento do dispositivo.\n\nPodes cambiar o uso deste atallo para outra función en Configuración > Accesibilidade."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activar"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 133d144..5eea849 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ચાલુ રાખવા માટે તમારા ફિંગરપ્રિન્ટ અથવા સ્ક્રીન લૉકનો ઉપયોગ કરો"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"કંઈક ખોટું થયું. ફરી પ્રયાસ કરો."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ફિંગરપ્રિન્ટ આયકન"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ફેસ અનલૉક"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ફેસ અનલૉકની સુવિધામાં સમસ્યા"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ચાલુ રાખવા માટે તમારા ફેસ લૉક અથવા સ્ક્રીન લૉકનો ઉપયોગ કરો"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"કંઈક ખોટું થયું. ફરી પ્રયાસ કરો."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"ચહેરા આઇકન"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"સિંક સેટિંગ વાંચો"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ઍપને એકાઉન્ટ માટે સિંક સેટિંગને વાંચવાની મંજૂરી આપે છે. ઉદાહરણ તરીકે, આ એકાઉન્ટ સાથે લોકો ઍપ સિંક થઈ છે કે કેમ તે નિર્ધારિત કરી શકે છે."</string>
@@ -954,7 +952,7 @@
<string name="keyguard_accessibility_widget" msgid="6776892679715699875">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> વિજેટ."</string>
<string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"વપરાશકર્તા પસંદગીકર્તા"</string>
<string name="keyguard_accessibility_status" msgid="6792745049712397237">"સ્થિતિ"</string>
- <string name="keyguard_accessibility_camera" msgid="7862557559464986528">"કૅમેરો"</string>
+ <string name="keyguard_accessibility_camera" msgid="7862557559464986528">"કૅમેરા"</string>
<string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"મીડિયા નિયંત્રણો"</string>
<string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"વિજેટ પુનઃક્રમાંકન પ્રારંભ થયું."</string>
<string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"વિજેટ પુનઃક્રમાંકન સમાપ્ત થયું."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"જ્યારે શૉર્ટકટ ચાલુ હોય, ત્યારે બન્ને વૉલ્યૂમ બટનને 3 સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધા શરૂ થઈ જશે."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ઍક્સેસિબિલિટી સુવિધાઓ માટે શૉર્ટકટ ચાલુ કરીએ?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"બન્ને વૉલ્યૂમ કીને થોડી સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધાઓ ચાલુ થઈ જાય છે. આનાથી તમારા ડિવાઇસની કામ કરવાની રીત બદલાઈ શકે છે.\n\nવર્તમાન સુવિધાઓ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nતમે સેટિંગ > ઍક્સેસિબિલિટીમાં જઈને પસંદ કરેલી સુવિધાઓને બદલી શકો છો."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> શૉર્ટકટ ચાલુ કરીએ?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"બન્ને વૉલ્યૂમ કીને થોડી સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધા એવી <xliff:g id="SERVICE">%1$s</xliff:g> ચાલુ થઈ જાય છે. આનાથી તમારા ડિવાઇસની કામ કરવાની રીત બદલાઈ શકે છે.\n\nતમે સેટિંગ > ઍક્સેસિબિલિટીમાં જઈને આ શૉર્ટકટને બીજી સુવિધામાં બદલી શકો છો."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"ચાલુ કરો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index c678650..b4df01b 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"जारी रखने के लिए, फ़िंगरप्रिंट या स्क्रीन लॉक क्रेडेंशियल डालकर पुष्टि करें"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"कोई गड़बड़ी हुई. फिर से कोशिश करें."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"फ़िंगरप्रिंट आइकॉन"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"फ़ेस अनलॉक"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"फ़ेस अनलॉक से जुड़ी समस्या"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"जारी रखने के लिए, अपना चेहरा दिखाकर या स्क्रीन लॉक क्रेडेंशियल डालकर पुष्टि करें"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"कोई गड़बड़ी हुई. फिर से कोशिश करें."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"चेहरे का आइकॉन"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"समन्वयन सेटिंग पढ़ें"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ऐप्स को किसी खाते की समन्वयन सेटिंग पढ़ने देता है. उदाहरण के लिए, इससे यह तय किया जा सकता है कि लोग ऐप्स किसी खाते के साथ समन्वयित है या नहीं."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"शॉर्टकट के चालू होने पर, दाेनाें वॉल्यूम बटन (आवाज़ कम या ज़्यादा करने वाले बटन) को तीन सेकंड तक दबाने से, सुलभता सुविधा शुरू हाे जाएगी."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"क्या आप सुलभता सुविधाओं के लिए शॉर्टकट चालू करना चाहते हैं?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"आवाज़ कम और ज़्यादा करने वाले दोनों बटन को कुछ सेकंड तक दबाकर रखने से सुलभता सुविधाएं चालू हो जाती हैं. ऐसा करने से आपके डिवाइस के काम करने के तरीके में बदलाव हो सकता है.\n\nमौजूदा सुविधाएं:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nआप सेटिंग और सुलभता में जाकर चुनी हुई सुविधाएं बदल सकते हैं."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"क्या आप <xliff:g id="SERVICE">%1$s</xliff:g> शॉर्टकट चालू करना चाहते हैं?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"आवाज़ कम और ज़्यादा करने वाले दोनों बटन को कुछ सेकंड तक दबाकर रखने से <xliff:g id="SERVICE">%1$s</xliff:g> चालू हो जाती है, जो एक सुलभता सुविधा है. ऐसा करने से आपके डिवाइस के काम करने के तरीके में बदलाव हो सकता है.\n\nआप सेटिंग और सुलभता में जाकर इस शॉर्टकट को किसी दूसरी सुविधा के लिए बदल सकते हैं."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"चालू करें"</string>
@@ -2014,7 +2011,7 @@
<string name="app_category_image" msgid="7307840291864213007">"फ़ोटो और तस्वीरें"</string>
<string name="app_category_social" msgid="2278269325488344054">"सामाजिक और संचार"</string>
<string name="app_category_news" msgid="1172762719574964544">"समाचार और पत्रिकाएं"</string>
- <string name="app_category_maps" msgid="6395725487922533156">"Maps और नेविगेशन ऐप्लिकेशन"</string>
+ <string name="app_category_maps" msgid="6395725487922533156">"मैप और नेविगेशन ऐप्लिकेशन"</string>
<string name="app_category_productivity" msgid="1844422703029557883">"उत्पादकता"</string>
<string name="app_category_accessibility" msgid="6643521607848547683">"सुलभता"</string>
<string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"डिवाइस में जगह"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 35cd2f5..23b2a2f 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -612,8 +612,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Za nastavak se identificirajte otiskom prsta ili vjerodajnicom zaključavanja zaslona"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Nešto nije u redu. Pokušajte ponovo."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona otiska prsta"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Otključavanje licem"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Poteškoće s otključavanjem licem"</string>
@@ -666,8 +665,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Za nastavak se identificirajte licem ili vjerodajnicom zaključavanja zaslona"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Nešto nije u redu. Pokušajte ponovo."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ikona lica"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"čitanje postavki sinkronizacije"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Aplikaciji omogućuje čitanje postavki sinkronizacije za račun. Time se, primjerice, može utvrditi je li aplikacija Osobe sinkronizirana s računom."</string>
@@ -1718,8 +1716,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kad je taj prečac uključen, pritiskom na obje tipke za glasnoću na tri sekunde pokrenut će se značajka pristupačnosti."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Želite li uključiti prečac za značajke pristupačnosti?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Značajke pristupačnosti uključuju se ako na nekoliko sekundi pritisnete obje tipke za glasnoću. Time se može promijeniti način na koji vaš uređaj radi.\n\nTrenutačne značajke:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nOdabrane značajke možete promijeniti u odjeljku Postavke > Pristupačnost."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Želite li uključiti prečac za uslugu <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ako na nekoliko sekundi pritisnete obje tipke za glasnoću, uključuje se značajka pristupačnosti <xliff:g id="SERVICE">%1$s</xliff:g>. Time se može promijeniti način na koji vaš uređaj radi.\n\nZnačajku na koju se taj prečac odnosi možete promijeniti u odjeljku Postavke > Pristupačnost."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Uključi"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 2e383ec..e59d3c4 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"A folytatás ujjlenyomattal vagy a képernyőzár feloldásával lehetséges"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Hiba történt. Próbálja újra."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ujjlenyomat ikon"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Arcalapú feloldás"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Arcalapú feloldással kapcsolatos problémák"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"A folytatás arcalapú feloldással vagy a képernyőzár feloldásával lehetséges"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Hiba történt. Próbálja újra."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Arcikon"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"szinkronizálási beállítások olvasása"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Lehetővé teszi az alkalmazás számára egy fiók szinkronizálási beállításainak beolvasását. Például ellenőrizheti, hogy a Személyek alkalmazás szinkronizálva van-e egy fiókkal."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Ha a gyorsparancs aktív, akkor a két hangerőgomb három másodpercig tartó együttes lenyomásával kisegítő funkciót indíthat el."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Bekapcsol gyorsparancsot a kisegítő lehetőségekhez?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"A kisegítő lehetőségek bekapcsolásához tartsa nyomva néhány másodpercig mindkét hangerőgombot. Ez hatással lehet az eszköz működésére.\n\nJelenlegi funkciók:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nA kiválasztott funkciókat a Beállítások > Kisegítő lehetőségek pontban módosíthatja."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Bekapcsolja a(z) <xliff:g id="SERVICE">%1$s</xliff:g> szolgáltatás gyorsparancsát?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"A(z) <xliff:g id="SERVICE">%1$s</xliff:g> kisegítő lehetőség bekapcsolásához tartsa nyomva néhány másodpercig mindkét hangerőgombot. Ez hatással lehet az eszköz működésére.\n\nEzt a gyorsparancsot a Beállítások > Kisegítő lehetőségek pontban módosíthatja másik funkció használatára."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Bekapcsolom"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index f4c0316..0a51e3e 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -177,7 +177,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="5766411446676388623">"Չի հաջողվում համաժամացնել"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="4562226280528716090">"Հետևյալ ծառայությունից չափազանց շատ տարրեր եք ջնջել՝ <xliff:g id="CONTENT_TYPE">%s</xliff:g>:"</string>
<string name="low_memory" product="tablet" msgid="5557552311566179924">"Պլանշետի պահոցը լիքն է: Ջնջեք մի քանի ֆայլ` տարածք ազատելու համար:"</string>
- <string name="low_memory" product="watch" msgid="3479447988234030194">"Ժամացույցի ֆայլերի պահեստը լիքն է: Ջնջեք որոշ ֆայլեր՝ տարածք ազատելու համար:"</string>
+ <string name="low_memory" product="watch" msgid="3479447988234030194">"Ժամացույցի ֆայլերի պահոցը լիքն է: Ջնջեք որոշ ֆայլեր՝ տարածք ազատելու համար:"</string>
<string name="low_memory" product="tv" msgid="6663680413790323318">"Android TV սարքի հիշողությունը լցված է։ Ջնջեք որոշ ֆայլեր՝ տարածք ազատելու համար:"</string>
<string name="low_memory" product="default" msgid="2539532364144025569">"Հեռախոսի պահոցը լիքն է: Ջնջեք մի քանի ֆայլեր` տարածություն ազատելու համար:"</string>
<plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Շարունակելու համար օգտագործեք ձեր մատնահետքը կամ էկրանի կողպումը"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Սխալ առաջացավ։ Նորից փորձեք։"</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Մատնահետքի պատկերակ"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Դեմքով ապակողպում"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Դեմքով ապակողպման հետ կապված խնդիր"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Շարունակելու համար օգտագործեք ձեր դեմքը կամ էկրանի կողպումը"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Սխալ առաջացավ։ Նորից փորձեք։"</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Դեմքի պատկերակ"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"կարդալ համաժամացման կարգավորումները"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Թույլ է տալիս հավելվածին կարդալ համաժամացման կարգավորումները հաշվի համար: Օրինակ՝ այն կարող է որոշել, արդյոք Մարդիկ հավելվածը համաժամացված է հաշվի հետ:"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Հատուկ գործառույթն օգտագործելու համար սեղմեք և 3 վայրկյան սեղմած պահեք ձայնի ուժգնության երկու կոճակները, երբ գործառույթը միացված է:"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Միացնե՞լ հատուկ գործառույթների դյուրանցումը"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ձայնի կարգավորման երկու կոճակները մի քանի վայրկյան սեղմած պահելով կմիացնեք հատուկ գործառույթները։ Դրա արդյունքում սարքի աշխատաեղանակը կարող է փոխվել։\n\nԸնթացիկ գործառույթներ՝\n<xliff:g id="SERVICE">%1$s</xliff:g>\nԸնտրված գործառույթները փոխելու համար անցեք Կարգավորումներ > Հատուկ գործառույթներ։"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Միացնե՞լ <xliff:g id="SERVICE">%1$s</xliff:g>-ի դյուրանցումը"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ձայնի կարգավորման երկու կոճակները մի քանի վայրկյան սեղմած պահելով կմիացնեք <xliff:g id="SERVICE">%1$s</xliff:g> ծառայությունը, որը հատուկ գործառույթ է։ Դրա արդյունքում սարքի աշխատաեղանակը կարող է փոխվել։\n\nԱյս դյուրանցումը մեկ այլ գործառույթով փոխելու համար անցեք Կարգավորումներ > Հատուկ գործառույթներ։"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Միացնել"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 47dd2a2..b44342a 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gunakan sidik jari atau kunci layar untuk melanjutkan"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Terjadi error. Coba lagi."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon sidik jari"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Face Unlock"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Masalah pada Face Unlock"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gunakan face lock atau kunci layar untuk melanjutkan"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Terjadi error. Coba lagi."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ikon wajah"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"baca setelan sinkronisasi"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Memungkinkan aplikasi membaca setelan sinkronisasi untuk sebuah akun. Misalnya, izin ini dapat menentukan apakah aplikasi Orang disinkronkan dengan sebuah akun."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Saat pintasan aktif, menekan kedua tombol volume selama 3 detik akan memulai fitur aksesibilitas."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Aktifkan pintasan untuk fitur aksesibilitas?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Menahan kedua tombol volume selama beberapa detik akan mengaktifkan fitur aksesibilitas. Tindakan ini dapat mengubah cara kerja perangkat Anda.\n\nFitur saat ini:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nAnda dapat mengubah fitur yang dipilih di Setelan > Aksesibilitas."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Aktifkan pintasan <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Menahan kedua tombol volume selama beberapa detik akan mengaktifkan <xliff:g id="SERVICE">%1$s</xliff:g>, yang merupakan fitur aksesibilitas. Tindakan ini dapat mengubah cara kerja perangkat Anda.\n\nAnda dapat mengubah pintasan ini ke fitur lain di Setelan > Aksesibilitas."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktifkan"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 59d0e4b..7656f88 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Notaðu fingrafar eða skjálás til að halda áfram"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Eitthvað fór úrskeiðis. Reyndu aftur."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Fingrafaratákn"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Andlitskenni"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Vandamál varðandi andlitskenni"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Notaðu andlitið eða skjálás til að halda áfram"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Eitthvað fór úrskeiðis. Reyndu aftur."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Andlitstákn"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"lesa samstillingar"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Leyfir forriti að lesa kosti samstillingar fyrir reikning. Þetta er til dæmis hægt að nota til að komast að því hvort forritið Fólk er samstillt við reikning."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Þegar flýtileiðin er virk er kveikt á aðgengiseiginleikanum með því að halda báðum hljóðstyrkshnöppunum inni í þrjár sekúndur."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Kveikja á flýtileið fyrir aðgangseiginleika?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Kveikt er á aðgengiseiginleikum þegar báðum hljóðstyrkstökkunum er haldið inni í nokkrar sekúndur. Þetta getur breytt því hvernig tækið virkar.\n\nNúverandi eiginleikar:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nÞú getur breytt völdum eiginleikum í Stillingar > Aðgengi."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Kveikja á flýtileið <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ef báðum hljóðstyrkstökkunum er haldið inni í nokkrar sekúndur er kveikt á aðgengiseiginleikanum <xliff:g id="SERVICE">%1$s</xliff:g>. Þetta getur breytt því hvernig tækið virkar.\n\nÞú getur breytt þessari flýtileið í annan eiginleika í Stillingar > Aðgengi."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Kveikja"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 7ccec0f..7131b19 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -615,8 +615,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"יש להשתמש בטביעת האצבע או בנעילת המסך כדי להמשיך"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"משהו השתבש. עליך לנסות שוב."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"סמל טביעת אצבע"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"פתיחה ע\"י זיהוי הפנים"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"בעיה בפתיחה ע\"י זיהוי הפנים"</string>
@@ -669,8 +668,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"יש להשתמש בזיהוי הפנים או בנעילת המסך כדי להמשיך"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"משהו השתבש. עליך לנסות שוב."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"סמל הפנים"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"קריאת הגדרות הסנכרון"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"מאפשרת לאפליקציה לקרוא את הגדרות הסנכרון של חשבון. לדוגמה, כך אפשר לדעת אם האפליקציה \'אנשים\' מסונכרנת עם חשבון כלשהו."</string>
@@ -1740,8 +1738,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"כשקיצור הדרך מופעל, לחיצה על שני לחצני עוצמת הקול למשך שלוש שניות מפעילה את תכונת הנגישות."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"האם להפעיל את מקש הקיצור לתכונות הנגישות?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"לחיצה ארוכה על שני לחצני עוצמת הקול למשך מספר שניות מפעילה את תכונות הנגישות. בעקבות זאת, ייתכן שאופן הפעולה של המכשיר ישתנה.\n\nהתכונות הנוכחיות:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nניתן לשנות את התכונות שנבחרו ב\'הגדרות\' > \'נגישות\'."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"האם להפעיל את מקש הקיצור של <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"לחיצה על שני מקשי עוצמת הקול למשך מספר שניות מפעילה את תכונת הנגישות <xliff:g id="SERVICE">%1$s</xliff:g>. ייתכן שאופן הפעולה של המכשיר ישתנה בעקבות זאת.\n\nאפשר לשנות את מקשי הקיצור האלה לתכונה אחרת ב\'הגדרות\' > \'נגישות\'."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"אני רוצה להפעיל"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 93fd395..df4b8bf 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"続行するには、指紋認証または画面ロックを使用してください"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"エラーが発生しました。もう一度お試しください。"</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指紋アイコン"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"顔認証"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"顔認証に関する問題"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"続行するには、顔認証または画面ロックを使用してください"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"エラーが発生しました。もう一度お試しください。"</string>
<string name="face_icon_content_description" msgid="465030547475916280">"顔アイコン"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"同期設定の読み取り"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"アカウントの同期設定の読み取りをアプリに許可します。たとえば、連絡帳アプリがアカウントと同期しているかどうかをアプリから特定できるようになります。"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ショートカットが ON の場合、両方の音量ボタンを 3 秒ほど長押しするとユーザー補助機能が起動します。"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ユーザー補助機能のショートカットを ON にしますか?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"音量大と音量小の両方のボタンを数秒ほど長押しすると、ユーザー補助機能が ON になります。この機能が ON になると、デバイスの動作が変わることがあります。\n\n現在の機能:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n選択した機能は [設定] > [ユーザー補助] で変更できます。"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> のショートカットを ON にしますか?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"音量大と音量小の両方のボタンを数秒ほど長押しすると、ユーザー補助機能の <xliff:g id="SERVICE">%1$s</xliff:g> が ON になります。この機能が ON になると、デバイスの動作が変わることがあります。\n\nこのショートカットは [設定] > [ユーザー補助] で別の機能に変更できます。"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"ON にする"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 3648788..6e7bd85 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"გასაგრძელებლად გამოიყენეთ თქვენი თითის ანაბეჭდი ან ეკრანის განბლოკვის ნიმუში"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"რაღაც შეცდომა მოხდა. ცადეთ ხელახლა."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"თითის ანაბეჭდის ხატულა"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"განბლოკვა სახით"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"პრობლემა სახით განბლოკვასთან დაკავშირებით"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"გასაგრძელებლად გამოიყენეთ თქვენი სახე ან ეკრანის განბლოკვის ნიმუში"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"რაღაც შეცდომა მოხდა. ცადეთ ხელახლა."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"სახის ხატულა"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"სინქრონიზაციის პარამეტრების წაკითხვა"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"აპს შეეძლება, წაიკითხოს ანგარიშის სინქრონიზაციის პარამეტრები. მაგალითად, მას შეეძლება განსაზღვროს, არის თუ არა People აპი სინქრონიზებული ანგარიშთან."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"თუ მალსახმობი ჩართულია, ხმის ორივე ღილაკზე 3 წამის განმავლობაში დაჭერით მარტივი წვდომის ფუნქცია ჩაირთვება."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ჩაირთოს მარტივი წვდომის ფუნქციების მალსახმობი?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ხმის ორივე ღილაკზე ხანგრძლივად დაჭერა რამდენიმე წამის განმავლობაში ჩართავს მარტივი წვდომის ფუნქციებს. ამ ქმედებამ შეიძლება შეცვალოს თქვენი მოწყობილობის მუშაობის პრინციპი.\n\nამჟამინდელი ფუნქციები:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nარჩეული ფუნქციების შეცვლა შესაძლებელია აქ: პარამეტრები > მარტივი წვდომა."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"ჩაირთოს <xliff:g id="SERVICE">%1$s</xliff:g>-ის მალსახმობი?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ხმის ორივე ღილაკზე რამდენიმე წამის განმავლობაში დაჭერით ჩაირთვება <xliff:g id="SERVICE">%1$s</xliff:g>, რომელიც მარტივი წვდომის ფუნქციაა. ამან შეიძლება შეცვალოს თქვენი მოწყობილობის მუშაობის პრინციპი.\n\nამ მალსახმობის შეცვლა სხვა ფუნქციით შეგიძლიათ აქ: პარამეტრები > აპები."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"ჩართვა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index c42e849..6493c18 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -278,7 +278,7 @@
<string name="notification_channel_physical_keyboard" msgid="5417306456125988096">"Физикалық пернетақта"</string>
<string name="notification_channel_security" msgid="8516754650348238057">"Қауіпсіздік"</string>
<string name="notification_channel_car_mode" msgid="2123919247040988436">"Көлік режимі"</string>
- <string name="notification_channel_account" msgid="6436294521740148173">"Есептік жазба күйі"</string>
+ <string name="notification_channel_account" msgid="6436294521740148173">"Аккаунт күйі"</string>
<string name="notification_channel_developer" msgid="1691059964407549150">"Әзірлеуші хабарлары"</string>
<string name="notification_channel_developer_important" msgid="7197281908918789589">"Әзірлеушілердің маңызды хабарлары"</string>
<string name="notification_channel_updates" msgid="7907863984825495278">"Жаңартылған нұсқалар"</string>
@@ -411,9 +411,9 @@
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Қолданба трансляция біткеннен кейін сақталатын бекітілген трансляцияларды жібере алатын болады. Тым жиі пайдалансаңыз, жад толып, Android TV құрылғысы баяу немесе тұрақсыз жұмыс істеуі мүмкін."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Қолданбаға хабар тарату аяқталғанда сақталатын жабысқақ хабар тарату мүмкіндігін береді. Тым көп қолдану телефон жұмысын баяулатады немесе жадты көп қолдану арқылы жұмысын тұрақсыздандырады."</string>
<string name="permlab_readContacts" msgid="8776395111787429099">"контактілерді оқу"</string>
- <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Қолданбаға планшетте сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданбалар контактілер жасалған планшеттегі есептік жазбаларды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған есептік жазбалар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string>
- <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Қолданбаға Android TV құрылғысында сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданба контактілер жасалған Android TV құрылғысындағы есептік жазбаларды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған есептік жазбалар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string>
- <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Қолданбаға телефонда сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданбалар контактілер жасалған телефондағы есептік жазбаларды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған есептік жазбалар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string>
+ <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Қолданбаға планшетте сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданбалар контактілер жасалған планшеттегі аккаунттарды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған аккаунттар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string>
+ <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Қолданбаға Android TV құрылғысында сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданба контактілер жасалған Android TV құрылғысындағы аккаунттарды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған аккаунттар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string>
+ <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Қолданбаға телефонда сақталған контактілеріңіз туралы деректерді оқуға рұқсат етеді. Қолданбалар контактілер жасалған телефондағы аккаунттарды пайдалана алады. Бұған сіз орнатқан қолданбалар арқылы жасалған аккаунттар кіруі мүмкін. Бұл рұқсат қолданбаларға контакт деректерін сақтау мүмкіндігін береді және зиянды қолданбалар контакт деректерін сіздің келісіміңізсіз бөлісуі ықтимал."</string>
<string name="permlab_writeContacts" msgid="8919430536404830430">"контактілерді өзгерту"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Қолданбаға планшетте сақталған контактілеріңіз туралы деректерді өзгертуге рұқсат етеді. Бұл рұқсат қолданбаларға контактілер туралы деректерді жоюға рұқсат береді."</string>
<string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Қолданбаға Android TV құрылғысында сақталған контактілеріңіз туралы деректерді өзгертуге рұқсат етеді. Бұл рұқсат қолданбаларға контактілер туралы деректерді жоюға рұқсат береді."</string>
@@ -499,10 +499,10 @@
<string name="permdesc_setTimeZone" product="tablet" msgid="1788868809638682503">"Қолданбаға планшеттің уақыт белдеуін өзгертуге рұқсат береді."</string>
<string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"Қолданба Android TV құрылғыңыздың уақыт белдеуін өзгерте алатын болады."</string>
<string name="permdesc_setTimeZone" product="default" msgid="4611828585759488256">"Қолданбаға телефонның уақыт белдеуін өзгертуге рұқсат береді."</string>
- <string name="permlab_getAccounts" msgid="5304317160463582791">"құрылғыдағы есептік жазбаларды табу"</string>
- <string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"Қолданбаға планшет арқылы белгілі есептік жазбалар тізімін алу мүмкіндігін береді. Сіз орнатқан қолданбалар жасақтаған есептік жазбалар да қамтылуы мүмкін."</string>
- <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Қолданба Android TV құрылғыңыз танитын есептік жазбалардың тізімін ала алатын болады. Оған сіз орнатқан қолданбалар арқылы жасалған кез келген есептік жазба кіруі мүмкін."</string>
- <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Қолданбаға телефон арқылы белгілі есептік жазбалар тізімін алу мүмкіндігін береді. Сіз орнатқан қолданбалар жасақтаған есептік жазбалар да қамтылуы мүмкін."</string>
+ <string name="permlab_getAccounts" msgid="5304317160463582791">"құрылғыдағы аккаунттарды табу"</string>
+ <string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"Қолданбаға планшет арқылы белгілі аккаунттар тізімін алу мүмкіндігін береді. Сіз орнатқан қолданбалар жасақтаған аккаунттар да қамтылуы мүмкін."</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Қолданба Android TV құрылғыңыз танитын аккаунтлардың тізімін ала алатын болады. Оған сіз орнатқан қолданбалар арқылы жасалған кез келген аккаунт кіруі мүмкін."</string>
+ <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Қолданбаға телефон арқылы белгілі аккаунттар тізімін алу мүмкіндігін береді. Сіз орнатқан қолданбалар жасақтаған аккаунттар да қамтылуы мүмкін."</string>
<string name="permlab_accessNetworkState" msgid="2349126720783633918">"желі байланыстарын көру"</string>
<string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Қолданбаға желі байланысы туралы ақпаратты, мысалы, қайсысы бар және қосылған деген сияқты, көру мүмкіндігін береді."</string>
<string name="permlab_createNetworkSockets" msgid="3224420491603590541">"желіге толық қатынасы бар"</string>
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Жалғастыру үшін саусақ ізін немесе экран құлпын пайдаланыңыз."</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Бірдеңе дұрыс болмады. Қайталап көріңіз."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Саусақ ізі белгішесі"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Бет тану"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Бет тану функциясына қатысты мәселе шықты"</string>
@@ -663,15 +662,14 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Жалғастыру үшін бетті анықтау функциясын немесе экран құлпын пайдаланыңыз."</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Бірдеңе дұрыс болмады. Қайталап көріңіз."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Бет белгішесі"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"синх параметрлерін оқу"</string>
- <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Қолданбаға есептік жазба синхрондау параметрлерін оқу мүмкіндігін береді. Мысалы, бұл арқылы People қолданбасының есептік жазбамен сихрондалғаны анықталуы мүмкін."</string>
+ <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Қолданбаға аккаунт синхрондау параметрлерін оқу мүмкіндігін береді. Мысалы, бұл арқылы People қолданбасының аккаунтмен сихрондалғаны анықталуы мүмкін."</string>
<string name="permlab_writeSyncSettings" msgid="6583154300780427399">"синх қосу және өшіру арасында ауысу"</string>
- <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"Қолданбаға есептік жазбаның синхрондау параметрлерін жөндеу мүмкіндігін береді. Мысалы, бұл People қолданбасын есептік жазбамен синхрондауды қосу үшін қолданылуы мүмкін."</string>
+ <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"Қолданбаға аккаунттың синхрондау параметрлерін жөндеу мүмкіндігін береді. Мысалы, бұл People қолданбасын аккаунтпен синхрондауды қосу үшін қолданылуы мүмкін."</string>
<string name="permlab_readSyncStats" msgid="3747407238320105332">"үйлестіру санақтық ақпаратын оқу"</string>
- <string name="permdesc_readSyncStats" msgid="3867809926567379434">"Қолданбаға есептік жазбаның синхрондалу статистикаларын, оның ішінде синхрондау шараларының тарихы және қанша дерек синхрондалғаны жайлы, оқу мүмкіндігін береді."</string>
+ <string name="permdesc_readSyncStats" msgid="3867809926567379434">"Қолданбаға аккаунттың синхрондалу статистикаларын, оның ішінде синхрондау шараларының тарихы және қанша дерек синхрондалғаны жайлы, оқу мүмкіндігін береді."</string>
<string name="permlab_sdcardRead" msgid="5791467020950064920">"ортақ жадтың мазмұнын оқу"</string>
<string name="permdesc_sdcardRead" msgid="6872973242228240382">"Қолданбаға ортақ жадтың мазмұнын оқуға мүмкіндік береді."</string>
<string name="permlab_sdcardWrite" msgid="4863021819671416668">"ортақ жадтың мазмұнын өзгерту немесе жою"</string>
@@ -694,7 +692,7 @@
<string name="permdesc_readNetworkUsageHistory" msgid="1112962304941637102">"Қолданбаға белгілі бір желілер және қолданбалар үшін журналдық желіні пайдалануды оқуға рұқсат береді."</string>
<string name="permlab_manageNetworkPolicy" msgid="6872549423152175378">"желі саясатын басқару"</string>
<string name="permdesc_manageNetworkPolicy" msgid="1865663268764673296">"Қолданбаға желілік саясаттарды басқаруға және қолданба ережелерін анықтауға рұқсат береді."</string>
- <string name="permlab_modifyNetworkAccounting" msgid="7448790834938749041">"желіні қолдану есептік жазбаларын өзгерту"</string>
+ <string name="permlab_modifyNetworkAccounting" msgid="7448790834938749041">"желіні қолдану аккаунттарын өзгерту"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5076042642247205390">"Қолданбаға қолданбалардың желіні қолдану әрекетін өзгерту мүмкіндігін береді. Қалыпты қолданбалар қолданысына арналмаған."</string>
<string name="permlab_accessNotifications" msgid="7130360248191984741">"хабарларға кіру"</string>
<string name="permdesc_accessNotifications" msgid="761730149268789668">"Қолданбаға хабарларды алу, тексеру және тазалау мүмкіндігін береді, басқа қолданбалар арқылы қойылған хабарларды қоса."</string>
@@ -928,7 +926,7 @@
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="2203704707679895487">"Телефонды ашуға <xliff:g id="NUMBER">%d</xliff:g> рет қате әрекеттендіңіз. Телефон зауыттың бастапқы параметрлеріне қайта реттеледі."</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6807200118164539589">"<xliff:g id="NUMBER">%d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="8362442730606839031">"Кескінді ұмытып қалдыңыз ба?"</string>
- <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Есептік жазбаның бекітпесін ашу"</string>
+ <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"Аккаунттың бекітпесін ашу"</string>
<string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"Тым көп кескін әрекеттері"</string>
<string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"Ашу үшін Google есептік жазбаңызбен кіріңіз."</string>
<string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"Пайдаланушы атауы (эл. пошта)"</string>
@@ -1486,8 +1484,8 @@
<string name="allow" msgid="6195617008611933762">"Рұқсат беру"</string>
<string name="deny" msgid="6632259981847676572">"Тыйым салу"</string>
<string name="permission_request_notification_title" msgid="1810025922441048273">"Рұқсат өтінілді"</string>
- <string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Рұқсат \nесептік жазба үшін <xliff:g id="ACCOUNT">%s</xliff:g> өтінілді."</string>
- <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"<xliff:g id="ACCOUNT">%2$s</xliff:g> есептік жазбасы үшін <xliff:g id="APP">%1$s</xliff:g>\nқолданбасы арқылы рұқсат сұралды."</string>
+ <string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Рұқсат \nаккаунт үшін <xliff:g id="ACCOUNT">%s</xliff:g> өтінілді."</string>
+ <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"<xliff:g id="ACCOUNT">%2$s</xliff:g> аккаунты үшін <xliff:g id="APP">%1$s</xliff:g>\nқолданбасы арқылы рұқсат сұралды."</string>
<string name="forward_intent_to_owner" msgid="4620359037192871015">"Осы қолданбаны жұмыс профиліңізден тыс пайдаланып жатырсыз"</string>
<string name="forward_intent_to_work" msgid="3620262405636021151">"Осы қолданбаны жұмыс профиліңізде пайдаланып жатырсыз"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"Енгізу әдісі"</string>
@@ -1536,13 +1534,13 @@
<string name="gpsVerifYes" msgid="3719843080744112940">"Иә"</string>
<string name="gpsVerifNo" msgid="1671201856091564741">"Жоқ"</string>
<string name="sync_too_many_deletes" msgid="6999440774578705300">"Жою шектеуінен асып кетті"</string>
- <string name="sync_too_many_deletes_desc" msgid="7409327940303504440">"Мұнда <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> жойылған <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> есептік жазбасының элементі бар. Не істеуді қалайсыз?"</string>
+ <string name="sync_too_many_deletes_desc" msgid="7409327940303504440">"Мұнда <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> жойылған <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> аккаунтының элементі бар. Не істеуді қалайсыз?"</string>
<string name="sync_really_delete" msgid="5657871730315579051">"Бұл нәрселер жойылсын"</string>
<string name="sync_undo_deletes" msgid="5786033331266418896">"Жойылғандарды кері орындау"</string>
<string name="sync_do_nothing" msgid="4528734662446469646">"Қазір ешқандай әрекет жасамаңыз"</string>
- <string name="choose_account_label" msgid="5557833752759831548">"Есептік жазба таңдау"</string>
- <string name="add_account_label" msgid="4067610644298737417">"Есептік жазба қосу"</string>
- <string name="add_account_button_label" msgid="322390749416414097">"Есептік жазба қосу."</string>
+ <string name="choose_account_label" msgid="5557833752759831548">"Аккаунт таңдау"</string>
+ <string name="add_account_label" msgid="4067610644298737417">"Аккаунт қосу"</string>
+ <string name="add_account_button_label" msgid="322390749416414097">"Аккаунт қосу."</string>
<string name="number_picker_increment_button" msgid="7621013714795186298">"Арттыру"</string>
<string name="number_picker_decrement_button" msgid="5116948444762708204">"Азайту"</string>
<string name="number_picker_increment_scroll_mode" msgid="8403893549806805985">"<xliff:g id="VALUE">%s</xliff:g> түймесін басып тұрыңыз."</string>
@@ -1670,13 +1668,13 @@
<string name="kg_invalid_puk" msgid="4809502818518963344">"Дұрыс PUK кодын қайта енгізіңіз. Әрекеттерді қайталау SIM картасының істен шығуына себеп болады."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="4705368340409816254">"PIN коды сәйкес емес."</string>
<string name="kg_login_too_many_attempts" msgid="699292728290654121">"Тым көп кескін әрекеттері"</string>
- <string name="kg_login_instructions" msgid="3619844310339066827">"Ашу үшін Google есептік жазбасы арқылы кіріңіз."</string>
+ <string name="kg_login_instructions" msgid="3619844310339066827">"Ашу үшін Google аккаунты арқылы кіріңіз."</string>
<string name="kg_login_username_hint" msgid="1765453775467133251">"Пайдаланушы атауы (эл. пошта)"</string>
<string name="kg_login_password_hint" msgid="3330530727273164402">"Құпия сөз"</string>
<string name="kg_login_submit_button" msgid="893611277617096870">"Кіру"</string>
<string name="kg_login_invalid_input" msgid="8292367491901220210">"Пайдаланушы атауы немесе кілтсөз жарамсыз."</string>
<string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"Пайдаланушы атауын немесе кілтсөзді ұмытып қалдыңыз ба?\n"<b>"google.com/accounts/recovery"</b>" веб-сайтына кіріңіз."</string>
- <string name="kg_login_checking_password" msgid="4676010303243317253">"Есептік жазбаны тексеруде…"</string>
+ <string name="kg_login_checking_password" msgid="4676010303243317253">"Аккаунтты тексеруде…"</string>
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"PIN кодты <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате тердіңіз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін қайталаңыз."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"Құпия сөзді <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате тердіңіз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін қайталаңыз."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="7357404233979139075">"Құлыпты ашу өрнегін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате салдыңыз. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
@@ -1686,9 +1684,9 @@
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"Планшетті ашуға <xliff:g id="NUMBER">%d</xliff:g> рет қате әрекеттендіңіз. Планшет бастапқы зауыттық параметрлеріне қайта реттеледі."</string>
<string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"Android TV құрылғыңыздың құлпын <xliff:g id="NUMBER">%d</xliff:g> рет дұрыс ашпадыңыз. Енді Android TV құрылғыңыздың зауыттық әдепкі параметрлері қайтарылады."</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"Телефонды ашуға <xliff:g id="NUMBER">%d</xliff:g> рет қате әрекеттендіңіз. Телефон бастапқы зауыттық параметрлеріне қайта реттеледі."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"Бекітпені ашу кескінін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате сыздыңыз. After <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін планшетіңізді есептік жазба арқылы ашу өтінішін аласыз.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"Бекітпені ашу кескінін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате сыздыңыз. After <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін планшетіңізді аккаунт арқылы ашу өтінішін аласыз.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string>
<string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"Құлыпты ашу өрнегін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет дұрыс сызбадыңыз. Енді тағы <xliff:g id="NUMBER_1">%2$d</xliff:g> рет қателессеңіз, Android TV құрылғыңыздың құлпын ашу үшін есептік жазбаңызға кіру керек болады.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайталап көріңіз."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Бекітпені ашу кескінін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате сыздыңыз. <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін телефоныңызды есептік жазба арқылы ашу өтінішін аласыз. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Бекітпені ашу кескінін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате сыздыңыз. <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін телефоныңызды аккаунт арқылы ашу өтінішін аласыз. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string>
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Жою"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Дыбыс деңгейін ұсынылған деңгейден көтеру керек пе?\n\nЖоғары дыбыс деңгейінде ұзақ кезеңдер бойы тыңдау есту қабілетіңізге зиян тигізуі мүмкін."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Түймелер тіркесімі қосулы кезде, екі дыбыс түймесін 3 секунд басып тұрсаңыз, \"Арнайы мүмкіндіктер\" функциясы іске қосылады."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Арнайы мүмкіндіктердің жылдам пәрмені іске қосылсын ба?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Дыбыс деңгейі пернелерін бірнеше секунд басып тұрсаңыз, арнайы мүмкіндіктер іске қосылады. Бұл – құрылғының жұмысына әсер етуі мүмкін.\n\nҚазіргі функциялар:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТаңдалған функцияларды \"Параметрлер > Арнайы мүмкіндіктер\" бөлімінен өзгерте аласыз."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> жылдам пәрмені іске қосылсын ба?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Дыбыс деңгейі пернелерін бірнеше секунд басып тұрсаңыз, <xliff:g id="SERVICE">%1$s</xliff:g> арнайы қызметі іске қосылады. Бұл – құрылғының жүмысына әсер етуі мүмкін.\n\nБұл таңбашаны басқа функцияға \"Параметрлер > Арнайы мүмкіндіктер\" бөлімінен өзгерте аласыз."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Қосылсын"</string>
@@ -1970,8 +1967,8 @@
<string name="importance_from_user" msgid="2782756722448800447">"Сіз осы хабарландырулардың маңыздылығын орнатасыз."</string>
<string name="importance_from_person" msgid="4235804979664465383">"Қатысты адамдарға байланысты бұл маңызды."</string>
<string name="notification_history_title_placeholder" msgid="7748630986182249599">"Арнаулы хабар хабарландыруы"</string>
- <string name="user_creation_account_exists" msgid="2239146360099708035">"<xliff:g id="APP">%1$s</xliff:g> қолданбасына <xliff:g id="ACCOUNT">%2$s</xliff:g> есептік жазбасы бар жаңа пайдаланушы (мұндай есептік жазбаға ие пайдаланушы бұрыннан бар) жасауға рұқсат етілсін бе?"</string>
- <string name="user_creation_adding" msgid="7305185499667958364">"<xliff:g id="APP">%1$s</xliff:g> қолданбасына <xliff:g id="ACCOUNT">%2$s</xliff:g> есептік жазбасы бар жаңа пайдаланушы жасауға рұқсат етілсін бе?"</string>
+ <string name="user_creation_account_exists" msgid="2239146360099708035">"<xliff:g id="APP">%1$s</xliff:g> қолданбасына <xliff:g id="ACCOUNT">%2$s</xliff:g> аккаунты бар жаңа пайдаланушы (мұндай аккаунтқа ие пайдаланушы бұрыннан бар) жасауға рұқсат етілсін бе?"</string>
+ <string name="user_creation_adding" msgid="7305185499667958364">"<xliff:g id="APP">%1$s</xliff:g> қолданбасына <xliff:g id="ACCOUNT">%2$s</xliff:g> аккаунты бар жаңа пайдаланушы жасауға рұқсат етілсін бе?"</string>
<string name="language_selection_title" msgid="52674936078683285">"Тіл қосу"</string>
<string name="country_selection_title" msgid="5221495687299014379">"Аймақ параметрі"</string>
<string name="search_language_hint" msgid="7004225294308793583">"Тіл атауын теріңіз"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 6418a6e..9949e12 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ប្រើការចាក់សោអេក្រង់ ឬស្នាមម្រាមដៃរបស់អ្នក ដើម្បីបន្ត"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"មានអ្វីមួយខុសប្រក្រតី។ សូមព្យាយាមម្ដងទៀត។"</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"រូបស្នាមម្រាមដៃ"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ដោះសោតាមទម្រង់មុខ"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"មានបញ្ហាពាក់ព័ន្ធនឹងមុខងារដោះសោតាមទម្រង់មុខ"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ប្រើការចាក់សោអេក្រង់ ឬមុខរបស់អ្នក ដើម្បីបន្ត"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"មានអ្វីមួយខុសប្រក្រតី។ សូមព្យាយាមម្ដងទៀត។"</string>
<string name="face_icon_content_description" msgid="465030547475916280">"រូបផ្ទៃមុខ"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"អានការកំណត់ធ្វើសមកាលកម្ម"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ឲ្យកម្មវិធីអានការកំណត់ធ្វើសមកាលកម្មសម្រាប់គណនី។ ឧទាហរណ៍ វាអាចកំណត់ថាតើកម្មវិធីត្រូវបានបើកជាមួយគណនីដែរឬទេ។"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"នៅពេលបើកផ្លូវកាត់ ការចុចប៊ូតុងកម្រិតសំឡេងទាំងពីររយៈពេល 3 វិនាទីនឹងចាប់ផ្តើមមុខងារភាពងាយប្រើ។"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"បើកផ្លូវកាត់សម្រាប់មុខងារភាពងាយស្រួលឬ?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ការសង្កត់គ្រាប់ចុចកម្រិតសំឡេងទាំងពីរឱ្យជាប់រយៈពេលពីរបីវិនាទីនឹងបើកមុខងារភាពងាយប្រើ។ ការធ្វើបែបនេះអាចផ្លាស់ប្ដូររបៀបដែលឧបករណ៍របស់អ្នកដំណើរការ។\n\nមុខងារបច្ចុប្បន្ន៖\n<xliff:g id="SERVICE">%1$s</xliff:g>\nអ្នកអាចប្ដូរមុខងារដែលបានជ្រើសរើសនៅក្នុងការកំណត់ > ភាពងាយស្រួល។"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"បើកផ្លូវកាត់ <xliff:g id="SERVICE">%1$s</xliff:g> ឬ?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ការសង្កត់គ្រាប់ចុចកម្រិតសំឡេងទាំងពីរឱ្យជាប់រយៈពេលពីរបីវិនាទីនឹងបើក <xliff:g id="SERVICE">%1$s</xliff:g> ដែលជាមុខងារភាពងាយប្រើ។ ការធ្វើបែបនេះអាចផ្លាស់ប្ដូររបៀបដែលឧបករណ៍របស់អ្នកដំណើរការ។\n\nអ្នកអាចប្ដូរផ្លូវកាត់នេះទៅមុខងារផ្សេងទៀតនៅក្នុងការកំណត់ > ភាពងាយស្រួល។"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"បើក"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 6c21e3e..2d7df35 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ಮುಂದುವರಿಸಲು ಫಿಂಗರ್ ಪ್ರಿಂಟ್ ಅಥವಾ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿ"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"ಏನೋ ತಪ್ಪಾಗಿದೆ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಐಕಾನ್"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ಫೇಸ್ ಅನ್ಲಾಕ್"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ಫೇಸ್ ಅನ್ಲಾಕ್ ಕುರಿತು ಸಮಸ್ಯೆ ಇದೆ"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ಮುಂದುವರಿಸಲು ನಿಮ್ಮ ಮುಖ ಅಥವಾ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿ"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"ಏನೋ ತಪ್ಪಾಗಿದೆ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"ಮುಖದ ಐಕಾನ್"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"ಸಿಂಕ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ರೀಡ್ ಮಾಡು"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ಒಂದು ಖಾತೆಯ ಸಿಂಕ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಉದಾಹರಣೆಗೆ, ಖಾತೆಯೊಂದಿಗೆ ಜನರ ಅಪ್ಲಿಕೇಶನ್ ಸಿಂಕ್ ಮಾಡಲಾಗಿದೆಯೇ ಎಂಬುದನ್ನು ಇದು ನಿರ್ಧರಿಸಬಹುದು."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ಶಾರ್ಟ್ಕಟ್ ಆನ್ ಆಗಿರುವಾಗ, ಎರಡೂ ವಾಲ್ಯೂಮ್ ಬಟನ್ಗಳನ್ನು 3 ಸೆಕೆಂಡುಗಳ ಕಾಲ ಒತ್ತಿದರೆ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯವೊಂದು ಪ್ರಾರಂಭವಾಗುತ್ತದೆ."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯಗಳಿಗಾಗಿ ಶಾರ್ಟ್ಕಟ್ ಆನ್ ಮಾಡಬೇಕೇ?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ಎರಡೂ ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಕೆಲವು ಸೆಕೆಂಡುಗಳ ಕಾಲ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳುವುದರಿಂದ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯಗಳು ಆನ್ ಆಗುತ್ತವೆ. ಇದು ನಿಮ್ಮ ಸಾಧನವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಬದಲಾಯಿಸಬಹುದು.\n\n ಪ್ರಸ್ತುತ ವೈಶಿಷ್ಟ್ಯಗಳು:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿಯಲ್ಲಿ ಆಯ್ದ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನೀವು ಬದಲಾಯಿಸಬಹುದು."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"ಶಾರ್ಟ್ಕಟ್ <xliff:g id="SERVICE">%1$s</xliff:g>ಆನ್ ಮಾಡಬೇಕೇ?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ಎರಡೂ ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಕೆಲವು ಸೆಕೆಂಡುಗಳ ಕಾಲ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳುವುದರಿಂದ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯವಾದ <xliff:g id="SERVICE">%1$s</xliff:g> ಆನ್ ಆಗುತ್ತದೆ. ಇದು ನಿಮ್ಮ ಸಾಧನವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಬದಲಾಯಿಸಬಹುದು.\n\nನೀವು ಈ ಶಾರ್ಟ್ಕಟ್ ಅನ್ನು ಸೆಟ್ಟಿಂಗ್ಗಳು ಮತ್ತು ಅಕ್ಸೆಸಿಬಿಲಿಟಿಯಲ್ಲಿನ ಮತ್ತೊಂದು ವೈಶಿಷ್ಟ್ಯಕ್ಕೆ ಬದಲಾಯಿಸಬಹುದು."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"ಆನ್ ಮಾಡಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 4657d52..04b17da 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"계속하려면 지문이나 화면 잠금을 사용하세요"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"문제가 발생했습니다. 다시 시도해 보세요."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"지문 아이콘"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"얼굴 인식 잠금 해제"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"얼굴 인식 잠금 해제 문제"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"계속하려면 얼굴 또는 화면 잠금을 사용하세요"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"문제가 발생했습니다. 다시 시도해 보세요."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"얼굴 아이콘"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"동기화 설정 읽기"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"앱이 계정의 동기화 설정을 읽을 수 있도록 허용합니다. 예를 들어, 계정에서 주소록 앱을 동기화할지 여부를 확인할 수 있습니다."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"단축키가 사용 설정된 경우 볼륨 버튼 두 개를 동시에 3초간 누르면 접근성 기능이 시작됩니다."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"접근성 기능 바로가기를 사용 설정하시겠습니까?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"볼륨 키 2개를 몇 초 동안 길게 누르면 접근성 기능이 사용 설정됩니다. 이때 기기 작동 방식이 달라질 수 있습니다.\n\n현재 기능:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n설정 > 접근성에서 선택한 기능을 변경할 수 있습니다."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> 바로가기를 사용 설정하시겠습니까?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"볼륨 키 2개를 몇 초 동안 길게 누르면 <xliff:g id="SERVICE">%1$s</xliff:g> 접근성 기능이 사용 설정됩니다. 이렇게 되면 기기 작동 방식이 달라질 수 있습니다.\n\n설정 > 접근성에서 이 단축키를 다른 기능으로 변경할 수 있습니다."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"사용"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 2458e11..1f869aa 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Улантуу үчүн манжа изин же экрандын кулпусун колдонуңуз"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Бир жерден ката кетти. Кайра аракет кылыңыз."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Манжа изинин сүрөтчөсү"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Жүзүнөн таанып ачуу"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Жүзүнөн таанып ачуу функциясында маселе келип чыкты"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Улантуу үчүн жүзүңүздү же экрандын кулпусун колдонуңуз"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Бир жерден ката кетти. Кайра аракет кылыңыз."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Жүздүн сүрөтчөсү"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"шайкештирүү жөндөөлөрүн окуу"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Колдонмого эсеп менен синхрондошуу тууралоолорун окуганга уруксат берет. Мисалы, Кишилер колдонмосу эсеп менен синхрондошкондугун аныктай алат."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Атайын мүмкүнчүлүктөр функциясын пайдалануу үчүн ал күйгүзүлгөндө, үндү катуулатып/акырындаткан эки баскычты тең 3 секунддай коё бербей басып туруңуз."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Атайын мүмкүнчүлүктөрдүн ыкчам баскычын иштетесизби?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Атайын мүмкүнчүлүктөр функциясын иштетүү үчүн үндү чоңойтуп/кичирейтүү баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nУчурдагы функциялар:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТандалган функцияларды өзгөртүү үчүн Жөндөөлөр > Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> ыкчам баскычын иштетесизби?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"<xliff:g id="SERVICE">%1$s</xliff:g> кызматын иштетүү үчүн үндү чоңойтуп/кичирейтүү баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nБаскычтардын ушул айкалышын башка функцияга дайындоо үчүн, Жөндөөлөр > Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Ооба"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 935df5a..7484246 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ໃຊ້ລາຍນິ້ວມື ຫຼື ການລັອກໜ້າຈໍຂອງທ່ານເພື່ອດຳເນີນການຕໍ່"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"ມີບາງຢ່າງຜິດພາດເກີດຂຶ້ນ. ກະລຸນາລອງໃໝ່."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ໄອຄອນລາຍນິ້ວມື"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ປົດລັອກດ້ວຍໜ້າ"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ເກີດບັນຫາກັບການປົດລັອກດ້ວຍໜ້າ"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ໃຊ້ໃບໜ້າ ຫຼື ການລັອກໜ້າຈໍຂອງທ່ານເພື່ອດຳເນີນການຕໍ່"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"ມີບາງຢ່າງຜິດພາດເກີດຂຶ້ນ. ກະລຸນາລອງໃໝ່."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"ໄອຄອນໃບໜ້າ"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"ອ່ານການຕັ້ງຄ່າຊິ້ງຂໍ້ມູນ"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ອະນຸຍາດໃຫ້ແອັບຯ ອ່ານການຕັ້ງຄ່າການຊິ້ງຂໍ້ມູນຂອງບັນຊີໄດ້. ຕົວຢ່າງເຊັ່ນ: ມັນຈະສາມາດກວດສອບໄດ້ແອັບຯ People ຖືກຊິ້ງຂໍ້ມູນກັບບັນຊີໃດນຶ່ງແລ້ວຫຼືຍັງ."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ເມື່ອເປີດໃຊ້ທາງລັດແລ້ວ, ການກົດປຸ່ມລະດັບສຽງທັງສອງຄ້າງໄວ້ 3 ວິນາທີຈະເປັນການເລີ່ມຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງ."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ເປີດໃຊ້ທາງລັດສຳລັບຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງບໍ?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ກົດປຸ່ມລະດັບສຽງທັງສອງຄ້າງໄວ້ສອງສາມວິນາທີເພື່ອເປີດໃຊ້ຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງ. ນີ້ອາດປ່ຽນວິທີການເຮັດວຽກຂອງອຸປະກອນທ່ານ.\n\nຄຸນສົມບັດປັດຈຸບັນ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nທ່ານສາມາດປ່ຽນຄຸນສົມບັດທີ່ເລືອກໄດ້ໃນການຕັ້ງຄ່າ > ການຊ່ວຍເຂົ້າເຖິງ."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"ເປີດໃຊ້ທາງລັດ <xliff:g id="SERVICE">%1$s</xliff:g> ບໍ?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ກົດປຸ່ມລະດັບສຽງທັງສອງຄ້າງໄວ້ສອງສາມວິນາທີເພື່ອເປີດໃຊ້ <xliff:g id="SERVICE">%1$s</xliff:g>, ຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງ. ນີ້ອາດປ່ຽນວິທີການເຮັດວຽກຂອງອຸປະກອນທ່ານ.\n\nທ່ານສາມາດປ່ຽນທາງລັດນີ້ເປັນຄຸນສົມບັດອື່ນໄດ້ໃນການຕັ້ງຄ່າ > ການຊ່ວຍເຂົ້າເຖິງ."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"ເປີດໃຊ້"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 7317f5f..eb5f2a6 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -615,8 +615,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Jei norite tęsti, naudokite kontrolinį kodą arba ekrano užraktą"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Kažkas nepavyko. Bandykite dar kartą."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Piršto antspaudo piktograma"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Atrakinimas pagal veidą"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Su atrakinimu pagal veidą susijusi problema"</string>
@@ -669,8 +668,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Jei norite tęsti, naudokite veido atpažinimo funkciją arba ekrano užraktą"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Kažkas nepavyko. Bandykite dar kartą."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Veido pkt."</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"skaityti sinchronizavimo nustatymus"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Leidžiama programai skaityti ir sinchronizuoti paskyros nustatymus. Pvz., taip gali būti nustatoma, ar su paskyra sinchronizuota Žmonių programa."</string>
@@ -1740,8 +1738,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kai spartusis klavišas įjungtas, paspaudus abu garsumo mygtukus ir palaikius 3 sekundes bus įjungta pritaikymo neįgaliesiems funkcija."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Įjungti pritaikymo neįgaliesiems funkcijų spartųjį klavišą?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Paspaudus abu garsumo klavišus ir palaikius kelias sekundes įjungiamos pritaikymo neįgaliesiems funkcijos. Tai gali pakeisti įrenginio veikimą.\n\nDabartinės funkcijos:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPasirinktas funkcijas galite pakeisti skiltyje „Nustatymai“ > „Pritaikomumas“."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • „<xliff:g id="SERVICE">%1$s</xliff:g>“\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Įjungti „<xliff:g id="SERVICE">%1$s</xliff:g>“ spartųjį klavišą?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Paspaudus abu garsumo klavišus ir palaikius kelias sekundes įjungiama pritaikymo neįgaliesiems funkcija „<xliff:g id="SERVICE">%1$s</xliff:g>“. Tai gali pakeisti įrenginio veikimą.\n\nGalite pakeisti šį spartųjį klavišą į kitą funkciją skiltyje „Nustatymai“ > „Pritaikomumas“."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Įjungti"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index db4587e..d988a6b 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -612,8 +612,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Izmantojiet pirksta nospiedumu vai ekrāna bloķēšanas opciju, lai turpinātu"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Radās kļūda. Mēģiniet vēlreiz."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Pirksta nospieduma ikona"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Autorizācija pēc sejas"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problēma ar autorizāciju pēc sejas"</string>
@@ -666,8 +665,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Izmantojiet autorizāciju pēc sejas vai ekrāna bloķēšanas opciju, lai turpinātu"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Radās kļūda. Mēģiniet vēlreiz."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Sejas ikona"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"lasīt sinhronizācijas iestatījumus"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Ļauj lietotnei lasīt konta sinhronizācijas iestatījumus. Piemēram, šādi var noteikt, vai lietotne Personas ir sinhronizēta ar kontu."</string>
@@ -1718,8 +1716,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kad īsinājumtaustiņš ir ieslēgts, nospiežot abas skaļuma pogas un 3 sekundes turot tās, tiks aktivizēta pieejamības funkcija."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vai ieslēgt pieejamības funkciju saīsni?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Turot nospiestus abus skaļuma taustiņus dažas sekundes, tiek ieslēgtas pieejamības funkcijas. Tas var mainīt ierīces darbību.\n\nPašreizējās funkcijas:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nAtlasītās funkcijas varat mainīt šeit: Iestatījumi > Pieejamība."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Vai ieslēgt <xliff:g id="SERVICE">%1$s</xliff:g> saīsni?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Turot nospiestus abus skaļuma taustiņus dažas sekundes, tiek ieslēgta pieejamības funkcija <xliff:g id="SERVICE">%1$s</xliff:g>. Tas var mainīt ierīces darbību.\n\nŠo saīsni uz citu funkciju varat mainīt šeit: Iestatījumi > Pieejamība."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Ieslēgt"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 09f6230..0b01a09 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Користете го вашиот отпечаток или заклучување екран за да продолжите"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Нешто не е во ред. Обидете се повторно."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Икона за отпечатоци"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Отклучување со лик"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Проблем со „Отклучување со лик“"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Користете отклучување со лик или заклучување екран за да продолжите"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Нешто не е во ред. Обидете се повторно."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Икона"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"чита поставки за синхронизација"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Овозможува апликацијата да ги чита поставките за синхронизирање на сметка. На пример, така може да се утврди дали апликацијата „Луѓе“ е синхронизирана со сметка."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Кога е вклучена кратенката, ако ги притиснете двете копчиња за јачина на звук во времетраење од 3 секунди, ќе се стартува функција за пристапност."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Да се вклучи кратенка за функциите за пристапност?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ако ги задржите притиснати двете копчиња за јачина на звук неколку секунди, ќе се вклучат функциите за пристапност. Ова може да го промени начинот на функционирање на уредот.\n\nТековни функции:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nМоже да ги промените избраните функции во „Поставки > Пристапност“."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Да се вклучи кратенка за <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ако ги задржите притиснати двете копчиња за јачина на звук неколку секунди, ќе се вклучи функцијата за пристапност <xliff:g id="SERVICE">%1$s</xliff:g>. Ова може да го промени начинот на функционирање на уредот.\n\nМоже да ја измените кратенкава да биде за друга функција во „Поставки > Пристапност“."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Вклучи"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index f36e02f..ed35ce4 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -306,7 +306,7 @@
<string name="permgroupdesc_contacts" msgid="9163927941244182567">"നിങ്ങളുടെ കോൺടാക്റ്റുകൾ ആക്സസ്സ് ചെയ്യുക"</string>
<string name="permgrouplab_location" msgid="1858277002233964394">"ലൊക്കേഷൻ"</string>
<string name="permgroupdesc_location" msgid="1995955142118450685">"ഈ ഉപകരണത്തിന്റെ ലൊക്കേഷൻ ആക്സസ് ചെയ്യാൻ"</string>
- <string name="permgrouplab_calendar" msgid="6426860926123033230">"കലണ്ടർ"</string>
+ <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string>
<string name="permgroupdesc_calendar" msgid="6762751063361489379">"നിങ്ങളുടെ കലണ്ടർ ആക്സസ്സ് ചെയ്യുക"</string>
<string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
<string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS സന്ദേശങ്ങൾ അയയ്ക്കുകയും കാണുകയും ചെയ്യുക"</string>
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"തുടരാൻ നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് അല്ലെങ്കിൽ സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"എന്തോ കുഴപ്പമുണ്ടായി. വീണ്ടും ശ്രമിക്കുക."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ഫിംഗർപ്രിന്റ് ഐക്കൺ"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ഫെയ്സ് അൺലോക്ക്"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ഫെയ്സ് അൺലോക്കുമായി ബന്ധപ്പെട്ട പ്രശ്നം"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"തുടരാൻ നിങ്ങളുടെ മുഖം അല്ലെങ്കിൽ സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"എന്തോ കുഴപ്പമുണ്ടായി. വീണ്ടും ശ്രമിക്കുക."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"മുഖത്തിന്റെ ഐക്കൺ"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"സമന്വയ ക്രമീകരണങ്ങൾ റീഡുചെയ്യുക"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ഒരു അക്കൗണ്ടിനായി സമന്വയ ക്രമീകരണങ്ങൾ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഉദാഹരണത്തിന്, ആളുകൾ അപ്ലിക്കേഷൻ ഒരു അക്കൗണ്ടിൽ സമന്വയിപ്പിച്ചിട്ടുണ്ടോയെന്നത് നിർണ്ണയിക്കാൻ ഇതിനാകും."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"കുറുക്കുവഴി ഓണായിരിക്കുമ്പോൾ, രണ്ട് വോളിയം ബട്ടണുകളും 3 സെക്കൻഡ് നേരത്തേക്ക് അമർത്തുന്നത് ഉപയോഗസഹായി ഫീച്ചർ ആരംഭിക്കും."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ഉപയോഗസഹായി ഫീച്ചറുകൾക്കുള്ള കുറുക്കുവഴി ഓണാക്കണോ?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"രണ്ട് വോളിയം കീകളും അൽപ്പ നേരത്തേക്ക് അമർത്തിപ്പിടിക്കുന്നത്, ഉപയോഗസഹായി ഫീച്ചറുകൾ ഓണാക്കുന്നു. നിങ്ങളുടെ ഉപകരണം പ്രവർത്തിക്കുന്ന രീതിയെ ഇത് മാറ്റിയേക്കാം.\n\nനിലവിലുള്ള ഫീച്ചറുകൾ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nതിരഞ്ഞെടുത്ത ഫീച്ചറുകൾ ക്രമീകരണം > ഉപയോഗസഹായി എന്നതിൽ മാറ്റാനാവും."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> കുറുക്കുവഴി ഓണാക്കണോ?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"രണ്ട് വോളിയം കീകളും അൽപ്പ നേരത്തേക്ക് അമർത്തിപ്പിടിക്കുന്നത് ഉപയോഗസഹായി ഫീച്ചറായ <xliff:g id="SERVICE">%1$s</xliff:g> എന്നതിനെ ഓണാക്കുന്നു. നിങ്ങളുടെ ഉപകരണം പ്രവർത്തിക്കുന്ന വിധം ഇത് മാറ്റിയേക്കാം.\n\nക്രമീകരണം > ഉപയോഗസഹായി എന്നതിലെ മറ്റൊരു ഫീച്ചറിലേക്ക് നിങ്ങൾക്ക് ഈ കുറുക്കുവഴി മാറ്റാനാവും."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"ഓണാക്കുക"</string>
@@ -2014,7 +2011,7 @@
<string name="app_category_image" msgid="7307840291864213007">"ഫോട്ടോകളും ചിത്രങ്ങളും"</string>
<string name="app_category_social" msgid="2278269325488344054">"സാമൂഹിക ആപ്സുകളും ആശയവിനിമയവും"</string>
<string name="app_category_news" msgid="1172762719574964544">"വാർത്തകളും മാസികകളും"</string>
- <string name="app_category_maps" msgid="6395725487922533156">"മാപ്പുകളും നാവിഗേഷനും"</string>
+ <string name="app_category_maps" msgid="6395725487922533156">"Maps & Navigation"</string>
<string name="app_category_productivity" msgid="1844422703029557883">"ഉല്പ്പാദനക്ഷമത"</string>
<string name="app_category_accessibility" msgid="6643521607848547683">"ഉപയോഗസഹായി"</string>
<string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"ഉപകരണ സ്റ്റോറേജ്"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index e35571f..7140487 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Үргэлжлүүлэхийн тулд хурууны хээ эсвэл дэлгэцийн түгжээгээ ашиглана уу"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Алдаа гарлаа. Дахин оролдоно уу."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Хурууны хээний дүрс"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Царайгаар түгжээ тайлах"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Царайгаар түгжээ тайлахтай холбоотой асуудал"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Үргэлжлүүлэхийн тулд царай эсвэл дэлгэцийн түгжээгээ ашиглана уу"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Алдаа гарлаа. Дахин оролдоно уу."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Царайны дүрс тэмдэг"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"синк тохиргоог унших"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Апп нь бүртгэлийн синк тохиргоог унших боломжтой. Жишээ нь энэ нь Хүмүүс апп бүртгэлтэй синк хийгдсэн эсэхийг тодорхойлох боломжтой."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Товчлол асаалттай үед дууны түвшний хоёр товчлуурыг хамтад нь 3 секунд дарснаар хандалтын онцлогийг эхлүүлнэ."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Хандалтын онцлогуудын товчлолыг асаах уу?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Дууны түвшний түлхүүрийг хэдэн секундийн турш зэрэг дарснаар хандалтын онцлогууд асна. Энэ нь таны төхөөрөмжийн ажиллах зарчмыг өөрчилж болзошгүй.\n\nОдоогийн онцлогууд:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТа сонгосон онцлогуудыг Тохиргоо > Хандалт хэсэгт өөрчлөх боломжтой."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g>-н товчлолыг асаах уу?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Дууны түвшний түлхүүрийг хэдэн секундийн турш зэрэг дарах нь хандалтын онцлог болох <xliff:g id="SERVICE">%1$s</xliff:g>-г асаадаг. Энэ нь таны төхөөрөмжийн ажиллах зарчмыг өөрчилж болзошгүй.\n\nТа Тохиргоо > Хандалт хэсэгт энэ товчлолыг өөр онцлогт оноож өөрчлөх боломжтой."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Асаах"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 45762cd..0a8f94f 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"पुढे सुरू ठेवण्यासाठी तुमचे फिंगरप्रिंट किंवा स्क्रीन लॉक वापरा"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"काहीतरी चूक झाली. पुन्हा प्रयत्न करा."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"फिंगरप्रिंट आयकन"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"फेस अनलॉक"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"फेस अनलॉकसंबंधित समस्या"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"पुढे सुरू ठेवण्यासाठी तुमचा चेहरा किंवा स्क्रीन लॉक वापरा"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"काहीतरी चूक झाली. पुन्हा प्रयत्न करा."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"चेहरा आयकन"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"सिंक सेटिंग्ज वाचा"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"खात्याच्या सिंक सेटिंग्ज वाचण्यासाठी अॅप ला अनुमती देते. उदाहरणार्थ, हे खात्यासह लोकांचा अॅप संकालित केला आहे किंवा नाही हे निर्धारित करू शकते."</string>
@@ -1020,7 +1018,7 @@
<string name="permlab_writeGeolocationPermissions" msgid="8605631647492879449">"ब्राउझर भौगोलिक स्थान परवानग्या सुधारित करा"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"ब्राउझरच्या भौगोलिक स्थान परवानग्या सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स यादृच्छिक वेबसाइटवर स्थान माहिती पाठविण्यास अनुमती देण्यासाठी याचा वापर करू शकतात."</string>
<string name="save_password_message" msgid="2146409467245462965">"ब्राउझरने हा पासवर्ड लक्षात ठेवावा असे तुम्ही इच्छिता?"</string>
- <string name="save_password_notnow" msgid="2878327088951240061">"आत्ता नाही"</string>
+ <string name="save_password_notnow" msgid="2878327088951240061">"आता नको"</string>
<string name="save_password_remember" msgid="6490888932657708341">"लक्षात ठेवा"</string>
<string name="save_password_never" msgid="6776808375903410659">"कधीही नाही"</string>
<string name="open_permission_deny" msgid="5136793905306987251">"तुम्हाला हे पृष्ठ उघडण्याची परवानगी नाही."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"शॉर्टकट सुरू असताना, दोन्ही व्हॉल्यूम बटणे तीन सेकंदांसाठी दाबून ठेवल्याने अॅक्सेसिबिलिटी वैशिष्ट्य सुरू होईल."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"अॅक्सेसिबिलिटी वैशिष्ट्यांसाठी शॉर्टकट सुरू करायचा आहे का?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"दोन्ही व्हॉल्यूम की काही सेकंद धरून ठेवल्याने अॅक्सेसिबिलिटी वैशिष्ट्ये सुरू होतात. यामुळे तुमचे डिव्हाइस कसे काम करते हे पूर्णपणे बदलते.\n\nसध्याची वैशिष्ट्ये:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nतुम्ही हा शॉर्टकट सेटिंग्ज > अॅक्सेसिबिलिटी मध्ये बदलू शकता."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> शॉर्टकट सुरू करायचा आहे का?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"दोन्ही व्हॉल्यूम की काही सेकंद धरून ठेवल्याने <xliff:g id="SERVICE">%1$s</xliff:g>, एक अॅक्सेसिबिलिटी वैशिष्ट्य सुरू होते. यामुळे तुमचे डिव्हाइस कसे काम करते हे पूर्णपणे बदलते.\n\nतुम्ही हा शॉर्टकट सेटिंग्ज > अॅक्सेसिबिलिटी मध्ये बदलू शकता."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"सुरू करा"</string>
@@ -2044,7 +2041,7 @@
<string name="autofill_update_title_with_3types" msgid="1312232153076212291">"हे आयटम "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> आणि <xliff:g id="TYPE_2">%3$s</xliff:g> मध्ये अपडेट करायचे का?"</string>
<string name="autofill_save_yes" msgid="8035743017382012850">"सेव्ह करा"</string>
<string name="autofill_save_no" msgid="9212826374207023544">"नाही, नको"</string>
- <string name="autofill_save_notnow" msgid="2853932672029024195">"आता नाही"</string>
+ <string name="autofill_save_notnow" msgid="2853932672029024195">"आता नको"</string>
<string name="autofill_save_never" msgid="6821841919831402526">"कधीही नाही"</string>
<string name="autofill_update_yes" msgid="4608662968996874445">"अपडेट करा"</string>
<string name="autofill_continue_yes" msgid="7914985605534510385">"पुढे सुरू ठेवा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index f6cf330..4ecac17 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gunakan cap jari atau kunci skrin anda untuk meneruskan"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Kesilapan telah berlaku. Cuba lagi."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon cap jari"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Buka Kunci Wajah"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Isu dengan Buka Kunci Wajah"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gunakan wajah atau kunci skrin anda untuk meneruskan"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Kesilapan telah berlaku. Cuba lagi."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ikon wajah"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"membaca tetapan penyegerakan"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Membenarkan apl membaca tetapan segerak untuk akaun. Sebagai contoh, ini boleh menentukan sama ada apl Orang disegerakkan dengan akaun."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Apabila pintasan dihidupkan, tindakan menekan kedua-dua butang kelantangan selama 3 saat akan memulakan ciri kebolehaksesan."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Hidupkan pintasan untuk ciri kebolehaksesan?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Tindakan menahan kedua-dua kekunci kelantangan selama beberapa saat akan menghidupkan ciri kebolehaksesan. Hal ini mungkin mengubah cara peranti anda berfungsi.\n\nCiri semasa:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nAnda boleh menukar ciri yang dipilih dalam Tetapan > Kebolehaksesan."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Hidupkan pintasan <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Tindakan menahan kedua-dua kekunci kelantangan selama beberapa saat akan menghidupkan <xliff:g id="SERVICE">%1$s</xliff:g>, iaitu satu ciri kebolehaksesan. Ini mungkin mengubah cara peranti anda berfungsi.\n\nAnda boleh menukar pintasan ini kepada ciri lain dalam Tetapan > Kebolehaksesan."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Hidupkan"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index ac523f9..0e23cd4 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Bruk fingeravtrykket eller skjermlåsen for å fortsette"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Noe gikk galt. Prøv på nytt."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon for fingeravtrykk"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ansiktslås"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem med ansiktslås"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Bruk ansikts- eller skjermlåsen for å fortsette"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Noe gikk galt. Prøv på nytt."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ansiktikon"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"lese synkroniseringsinnstillinger"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Lar appen lese synkroniseringsinnstillingene for en konto. For eksempel kan den finne ut om Personer-appen er synkronisert med en konto."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Når snarveien er på, starter en tilgjengelighetsfunksjon når du trykker inn begge volumknappene i tre sekunder."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vil du slå på snarveien for tilgjengelighetsfunksjoner?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Hvis du holder inne volumtastene i noen sekunder, slås tilgjengelighetsfunksjoner på. Dette kan endre hvordan enheten din fungerer.\n\nNåværende funksjoner:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nDu kan endre valgte funksjoner i Innstillinger > Tilgjengelighet."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Vil du slå på <xliff:g id="SERVICE">%1$s</xliff:g>-snarveien?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Hvis du holder inne begge volumtastene i noen sekunder, slår du på <xliff:g id="SERVICE">%1$s</xliff:g>, en tilgjengelighetsfunksjon. Dette kan endre hvordan enheten din fungerer.\n\nDu kan endre denne snarveien til en annen funksjon i Innstillinger > Tilgjengelighet."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Slå på"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 0751379..ae69fcc 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"जारी राख्न आफ्नो फिंगरप्रिन्ट वा स्क्रिन लक प्रयोग गरी पुष्टि गर्नुहोस्"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"केही चिज गडबड भयो। फेरि प्रयास गर्नुहोस्।"</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"फिंगरप्रिन्ट आइकन"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"फेस अनलक"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"फेस अनलक सुविधामा अनुहार दर्ता गर्ने क्रममा त्रुटि भयो"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"जारी राख्न आफ्नो फेस वा स्क्रिन लक प्रयोग गरी पुष्टि गर्नुहोस्"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"केही चिज गडबड भयो। फेरि प्रयास गर्नुहोस्।"</string>
<string name="face_icon_content_description" msgid="465030547475916280">"अनुहारको आइकन"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"समीकरण सेटिङहरू पढ्नुहोस्"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"एपलाई खाताको लागि सिंक सेटिङहरू पढ्न अनुमति दिन्छ। उदाहरणको लागि यसले व्यक्तिहरको एप खातासँग सिंक भएको नभएको निर्धारण गर्न सक्दछ।"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"यो सर्टकट सक्रिय हुँदा, ३ सेकेन्डसम्म दुवै भोल्युम बटन थिच्नुले पहुँचसम्बन्धी कुनै सुविधा सुरु गर्ने छ।"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"एक्सेसिबिलिटीसम्बन्धी सुविधा प्रयोग गर्न सर्टकट अन गर्ने हो?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"केही सेकेन्डसम्म दुवै भोल्युम की थिचिराख्नुभयो भने पहुँचसम्बन्धी सुविधाहरू सक्रिय हुन्छ। यसले तपाईंको यन्त्रले काम गर्ने तरिका परिवर्तन गर्न सक्छ।\n\nहालका सुविधाहरू:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nतपाईं सेटिङ > पहुँचमा गएर चयन गरिएका सुविधाहरू परिवर्तन गर्न सक्नुहुन्छ।"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> प्रयोग गर्न सर्टकट अन गर्ने हो?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"केही सेकेन्डसम्म दुवै भोल्युम की थिचिराख्नुले <xliff:g id="SERVICE">%1$s</xliff:g> नामक पहुँचसम्बन्धी सुविधा सक्रिय गर्छ। यसले तपाईंको यन्त्रले काम गर्ने तरिका परिवर्तन गर्न सक्छ।\n\nतपाईं सेटिङ > पहुँचमा गई यो सर्टकटमार्फत अर्को सुविधा खुल्ने बनाउन सक्नुहुन्छ।"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"सक्रिय गरियोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 8c4021d..5377be8 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gebruik je vingerafdruk of schermvergrendeling om door te gaan"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Er is iets misgegaan. Probeer het opnieuw."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Vingerafdruk-icoon"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ontgrendelen via gezichtsherkenning"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Probleem met Ontgrendelen via gezichtsherkenning"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gebruik je gezicht of schermvergrendeling om door te gaan"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Er is iets misgegaan. Probeer het opnieuw."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Gezichtspictogram"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"synchronisatie-instellingen lezen"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Hiermee kan de app de synchronisatie-instellingen voor een account lezen. Dit kan bijvoorbeeld bepalen of de app Personen wordt gesynchroniseerd met een account."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Als de snelkoppeling aanstaat, houd je beide volumeknoppen 3 seconden ingedrukt om een toegankelijkheidsfunctie te starten."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Snelkoppeling voor toegankelijkheidsfuncties aanzetten?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Als je beide volumetoetsen een paar seconden ingedrukt houdt, zet je de toegankelijkheidsfuncties aan. Hierdoor kan de manier veranderen waarop je apparaat werkt.\n\nHuidige functies:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nJe kunt de geselecteerde functies wijzigen via Instellingen > Toegankelijkheid."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Snelkoppeling voor <xliff:g id="SERVICE">%1$s</xliff:g> aanzetten?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Als je beide volumetoetsen een paar seconden ingedrukt houdt, wordt de toegankelijkheidsfunctie <xliff:g id="SERVICE">%1$s</xliff:g> aangezet. Hierdoor kan de manier veranderen waarop je apparaat werkt.\n\nJe kunt deze sneltoets op een andere functie instellen via Instellingen > Toegankelijkheid."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aanzetten"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 14ca2e5..8c40899 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ଟିପଚିହ୍ନ କିମ୍ବା ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"କିଛି ତ୍ରୁଟି ହୋଇଛି। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ଟିପଚିହ୍ନ ଆଇକନ୍"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ଫେସ୍ ଅନଲକ୍"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ଫେସ୍ ଅନଲକ୍ ସହ ସମସ୍ୟା"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ଚେହେରା କିମ୍ବା ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"କିଛି ତ୍ରୁଟି ହୋଇଛି। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="face_icon_content_description" msgid="465030547475916280">"ଫେସ୍ ଆଇକନ୍"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"ସିଙ୍କ ସେଟିଙ୍ଗକୁ ପଢ଼ନ୍ତୁ"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ଏକ ଆକାଉଣ୍ଟ ପାଇଁ ସିଙ୍କ ସେଟିଙ୍ଗ ପଢ଼ିବାକୁ ଆପ୍ଟିକୁ ଅନୁମତି ଦିଏ। ଉଦାହରଣସ୍ୱରୂପ, ଲୋକଙ୍କ ଆପ୍ ଏକ ଆକାଉଣ୍ଟରେ ସିଙ୍କ ହୋଇଛି କି ନାହିଁ ଏହା ଜାଣିପାରେ।"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ସର୍ଟକଟ୍ ଚାଲୁ ଥିବା ବେଳେ, ଉଭୟ ଭଲ୍ୟୁମ୍ ବଟନ୍ 3 ସେକେଣ୍ଡ ପାଇଁ ଦବାଇବା ଦ୍ୱାରା ଏକ ଆକ୍ସେସବିଲିଟି ଫିଚର୍ ଆରମ୍ଭ ହେବ।"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ଆକ୍ସେସିବିଲିଟୀ ଫିଚରଗୁଡ଼ିକ ପାଇଁ ସର୍ଟକଟ୍ ଚାଲୁ କରିବେ?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"କିଛି ସେକେଣ୍ଡ ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ୍ କୀ’କୁ ଧରି ରଖିବା ଫଳରେ ଆକ୍ସେସିବିଲିଟୀ ଫିଚରଗୁଡ଼ିକ ଚାଲୁ ହୁଏ। ଏହା ଆପଣଙ୍କ ଡିଭାଇସ୍ କିପରି କାମ କରେ ତାହା ପରିବର୍ତ୍ତନ କରିପାରେ।\n\nବର୍ତ୍ତମାନର ଫିଚରଗୁଡ଼ିକ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n ଆପଣ ସେଟିଂସ୍ &gt ଆକ୍ସେସିବିଲିଟୀରେ ଚୟନିତ ଫିଚରଗୁଡ଼ିକୁ ପରିବର୍ତ୍ତନ କରିପାରିବେ।"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> ସର୍ଟକଟ୍ ଚାଲୁ କରିବେ?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"କିଛି ସେକେଣ୍ଡ ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ୍ କୀ’କୁ ଧରି ରଖିବା ଫଳରେ ଏକ ଆକ୍ସେସିବିଲିଟୀ ଫିଚର୍ <xliff:g id="SERVICE">%1$s</xliff:g> ଚାଲୁ ହୁଏ। ଏହା ଆପଣଙ୍କ ଡିଭାଇସ୍ କିପରି କାମ କରେ ତାହା ପରିବର୍ତ୍ତନ କରିପାରେ।\n\nଆପଣ ସେଟିଂସ୍ &gt ଆକ୍ସେସିବିଲିଟୀରେ ଏହି ସର୍ଚକଟକୁ ଅନ୍ୟ ଏକ ଫିଚରରେ ପରିବର୍ତ୍ତନ କରିପାରିବେ।"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"ଚାଲୁ କରନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index b9e2a0b..383ef18 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਵਰਤੋ"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"ਕੋਈ ਗੜਬੜ ਹੋ ਗਈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਤੀਕ"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ਫ਼ੇਸ ਅਣਲਾਕ"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ਫ਼ੇਸ ਅਣਲਾਕ ਨਾਲ ਸਮੱਸਿਆ"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣਾ ਚਿਹਰਾ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਵਰਤੋ"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"ਕੋਈ ਗੜਬੜ ਹੋ ਗਈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="face_icon_content_description" msgid="465030547475916280">"ਚਿਹਰਾ ਪ੍ਰਤੀਕ"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"ਸਿੰਕ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹੋ"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ਐਪ ਨੂੰ ਕਿਸੇ ਖਾਤੇ ਲਈ ਸਮਕਾਲੀਕਰਨ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਹ ਪਤਾ ਕਰ ਸਕਦਾ ਹੈ ਕਿ People ਐਪ ਦਾ ਕਿਸੇ ਖਾਤੇ ਨਾਲ ਸਮਕਾਲੀਕਿਰਤ ਕੀਤਾ ਗਿਆ ਹੈ ਜਾਂ ਨਹੀਂ।"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਹੋਣ \'ਤੇ, ਕਿਸੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ ਬਟਨਾਂ ਨੂੰ 3 ਸਕਿੰਟ ਲਈ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ਕੀ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਲਈ ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"ਕੁਝ ਸਕਿੰਟਾਂ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਨੂੰ ਦਬਾਈ ਰੱਖਣਾ, ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਚਾਲੂ ਕਰ ਦਿੰਦਾ ਹੈ। ਇਹ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਕੰਮ ਕਰਨ ਦੇ ਤਰੀਕੇ ਨੂੰ ਬਦਲ ਸਕਦਾ ਹੈ।\n\nਮੌਜੂਦਾ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nਸੈਟਿੰਗਾਂ ਅਤੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿੱਚ ਤੁਸੀਂ ਚੁਣੀਆਂ ਗਈਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"ਕੀ <xliff:g id="SERVICE">%1$s</xliff:g> ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"ਕੁਝ ਸਕਿੰਟਾਂ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਨੂੰ ਦਬਾਈ ਰੱਖਣਾ <xliff:g id="SERVICE">%1$s</xliff:g>, ਇੱਕ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਚਾਲੂ ਕਰ ਦਿੰਦਾ ਹੈ। ਇਹ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਕੰਮ ਕਰਨ ਦੇ ਤਰੀਕੇ ਨੂੰ ਬਦਲ ਸਕਦਾ ਹੈ।\n\nਸੈਟਿੰਗਾਂ ਅਤੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿੱਚ ਤੁਸੀਂ ਇਸ ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਕਿਸੇ ਹੋਰ ਵਿਸ਼ੇਸ਼ਤਾ ਵਿੱਚ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"ਚਾਲੂ ਕਰੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index c3c30da1..cbd8900 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -615,8 +615,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Aby kontynuować, użyj odcisku palca lub blokady ekranu"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Coś poszło nie tak. Spróbuj ponownie."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona odcisku palca"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Rozpoznawanie twarzy"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem z rozpoznawaniem twarzy"</string>
@@ -669,8 +668,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Aby kontynuować, użyj rozpoznawania twarzy lub blokady ekranu"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Coś poszło nie tak. Spróbuj ponownie."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ikona twarzy"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"czytanie ustawień synchronizacji"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Zezwala aplikacji na odczyt ustawień synchronizacji konta. Pozwala to na przykład określić, czy aplikacja Ludzie jest zsynchronizowana z kontem."</string>
@@ -1740,8 +1738,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Gdy skrót jest włączony, jednoczesne naciskanie przez trzy sekundy obu przycisków głośności uruchamia funkcję ułatwień dostępu."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Włączyć skrót ułatwień dostępu?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Przytrzymanie obu klawiszy głośności przez kilka sekund włącza ułatwienia dostępu. Może to zmienić sposób działania urządzenia.\n\nBieżące funkcje:\n<xliff:g id="SERVICE">%1$s</xliff:g>\naby zmienić wybrane funkcje, kliknij Ustawienia > Ułatwienia dostępu."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Włączyć skrót <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Przytrzymanie obu klawiszy głośności przez kilka sekund włącza usługę <xliff:g id="SERVICE">%1$s</xliff:g>, stanowiącą ułatwienie dostępu. Może to zmienić sposób działania urządzenia.\n\nAby zmienić ten skrót i wskazać inną funkcję, kliknij Ustawienia > Ułatwienia dostępu."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Włącz"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index e5eb61d..d6107d7 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1941,7 +1941,7 @@
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabalho"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Alertado"</string>
<string name="notification_verified_content_description" msgid="6401483602782359391">"Verificada"</string>
- <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expandir"</string>
+ <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Abrir"</string>
<string name="expand_button_content_description_expanded" msgid="7484217944948667489">"Recolher"</string>
<string name="expand_action_accessibility" msgid="1947657036871746627">"alternar expansão"</string>
<string name="usb_midi_peripheral_name" msgid="490523464968655741">"Porta USB periférica Android"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index e5eb61d..d6107d7 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1941,7 +1941,7 @@
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabalho"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Alertado"</string>
<string name="notification_verified_content_description" msgid="6401483602782359391">"Verificada"</string>
- <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expandir"</string>
+ <string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Abrir"</string>
<string name="expand_button_content_description_expanded" msgid="7484217944948667489">"Recolher"</string>
<string name="expand_action_accessibility" msgid="1947657036871746627">"alternar expansão"</string>
<string name="usb_midi_peripheral_name" msgid="490523464968655741">"Porta USB periférica Android"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 71e338f..41ecdbd 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -612,8 +612,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Folosiți amprenta sau blocarea ecranului pentru a continua"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"A apărut o eroare. Încercați din nou."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Pictograma amprentă"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Deblocare facială"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problemă cu Deblocarea facială"</string>
@@ -666,8 +665,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Folosiți-vă chipul sau blocarea ecranului pentru a continua"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"A apărut o eroare. Încercați din nou."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Pictograma chip"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"citire setări sincronizare"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Permite aplicației să citească setările de sincronizare ale unui cont. De exemplu, cu această permisiune aplicația poate determina dacă aplicația Persoane este sincronizată cu un anumit cont."</string>
@@ -1718,8 +1716,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Atunci când comanda rapidă este activată, dacă apăsați ambele butoane de volum timp de trei secunde, veți lansa o funcție de accesibilitate."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Activați comanda rapidă pentru funcțiile de accesibilitate?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Dacă apăsați ambele taste de volum câteva secunde, activați funcțiile de accesibilitate. Acest lucru poate schimba funcționarea dispozitivului.\n\nFuncțiile actuale:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPuteți schimba funcțiile selectate din Setări > Accesibilitate."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Activați comanda rapidă <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Dacă apăsați ambele taste de volum câteva secunde, activați funcția de accesibilitate <xliff:g id="SERVICE">%1$s</xliff:g>. Acest lucru poate schimba funcționarea dispozitivului.\n\nPuteți alege altă funcție pentru această comandă în Setări > Accesibilitate."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Activați"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 88d06f8..ef8561d 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -615,8 +615,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Чтобы продолжить, используйте отпечаток пальца или данные для разблокировки экрана."</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Произошла ошибка. Повторите попытку."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Значок отпечатка пальца"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Фейсконтроль"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Ошибка фейсконтроля"</string>
@@ -669,8 +668,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Чтобы продолжить, посмотрите на экран или используйте данные для разблокировки."</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Произошла ошибка. Повторите попытку."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Значок лица"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"Просмотр настроек синхронизации"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Приложение сможет просматривать настройки синхронизации аккаунта, например определять, включена ли синхронизация для приложения \"Контакты\"."</string>
@@ -1740,8 +1738,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Чтобы использовать функцию специальных возможностей, когда она включена, нажмите и удерживайте обе кнопки регулировки громкости в течение трех секунд."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Использовать быстрое включение?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Чтобы включить специальные возможности, нажмите обе кнопки регулировки громкости и удерживайте несколько секунд. Обратите внимание, что в работе устройства могут произойти изменения.\n\nТекущие функции:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nЧтобы изменить выбранные функции, перейдите в настройки и нажмите \"Специальные возможности\"."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Использовать быстрое включение сервиса \"<xliff:g id="SERVICE">%1$s</xliff:g>\"?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Чтобы включить функцию \"<xliff:g id="SERVICE">%1$s</xliff:g>\", нажмите обе кнопки регулировки громкости на несколько секунд. Обратите внимание, что в работе устройства могут произойти изменения.\n\nЧтобы назначить это сочетание клавиш другой функции, перейдите в настройки и выберите \"Специальные возможности\"."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Включить"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 1b7973d..af59be3 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ඉදිරියට යාමට ඔබගේ ඇඟිලි සලකුණ හෝ තිර අගුල භාවිත කරන්න"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"යම් දෙයක් වැරදිණි. නැවත උත්සාහ කරන්න."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ඇඟිලි සලකුණු නිරූපකය"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"මුහුණෙන් අගුළු හැරීම"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"මුහුණෙන් අගුලු හැරීම සම්බන්ධව ගැටලුවකි"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ඉදිරියට යාමට ඔබගේ මුහුණු හෝ තිර අගුල භාවිත කරන්න"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"යම් දෙයක් වැරදිණි. නැවත උත්සාහ කරන්න."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"මුහුණ නිරූපකය"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"සමමුහුර්ත සැකසීම් කියවන්න"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ගිණුම සඳහා සමමුහුර්ත සැකසීම් කියවීමට යෙදුමට අවසර දෙන්න. උදාහරණයක් ලෙස, ගිණුමක් සමඟ පුද්ගල යෙදුම සමමුහුර්ත දැයි මෙයට හඳුනා ගත හැක."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"කෙටිමග ක්රියාත්මක විට, හඬ පරිමා බොත්තම් දෙකම තත්පර 3ක් තිස්සේ එබීමෙන් ප්රවේශ්යතා විශේෂාංගය ආරම්භ වනු ඇත."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ප්රවේශ්යතා විශේෂාංග සඳහා කෙටි මග ක්රියාත්මක කරන්නද?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"හඬ පරිමා යතුරු දෙකම තත්පර කීපයකට පහළට අල්ලාගෙන සිටීම ප්රවේශ්යතා විශේෂාංග ක්රියාත්මක කරයි. මෙය ඔබේ උපාංගය ක්රියා කරන ආකාරය වෙනස් කළ හැකිය.\n\nවත්මන් විශේෂාංග:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nඔබට තේරූ විශේෂාංග සැකසීම් > ප්රවේශ්යතාව හි වෙනස් කළ හැකිය."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> කෙටි මග ක්රියාත්මක කරන්නද?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"හඬ පරිමා යතුරු දෙකම තත්පර කීපයකට පහළට අල්ලාගෙන සිටීම ප්රවේශ්යතා විශේෂාංගයක් වන <xliff:g id="SERVICE">%1$s</xliff:g> ක්රියාත්මක කරයි. මෙය ඔබේ උපාංගය ක්රියා කරන ආකාරය වෙනස් කළ හැකිය.\n\nඔබට මෙම කෙටිමග සැකසීම් > ප්රවේශ්යතාව හි තවත් විශේෂාංගයකට වෙනස් කළ හැකිය."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"ක්රියාත්මක කරන්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 33ea9c9..7c56c49 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -615,8 +615,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Pokračujte použitím odtlačku prsta alebo zámky obrazovky"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Vyskytla sa chyba. Skúste to znova."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona odtlačku prsta"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Odomknutie tvárou"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problém s odomknutím tvárou"</string>
@@ -669,8 +668,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Pokračujte použitím tváre alebo zámky obrazovky"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Vyskytla sa chyba. Skúste to znova."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ikona tváre"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"čítať nastavenia synchronizácie"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Umožňuje aplikácii čítať nastavenia synchronizácie v účte. Môže napríklad určiť, či je s účtom synchronizovaná aplikácia Ľudia."</string>
@@ -1740,8 +1738,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Keď je skratka zapnutá, stlačením obidvoch tlačidiel hlasitosti na tri sekundy spustíte funkciu dostupnosti."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Chcete zapnúť skratku pre funkcie dostupnosti?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Pridržaním oboch tlačidiel hlasitosti na niekoľko sekúnd zapnete funkcie dostupnosti. Môže sa tým zmeniť spôsob fungovania vášho zariadenia.\n\nAktuálne funkcie:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nVybrané funkcie môžete zmeniť v časti Nastavenia > Dostupnosť."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Chcete zapnúť skratku na službu <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Pridržaním oboch klávesov hlasitosti na niekoľko sekúnd zapnete funkciu dostupnosti <xliff:g id="SERVICE">%1$s</xliff:g>. Môže sa tým zmeniť spôsob fungovania vášho zariadenia.\n\nTúto skratku môžete zmeniť na inú funkciu v časti Nastavenia > Dostupnosť."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Zapnúť"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index f53d847b..deab3a4 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -615,8 +615,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Za nadaljevanje uporabite prstni odtis ali odklepanje s poverilnico."</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Prišlo je do napake. Poskusite znova."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona prstnih odtisov"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Odklepanje z obrazom"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Težava z odklepanjem z obrazom"</string>
@@ -669,8 +668,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Za nadaljevanje uporabite obraz ali odklepanje s poverilnico."</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Prišlo je do napake. Poskusite znova."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ikona obraza"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"branje nastavitev sinhronizacije"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Aplikaciji omogoča branje nastavitev sinhronizacije za račun. S tem lahko aplikacija na primer ugotovi, ali je aplikacija Ljudje sinhronizirana z računom."</string>
@@ -1740,8 +1738,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Ko je bližnjica vklopljena, pritisnite gumba za glasnost in ju pridržite tri sekunde, če želite zagnati funkcijo za ljudi s posebnimi potrebami."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Želite vklopiti bližnjico za funkcije za ljudi s posebnimi potrebami?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Če za nekaj sekund pridržite obe tipki za glasnost, boste vklopili funkcije za ljudi s posebnimi potrebami. To lahko spremeni način delovanja naprave.\n\nTrenutne funkcije:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nIzbrane funkcije lahko spremenite v meniju »Nastavitve« > »Funkcije za ljudi s posebnimi potrebami«."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Želite vklopiti bližnjico za <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Če za nekaj sekund pridržite obe tipki za glasnost, boste vklopili storitev <xliff:g id="SERVICE">%1$s</xliff:g>, ki je funkcija za ljudi s posebnimi potrebami. To lahko spremeni način delovanja naprave.\n\nTo bližnjico lahko v meniju »Nastavitve« > »Funkcije za ljudi s posebnimi potrebami« spremenite, da bo uporabljena za drugo funkcijo."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Vklopi"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 9cbc916..c04a888 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Përdor gjurmën tënde të gishtit ose kyçjen e ekranit për të vazhduar"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Ndodhi një gabim. Provo sërish."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikona e gjurmës së gishtit"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Shkyçja me fytyrë"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem me \"Shkyçjen me fytyrë\""</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Përdor fytyrën tënde ose kyçjen e ekranit për të vazhduar"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Ndodhi një gabim. Provo sërish."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ikona e fytyrës"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"lexo cilësimet e sinkronizimit"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Lejon aplikacionin të lexojë cilësimet e sinkronizimit për një llogari. Për shembull, kjo mund të përcaktojë nëse aplikacioni \"Kontaktet\" është i sinkronizuar me një llogari."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kur shkurtorja është e aktivizuar, shtypja e të dy butonave për 3 sekonda do të nisë një funksion qasshmërie."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Të aktivizohet shkurtorja për veçoritë e qasshmërisë?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Mbajtja shtypur e dy tasteve të volumit për pak sekonda aktivizon veçoritë e qasshmërisë. Kjo mund të ndryshojë mënyrën se si funksionon pajisja jote.\n\nVeçoritë aktuale:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nKe ndryshuar veçoritë e zgjedhura te Cilësimet > Qasshmëria."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Të aktivizohet shkurtorja për <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Mbajtja shtypur e dy tasteve të volumit për pak sekonda aktivizon <xliff:g id="SERVICE">%1$s</xliff:g>, një veçori të qasshmërisë. Kjo mund të ndryshojë mënyrën se si funksionon pajisja jote.\n\nMund të ndryshosh këtë shkurtore te një veçori tjetër te Cilësimet > Qasshmëria."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktivizo"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 561f5a3..8d111d5 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -612,8 +612,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Користите отисак прста или закључавање екрана да бисте наставили"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Дошло је до проблема. Пробајте поново."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Икона отиска прста"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Откључавање лицем"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Проблем са откључавање лицем"</string>
@@ -666,8 +665,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Користите лице или закључавање екрана да бисте наставили"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Дошло је до проблема. Пробајте поново."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Икона лица"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"читање подешавања синхронизације"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Дозвољава апликацији да чита подешавања синхронизације за налог. На пример, овако може да се утврди да ли је апликација Људи синхронизована са налогом."</string>
@@ -1718,8 +1716,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Када је пречица укључена, притисните оба дугмета за јачину звука да бисте покренули функцију приступачности."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Желите да укључите пречицу за функције приступачности?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ако задржите оба тастера за јачину звука пар секунди, укључиће се функције приступачности. То може да промени начин рада уређаја.\n\nПостојеће функције:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nМожете да промените изабране функције у одељку Подешавања > Приступачност."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Желите да укључите пречицу за услугу <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ако задржите оба тастера за јачину звука пар секунди, укључује се <xliff:g id="SERVICE">%1$s</xliff:g>, функција приступачности. То може да промени начин рада уређаја.\n\nМожете да промените функцију на коју се односи ова пречица у одељку Подешавања > Приступачност."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Укључи"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 72c8ccc..f6cc4cf 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Fortsätt med hjälp av ditt fingeravtryck eller skärmlåset"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Något gick fel. Försök igen."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Ikon för fingeravtryck"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ansiktslås"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Problem med ansiktslås"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Fortsätt med hjälp av ditt ansikte eller skärmlåset"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Något gick fel. Försök igen."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Ansikte"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"läsa synkroniseringsinställningar"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Tillåter att appen läser synkroniseringsinställningarna för ett konto. Detta kan användas till exempel för att avgöra om appen Personer är synkroniserad med ett konto."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"När kortkommandot har aktiverats startar du en tillgänglighetsfunktion genom att trycka ned båda volymknapparna i tre sekunder."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vill du aktivera genvägen till tillgänglighetsfunktioner?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Om du trycker ned båda volymknapparna i ett par sekunder aktiveras tillgänglighetsfunktionerna. Det kan få enheten ett fungera annorlunda.\n\nAktuella funktioner:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nDu kan ändra vilka funktioner som aktiveras under Inställningar > Tillgänglighet."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Vill du aktivera genvägen till <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Om du trycker ned båda volymknapparna i ett par sekunder aktiveras <xliff:g id="SERVICE">%1$s</xliff:g>, en tillgänglighetsfunktion. Det kan leda till att enheten fungerar annorlunda.\n\nDu kan ändra vilken funktion som ska aktiveras med genvägen under Inställningar > Tillgänglighet."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Aktivera"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 90bdf85..8a05fdc 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Tumia alama ya kidole au mbinu yako ya kufunga skrini ili uendelee"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Hitilafu fulani imetokea. Jaribu tena."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Aikoni ya alama ya kidole"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Kufungua kwa Uso"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Hitilafu imetokea kwenye kipengele cha Kufungua kwa Uso"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Tumia uso au mbinu yako ya kufunga skrini ili uendelee"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Hitilafu fulani imetokea. Jaribu tena."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Aikoni ya uso"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"kusoma mipangilio ya usawazishaji"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Inaruhusu programu kusoma mipangilio ya upatanishi wa akaunti. Kwa mfano, huku kunaweza kuamua kama programu ya Watu imepatanishwa na akaunti."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Unapowasha kipengele cha njia ya mkato, hatua ya kubonyeza vitufe vyote viwili vya sauti kwa sekunde tatu itafungua kipengele cha ufikivu."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Ungependa kuwasha njia ya mkato ya vipengele vya ufikivu?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Hatua ya kushikilia chini vitufe vyote viwili vya sauti kwa sekunde chache huwasha vipengele vya ufikivu. Huenda hatua hii ikabadilisha jinsi kifaa chako kinavyofanya kazi.\n\nVipengele vya sasa:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nUnaweza kubadilisha vipengele ulivyochagua katika Mipangilio > Ufikivu."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Ungependa kuwasha njia ya mkato ya <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Hatua ya kushikilia chini vitufe vyote viwili vya sauti kwa sekunde chache huwasha <xliff:g id="SERVICE">%1$s</xliff:g>, kipengele cha ufikivu. Huenda hatua hii ikabadilisha jinsi kifaa chako kinavyofanya kazi.\n\nUnaweza kubadilisha njia hii ya mkato iwe kipengele kingine katika Mipangilio > Ufikivu."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Washa"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 62fb2a0..920a0b8 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"தொடர, உங்கள் கைரேகையையோ திரைப் பூட்டையோ பயன்படுத்துங்கள்"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"ஏதோ தவறாகிவிட்டது. மீண்டும் முயலவும்."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"கைரேகை ஐகான்"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"முகம் காட்டித் திறத்தல்"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"முகம் காட்டித் திறத்தல் அம்சத்தில் சிக்கல்"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"தொடர, உங்கள் முகத்தையோ திரைப் பூட்டையோ பயன்படுத்துங்கள்"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"ஏதோ தவறாகிவிட்டது. மீண்டும் முயலவும்."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"முக ஐகான்"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"ஒத்திசைவு அமைப்புகளைப் படித்தல்"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"கணக்கிற்கான ஒத்திசைவு அமைப்புகளைப் படிக்க ஆப்ஸை அனுமதிக்கிறது. எடுத்துக்காட்டாக, பீப்பிள் ஆப்ஸ் கணக்குடன் ஒத்திசைக்கப்பட்டுள்ளதா என்பதை இது தீர்மானிக்கலாம்."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"ஷார்ட்கட் இயக்கத்தில் இருக்கும்போது ஒலியளவு பட்டன்கள் இரண்டையும் 3 வினாடிகளுக்கு அழுத்தினால் அணுகல்தன்மை அம்சம் இயக்கப்படும்."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"அணுகல்தன்மை அம்சங்களுக்கான ஷார்ட்கட்டை ஆன் செய்யவா?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"இரண்டு ஒலியளவு விசைகளையும் சில விநாடிகள் பிடித்திருந்தால் அணுகல்தன்மை அம்சங்கள் ஆன் செய்யப்படும். இதனால் உங்கள் சாதனம் வேலை செய்யும் முறை மாறக்கூடும்.\n\nதற்போதைய அம்சங்கள்:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nதேர்ந்தெடுத்த அம்சங்களை அமைப்புகள் > அணுகல்தன்மைக்குச் சென்று உங்களால் மாற்ற முடியும்."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> அம்சத்துக்கான ஷார்ட்கட்டை ஆன் செய்யவா?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"இரண்டு ஒலியளவு விசைகளையும் சில விநாடிகள் பிடித்திருப்பதால் அணுகல்தன்மை அம்சமான <xliff:g id="SERVICE">%1$s</xliff:g> ஆன் ஆகும். இதனால் உங்கள் சாதனம் வேலை செய்யும் முறை மாறக்கூடும்.\n\nஅமைப்புகள் > அணுகல்தன்மைக்குச் சென்று இந்த ஷார்ட்கட்டை வேறு அம்சத்திற்கு மாற்ற முடியும்."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"ஆன் செய்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index ef5c621..50fa752 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -361,11 +361,11 @@
<string name="permlab_receiveMms" msgid="4000650116674380275">"వచన మెసేజ్లను (MMS) స్వీకరించడం"</string>
<string name="permdesc_receiveMms" msgid="958102423732219710">"MMS మెసేజ్లను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. యాప్ మీ డివైజ్కు పంపబడిన మెసేజ్లను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"సెల్ ప్రసార మెసేజ్లను ఫార్వర్డ్ చేయడం"</string>
- <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"సెల్ ప్రసార మెసేజ్లను అందుకుంటే, వాటిని ఫార్వర్డ్ చేసే విధంగా సెల్ ప్రసార మాడ్యూల్కు కట్టుబడి ఉండటానికి యాప్ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం అందుకున్నప్పుడు హానికరమైన యాప్లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string>
+ <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"సెల్ ప్రసార మెసేజ్లను స్వీకరించినప్పుడు, వాటిని ఫార్వర్డ్ చేయడానికి సెల్ ప్రసార మాడ్యూల్కు కట్టుబడి ఉండేందుకు యాప్ను అనుమతిస్తుంది. ఎమర్జెన్సీ పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని లొకేషన్లలో సెల్ ప్రసార అలర్ట్లు డెలివరీ చేయబడతాయి. ఎమర్జెన్సీ సెల్ ప్రసార అలర్ట్ను స్వీకరించినప్పుడు హానికరమైన యాప్లు మీ పరికరం పనితీరుకు లేదా నిర్వహణకు ఆటంకం కలిగించే అవకాశం ఉంది."</string>
<string name="permlab_manageOngoingCalls" msgid="281244770664231782">"కొనసాగుతున్న కాల్స్ను మేనేజ్ చేయి"</string>
<string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"మీ పరికరంలో కొనసాగుతున్న కాల్స్ను చూడటానికి అలాగే వాటిని కంట్రోల్ చేయడానికి ఒక యాప్కు అనుమతిస్తోంది."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"సెల్ ప్రసార మెసేజ్లను చదవడం"</string>
- <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార మెసేజ్లను చదవడానికి యాప్ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం స్వీకరించినప్పుడు హానికరమైన యాప్లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string>
+ <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార మెసేజ్లను చదవడానికి యాప్ను అనుమతిస్తుంది. ఎమర్జెన్సీ పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని లొకేషన్లలో సెల్ ప్రసార అలర్ట్లు డెలివరీ చేయబడతాయి. ఎమర్జెన్సీ సెల్ ప్రసార అలర్ట్ను స్వీకరించినప్పుడు హానికరమైన యాప్లు మీ పరికరం పనితీరుకు లేదా నిర్వహణకు ఆటంకం కలిగించే అవకాశం ఉంది."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"చందా చేయబడిన ఫీడ్లను చదవడం"</string>
<string name="permdesc_subscribedFeedsRead" msgid="6911349196661811865">"ప్రస్తుతం సమకాలీకరించిన ఫీడ్ల గురించి వివరాలను పొందడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="permlab_sendSms" msgid="7757368721742014252">"SMS మెసేజ్లను పంపడం మరియు వీక్షించడం"</string>
@@ -561,8 +561,8 @@
<string name="permdesc_videoWrite" msgid="6124731210613317051">"మీ వీడియో సేకరణను సవరించడానికి యాప్ని అనుమతిస్తుంది."</string>
<string name="permlab_imagesWrite" msgid="1774555086984985578">"మీ ఫోటో సేకరణను ఎడిట్ చేయండి"</string>
<string name="permdesc_imagesWrite" msgid="5195054463269193317">"మీ ఫోటో సేకరణను సవరించడానికి యాప్ను అనుమతిస్తుంది."</string>
- <string name="permlab_mediaLocation" msgid="7368098373378598066">"మీ మీడియా సేకరణ నుండి స్థానాలను చదవండి"</string>
- <string name="permdesc_mediaLocation" msgid="597912899423578138">"మీ మీడియా సేకరణ నుండి స్థానాలను చదవడానికి యాప్ను అనుమతిస్తుంది."</string>
+ <string name="permlab_mediaLocation" msgid="7368098373378598066">"మీ మీడియా సేకరణ నుండి లొకేషన్లను చదవండి"</string>
+ <string name="permdesc_mediaLocation" msgid="597912899423578138">"మీ మీడియా సేకరణ నుండి లొకేషన్లను చదవడానికి యాప్ను అనుమతిస్తుంది."</string>
<string name="biometric_app_setting_name" msgid="3339209978734534457">"బయోమెట్రిక్స్ను ఉపయోగించండి"</string>
<string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"బయోమెట్రిక్స్ను లేదా స్క్రీన్ లాక్ను ఉపయోగించండి"</string>
<string name="biometric_dialog_default_title" msgid="55026799173208210">"ఇది మీరేనని వెరిఫై చేసుకోండి"</string>
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"కొనసాగించడానికి మీ వేలిముద్ర లేదా స్క్రీన్ లాక్ను ఉపయోగించండి"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"ఏదో తప్పు జరిగింది. మళ్లీ ట్రై చేయండి."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"వేలిముద్ర చిహ్నం"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"ఫేస్ అన్లాక్"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"ఫేస్ అన్లాక్తో సమస్య"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"కొనసాగించడానికి మీ ముఖం లేదా స్క్రీన్ లాక్ను ఉపయోగించండి"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"ఏదో తప్పు జరిగింది. మళ్లీ ట్రై చేయండి."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"ముఖ చిహ్నం"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"సింక్ సెట్టింగ్లను చదవగలగడం"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ఖాతా యొక్క సింక్ సెట్టింగ్లను చదవడానికి యాప్ను అనుమతిస్తుంది. ఉదాహరణకు, వ్యక్తుల యాప్ ఖాతాతో సమకాలీకరించబడాలా లేదా అనే విషయాన్ని ఇది నిశ్చయించవచ్చు."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"షార్ట్కట్ ఆన్ చేసి ఉన్నప్పుడు, రెండు వాల్యూమ్ బటన్లను 3 సెకన్ల పాటు నొక్కి ఉంచితే యాక్సెస్ సౌలభ్య ఫీచర్ ప్రారంభం అవుతుంది."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"యాక్సెస్ సౌలభ్య ఫీచర్ల కోసం షార్ట్కట్ను ఆన్ చేయాలా?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"రెండు వాల్యూమ్ కీలను కొంత సేపు నొక్కి పట్టుకుంటే యాక్సెసిబిలిటీ ఫీచర్లు ఆన్ అవుతాయి. ఇది మీ పరికరం పని చేసే విధానాన్ని మార్చవచ్చు.\n\nప్రస్తుత ఫీచర్లు:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nఎంపిక చేసిన ఫీచర్లను మీరు సెట్టింగ్లు>యాక్సెసిబిలిటీలో మార్చవచ్చు."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> షార్ట్కట్ను ఆన్ చేయాలా?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"రెండు వాల్యూమ్ కీలను కొన్ని సెకన్ల పాటు నొక్కి పట్టుకోవడం ద్వారా యాక్సెసిబిలిటీ అయిన <xliff:g id="SERVICE">%1$s</xliff:g> ఆన్ అవుతుంది. ఇది మీ పరికరం పని చేసే విధానాన్ని మార్చవచ్చు.\n\nసెట్టింగ్లు > యాక్సెసిబిలిటీలో, వేరొక ఫీచర్ను ప్రారంభించేలా ఈ షార్ట్ కట్ను మీరు మార్చవచ్చు."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"ఆన్ చేయి"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 7452ad1..0056d79 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"ใช้ลายนิ้วมือหรือการล็อกหน้าจอเพื่อดำเนินการต่อ"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"เกิดข้อผิดพลาด ลองอีกครั้ง"</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"ไอคอนลายนิ้วมือ"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"การปลดล็อกด้วยใบหน้า"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"มีปัญหาเกี่ยวกับฟีเจอร์ปลดล็อกด้วยใบหน้า"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"ใช้ใบหน้าหรือการล็อกหน้าจอเพื่อดำเนินการต่อ"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"เกิดข้อผิดพลาด ลองอีกครั้ง"</string>
<string name="face_icon_content_description" msgid="465030547475916280">"ไอคอนใบหน้า"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"อ่านการตั้งค่าการซิงค์"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"อนุญาตให้แอปพลิเคชันอ่านการตั้งค่าการซิงค์ของบัญชี ตัวอย่างเช่น การอนุญาตนี้สามารถระบุได้ว่าแอปพลิเคชัน People ซิงค์กับบัญชีหรือไม่"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"เมื่อทางลัดเปิดอยู่ การกดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มนาน 3 วินาทีจะเริ่มฟีเจอร์การช่วยเหลือพิเศษ"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"เปิดใช้ทางลัดสำหรับฟีเจอร์การช่วยเหลือพิเศษใช่ไหม"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"การกดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มค้างไว้ 2-3 วินาทีจะเปิดฟีเจอร์การช่วยเหลือพิเศษ การดำเนินการนี้อาจเปลี่ยนแปลงลักษณะการทำงานของอุปกรณ์\n\nฟีเจอร์ปัจจุบัน:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nคุณจะเปลี่ยนฟีเจอร์ที่เลือกไว้ได้ในการตั้งค่า > การช่วยเหลือพิเศษ"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"เปิดใช้ทางลัด <xliff:g id="SERVICE">%1$s</xliff:g> ใช่ไหม"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"การกดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มค้างไว้ 2-3 วินาทีจะเปิด <xliff:g id="SERVICE">%1$s</xliff:g> ซึ่งเป็นฟีเจอร์การช่วยเหลือพิเศษ การดำเนินการนี้อาจเปลี่ยนแปลงลักษณะการทำงานของอุปกรณ์\n\nคุณแก้ไขทางลัดนี้ให้เปิดฟีเจอร์อื่นได้ในการตั้งค่า > การช่วยเหลือพิเศษ"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"เปิด"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 78fcafb..6be37be 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Gamitin ang iyong fingerprint o lock ng screen para magpatuloy"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Nagkaproblema. Subukan ulit."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Icon ng fingerprint"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Pag-unlock Gamit ang Mukha"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Isyu sa Pag-unlock Gamit ang Mukha"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Gamitin ang iyong mukha o lock ng screen para magpatuloy"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Nagkaproblema. Subukan ulit."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Face icon"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"basahin ang mga setting ng sync"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Pinapayagan ang app na basahin ang mga setting ng pag-sync para sa isang account. Halimbawa, matutukoy nito kung naka-sync ang app na Mga Tao sa isang account."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kapag naka-on ang shortcut, magsisimula ang isang feature ng pagiging naa-access kapag pinindot ang parehong button ng volume."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"I-on ang shortcut para sa mga feature ng pagiging naa-access?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Mao-on ang mga feature ng accessibility kapag pinindot nang matagal ang parehong volume key nang ilang segundo. Posibleng mabago nito ang paggana ng iyong device.\n\nMga kasalukuyang feature:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nPuwede mong baguhin ang mga napiling feature sa Mga Setting > Accessibility."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"I-on ang shortcut ng <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Mao-on ang feature ng accessibility na <xliff:g id="SERVICE">%1$s</xliff:g> kapag pinindot nang matagal ang parehong volume key nang ilang segundo. Posibleng mabago nito ang paggana ng iyong device.\n\nPuwede mong palitan ng ibang feature ang shortcut na ito sa Mga Setting > Accessibility."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"I-on"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 92aeea1..51c3931 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Devam etmek için parmak izi veya ekran kilidinizi kullanın"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Bir hata oluştu. Tekrar deneyin."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Parmak izi simgesi"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Yüz Tanıma Kilidi"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Yüz Tanıma Kilidi sorunu"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Devam etmek için yüz veya ekran kilidinizi kullanın"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Bir hata oluştu. Tekrar deneyin."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Yüz simgesi"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"senk. ayarlarını okuma"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Uygulamaya bir hesaba ait senkronizasyon ayarlarını okuma izni verir. Örneğin, bu izne sahip bir uygulama Kişiler uygulamasının bir hesapla senkronize olup olmadığını belirleyebilir."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kısayol açıkken ses düğmelerinin ikisini birden 3 saniyeliğine basılı tutmanız bir erişilebilirlik özelliğini başlatır."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Erişilebilirlik özellikleri için kısayol açılsın mı?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ses tuşlarının ikisini birden birkaç saniyeliğine basılı tutmak, erişilebilirlik özelliklerini açar. Bu, cihazınızın çalışma şeklini değiştirebilir.\n\nGeçerli özellikler:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nSeçilen özellikleri Ayarlar > Erişilebilirlik\'te değiştirebilirsiniz."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> kısayolu açılsın mı?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ses tuşlarının ikisini birden birkaç saniyeliğine basılı tutmak <xliff:g id="SERVICE">%1$s</xliff:g> erişilebilirlik özelliğini etkinleştirir. Bu, cihazınızın çalışma şeklini değiştirebilir.\n\nBu kısayolu, Ayarlar > Erişilebilirlik\'te başka bir özellikle değiştirebilirsiniz."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Etkinleştir"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index d450667..0af79d3 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"جاری رکھنے کے لیے اپنے فنگر پرنٹ یا اسکرین لاک کا استعمال کریں"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"کچھ غلط ہو گیا۔ دوبارہ کوشش کریں۔"</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"فنگر پرنٹ آئیکن"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"فیس اَنلاک"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"فیس اَنلاک میں مسئلہ"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"جاری رکھنے کے لیے اپنے چہرے یا اسکرین لاک کا استعمال کریں"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"کچھ غلط ہو گیا۔ دوبارہ کوشش کریں۔"</string>
<string name="face_icon_content_description" msgid="465030547475916280">"چہرے کا آئیکن"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"مطابقت پذیری کی ترتیبات پڑھیں"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"ایپ کو کسی اکاؤنٹ کیلئے مطابقت پذیری کی ترتیبات پڑھنے کی اجازت دیتا ہے۔ مثلا، یہ تعین کرسکتا ہے کہ آیا People ایپ کسی اکاؤنٹ کے ساتھ مطابقت پذیر ہے۔"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"شارٹ کٹ آن ہونے پر، 3 سیکنڈ تک دونوں والیوم بٹنز کو دبانے سے ایک ایکسیسبیلٹی خصوصیت شروع ہو جائے گی۔"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"ایکسیسبیلٹی خصوصیات کے لیے شارٹ کٹ آن کریں؟"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"دونوں والیوم کی کلیدوں کو کچھ سیکنڈز تک دبائیں رکھنے سے ایکسیسبیلٹی خصوصیات آن ہو جاتی ہیں۔ اس سے آپ کے آلے کے کام کرنے کا طریقہ تبدیل ہو سکتا ہے۔\n\nموجودہ خصوصیات:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nآپ ترتیبات اور ایکسیسبیلٹی میں منتخب کردہ خصوصیات کو تبدیل کر سکتے ہیں۔"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> شارٹ کٹ آن کریں؟"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"والیوم کی دونوں کلیدوں کو کچھ سیکنڈز تک دبائے رکھنے سے <xliff:g id="SERVICE">%1$s</xliff:g> ایکسیسبیلٹی خصوصیت آن ہو جاتی ہے۔ اس سے آپ کے آلے کے کام کرنے کا طریقہ تبدیل ہو سکتا ہے۔\n\nآپ ترتیبات اور ایکسیسبیلٹی میں دیگر خصوصیت کے لیے اس شارٹ کٹ کو تبدیل کر سکتے ہیں۔"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"آن کریں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index f5a8fed2..f200dbb 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Davom etish uchun barmoq izi yoki ekran qulfidan foydalaning"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Xatolik yuz berdi. Qayta urining."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Barmoq izi belgisi"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Yuz bilan ochish"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Yuz bilan ochishda muammo bor"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Davom etish uchun yuz tekshiruvi yoki ekran qulfidan foydalaning"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Xatolik yuz berdi. Qayta urining."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Yuz belgisi"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"sinx-sh sozlamalarini o‘qish"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Ilovaga hisobning sinxronlash sozlamalarini o‘qish uchun ruxsat beradi. Masalan, bu \"Odamlar\" ilovasi hisob bilan sinxronlangan yoki aksini aniqlay oladi."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Maxsus imkoniyatlar funksiyasidan foydalanish uchun u yoniqligida ikkala tovush tugmasini 3 soniya bosib turing."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Maxsus imkoniyatlar uchun tezkor tugma yoqilsinmi?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Maxsus imkoniyatlarni yoqish uchun ikkala tovush tugmalarini bir necha soniya bosib turing. Qurilmangiz ishlashida oʻzgarish yuz berishi mumkin.\n\nJoriy funksiyalar:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nTanlangan funksiyalarni Sozlamalar ichidagi Maxsus imkoniyatlar ustiga bosib oʻzgartirishingiz mumkin."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> tezkor tugmasi yoqilsinmi?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"<xliff:g id="SERVICE">%1$s</xliff:g> funksiyasini yoqish uchun ikkala tovush tugmalarini bir necha soniya bosib turing. Qurilmangiz ishlashida oʻzgarish yuz berishi mumkin.\n\nBu tezkor tugmalarni boshqa funksiyaga Sozlamalar ichidagi Maxsus imkoniyatlar orqali tayinlash mumkin."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Yoqilsin"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 31a2605..ab13dba 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Dùng vân tay của bạn hoặc phương thức khóa màn hình để tiếp tục"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Đã xảy ra lỗi. Hãy thử lại."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Biểu tượng vân tay"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Mở khóa bằng khuôn mặt"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Vấn đề với tính năng Mở khóa bằng khuôn mặt"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Dùng khuôn mặt của bạn hoặc phương thức khóa màn hình để tiếp tục"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Đã xảy ra lỗi. Hãy thử lại."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Biểu tượng khuôn mặt"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"đọc cài đặt đồng bộ hóa"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Cho phép ứng dụng đọc cài đặt đồng bộ hóa cho tài khoản. Ví dụ: việc này có thể xác định liệu ứng dụng Mọi người đã được đồng bộ hóa với tài khoản chưa."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Khi phím tắt này đang bật, thao tác nhấn cả hai nút âm lượng trong 3 giây sẽ mở tính năng hỗ trợ tiếp cận."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Bật phím tắt cho các tính năng hỗ trợ tiếp cận?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Thao tác nhấn và giữ cả hai phím âm lượng trong vài giây sẽ bật các tính năng hỗ trợ tiếp cận. Việc bật các tính năng này có thể thay đổi cách thiết bị của bạn hoạt động.\n\nCác tính năng hiện tại:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nBạn có thể thay đổi những tính năng đã chọn trong phần Cài đặt > Hỗ trợ tiếp cận."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Bật phím tắt cho <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Thao tác nhấn và giữ cả hai phím âm lượng trong vài giây sẽ bật <xliff:g id="SERVICE">%1$s</xliff:g>, một tính năng hỗ trợ tiếp cận. Việc bật tính năng này có thể thay đổi cách thiết bị của bạn hoạt động.\n\nBạn có thể chuyển phím tắt này thành một tính năng khác trong phần Cài đặt > Hỗ trợ tiếp cận."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Bật"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 26c2b25..b9d5654 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"使用指纹解锁或屏幕锁定凭据验证身份,才能继续操作"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"出了点问题。请重试。"</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指纹图标"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"人脸解锁"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"人脸解锁存在问题"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"使用人脸解锁或屏幕锁定凭据验证身份,才能继续操作"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"出了点问题。请重试。"</string>
<string name="face_icon_content_description" msgid="465030547475916280">"面孔图标"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"读取同步设置"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"允许该应用读取某个帐号的同步设置。例如,此权限可确定“联系人”应用是否与某个帐号同步。"</string>
@@ -1221,8 +1219,8 @@
<string name="noApplications" msgid="1186909265235544019">"没有应用可执行此操作。"</string>
<string name="aerr_application" msgid="4090916809370389109">"<xliff:g id="APPLICATION">%1$s</xliff:g>已停止运行"</string>
<string name="aerr_process" msgid="4268018696970966407">"<xliff:g id="PROCESS">%1$s</xliff:g>已停止运行"</string>
- <string name="aerr_application_repeated" msgid="7804378743218496566">"<xliff:g id="APPLICATION">%1$s</xliff:g>屡次停止运行"</string>
- <string name="aerr_process_repeated" msgid="1153152413537954974">"<xliff:g id="PROCESS">%1$s</xliff:g>屡次停止运行"</string>
+ <string name="aerr_application_repeated" msgid="7804378743218496566">"“<xliff:g id="APPLICATION">%1$s</xliff:g>”屡次停止运行"</string>
+ <string name="aerr_process_repeated" msgid="1153152413537954974">"“<xliff:g id="PROCESS">%1$s</xliff:g>”屡次停止运行"</string>
<string name="aerr_restart" msgid="2789618625210505419">"重新打开应用"</string>
<string name="aerr_report" msgid="3095644466849299308">"发送反馈"</string>
<string name="aerr_close" msgid="3398336821267021852">"关闭"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"启用这项快捷方式后,同时按下两个音量按钮 3 秒钟即可启动无障碍功能。"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"要开启无障碍功能快捷方式吗?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"同时按住两个音量键几秒钟,即可开启无障碍功能。这样做可能会改变您设备的工作方式。\n\n当前功能:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n您可以在“设置”>“无障碍”中更改所选功能。"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"要开启<xliff:g id="SERVICE">%1$s</xliff:g>快捷方式吗?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"同时按住两个音量键几秒钟,即可开启<xliff:g id="SERVICE">%1$s</xliff:g>无障碍功能。这样做可能会改变您设备的工作方式。\n\n您可以在“设置”>“无障碍”中将此快捷方式更改为开启另一项功能。"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"开启"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 4fb2225..71bcf00 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"請使用指紋解鎖或螢幕鎖定功能驗證身分,才能繼續操作"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"發生錯誤,請再試一次。"</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"指紋圖示"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"人臉解鎖"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"人臉解鎖功能發生問題"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"請使用人臉解鎖或螢幕鎖定功能驗證身分,才能繼續操作"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"發生錯誤,請再試一次。"</string>
<string name="face_icon_content_description" msgid="465030547475916280">"臉孔圖示"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"讀取同步處理設定"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"允許應用程式讀取帳戶的同步處理設定,例如判斷「使用者」應用程式是否和某個帳戶進行同步處理。"</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"啟用捷徑功能,只要同時按下兩個音量按鈕 3 秒,就能啟動無障礙功能。"</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"要開啟無障礙功能快速鍵嗎?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"同時按住音量調高鍵和調低鍵數秒,即可開啟無障礙功能。這麼做可能會改變裝置的運作方式。\n\n目前的功能:\n<xliff:g id="SERVICE">%1$s</xliff:g>\n你可以在 [設定] > [無障礙設定] 中變更選取的功能。"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"要開啟「<xliff:g id="SERVICE">%1$s</xliff:g>」快速鍵嗎?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"同時按住音量調高鍵和調低鍵數秒,即可開啟「<xliff:g id="SERVICE">%1$s</xliff:g>」無障礙功能。這麼做可能會改變裝置的運作方式。\n\n你可以在 [設定] > [無障礙設定] 中變更這個快速鍵觸發的功能。"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"開啟"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index ae0cbe2..4c7624e 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -609,8 +609,7 @@
<string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Sebenzisa izigxivizo zakho zomunwe noma ukukhiya isikrini ukuze uqhubeke"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <!-- no translation found for fingerprint_error_vendor_unknown (4170002184907291065) -->
- <skip />
+ <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Kunento engahambanga kahle. Zama futhi."</string>
<string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Isithonjana sezigxivizo zeminwe"</string>
<string name="face_recalibrate_notification_name" msgid="7311163114750748686">"Ukuvula ubuso"</string>
<string name="face_recalibrate_notification_title" msgid="2524791952735579082">"Inkinga Ngokuvula ngobuso"</string>
@@ -663,8 +662,7 @@
<string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Sebenzisa ubuso bakho noma ukukhiya isikrini ukuze uqhubeke"</string>
<string-array name="face_error_vendor">
</string-array>
- <!-- no translation found for face_error_vendor_unknown (7387005932083302070) -->
- <skip />
+ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Kunento engahambanga kahle. Zama futhi."</string>
<string name="face_icon_content_description" msgid="465030547475916280">"Isithonjana sobuso"</string>
<string name="permlab_readSyncSettings" msgid="6250532864893156277">"funda izilungiselelo zokuvumelanisa"</string>
<string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Ivumela uhlelo lokusebenza ukufunda izilungiselelo zokuvumelanisa ze-akhawunti. Isibonelo, lokhu kungacacisa ukuthi noma ngabe uhlelo lokusebenza le-People livumelanisiwe ne-akhawunti."</string>
@@ -1696,8 +1694,7 @@
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Uma isinqamuleli sivuliwe, ukucindezela zombili izinkinobho zevolumu amasekhondi angu-3 kuzoqalisa isici sokufinyelela."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Vula isinqamuleli sezici zokufinyeleleka?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Ukubambela phansi bobabili okhiye bevolumu amasekhondi ambalwa kuvula izici zokufinyelela. Lokhu kungashintsha indlela idivayisi yakho esebenza ngayo.\n\nIzici zamanje:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nUngashintsha izici ezikhethiwe Kuzilungiselelo > Ukufinyeleleka."</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_list (2128323171922023762) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"Vula isinqamuleli se-<xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Ukubambela phansi bobabili okhiye bevolumu amasekhondi ambalwa kuvula i-<xliff:g id="SERVICE">%1$s</xliff:g>, eyisici sokufinyelela Lokhu kungashintsha indlela idivayisi yakho esebenza ngayo.\n\nUngashintshela lesi sinqamuleli kwesinye isici Kuzilungiselelo > Ukufinyeleleka."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Vula"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d11c3f7..83b0ce9 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4883,6 +4883,21 @@
or > 1, it is ignored and central positionis used (0.5). -->
<item name="config_letterboxHorizontalPositionMultiplier" format="float" type="dimen">0.5</item>
+ <!-- Whether reachability repositioning is allowed for letterboxed fullscreen apps in landscape
+ device orientation. -->
+ <bool name="config_letterboxIsReachabilityEnabled">false</bool>
+
+ <!-- Default horizonal position of a center of the letterboxed app window when reachability is
+ enabled and an app is fullscreen in landscape device orientation.
+ 0 corresponds to the left side of the screen and 1 to the right side. If given value < 0.0
+ or > 1, it is ignored and right positionis used (1.0). The position multiplier is changed
+ to a symmetrical value computed as (1 - current multiplier) after each double tap in the
+ letterbox area. -->
+ <item name="config_letterboxDefaultPositionMultiplierForReachability"
+ format="float" type="dimen">
+ 0.9
+ </item>
+
<!-- If true, hide the display cutout with display area -->
<bool name="config_hideDisplayCutoutWithDisplayArea">false</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5df7a97..e695d22 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4255,6 +4255,8 @@
<java-symbol type="integer" name="config_letterboxBackgroundType" />
<java-symbol type="color" name="config_letterboxBackgroundColor" />
<java-symbol type="dimen" name="config_letterboxHorizontalPositionMultiplier" />
+ <java-symbol type="bool" name="config_letterboxIsReachabilityEnabled" />
+ <java-symbol type="dimen" name="config_letterboxDefaultPositionMultiplierForReachability" />
<java-symbol type="bool" name="config_hideDisplayCutoutWithDisplayArea" />
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index 685671b..34c1763 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -16,9 +16,11 @@
package android.app;
-import static androidx.core.graphics.ColorUtils.calculateContrast;
+import static android.app.Notification.Builder.ensureColorSpanContrast;
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.internal.util.ContrastColorUtilTest.assertContrastIsAtLeast;
+import static com.android.internal.util.ContrastColorUtilTest.assertContrastIsWithinRange;
import static com.google.common.truth.Truth.assertThat;
@@ -35,6 +37,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.LocusId;
+import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.graphics.BitmapFactory;
import android.graphics.Color;
@@ -42,12 +45,21 @@
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.TextAppearanceSpan;
import android.widget.RemoteViews;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.R;
+import com.android.internal.util.ContrastColorUtil;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -334,6 +346,163 @@
}
@Test
+ public void testBuilder_getFullLengthSpanColor_returnsNullForString() {
+ assertThat(Notification.Builder.getFullLengthSpanColor("String")).isNull();
+ }
+
+ @Test
+ public void testBuilder_getFullLengthSpanColor_returnsNullWithPartialSpan() {
+ CharSequence text = new SpannableStringBuilder()
+ .append("text with ")
+ .append("some red", new ForegroundColorSpan(Color.RED),
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ assertThat(Notification.Builder.getFullLengthSpanColor(text)).isNull();
+ }
+
+ @Test
+ public void testBuilder_getFullLengthSpanColor_worksWithSingleSpan() {
+ CharSequence text = new SpannableStringBuilder()
+ .append("text that is all red", new ForegroundColorSpan(Color.RED),
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ assertThat(Notification.Builder.getFullLengthSpanColor(text)).isEqualTo(Color.RED);
+ }
+
+ @Test
+ public void testBuilder_getFullLengthSpanColor_worksWithFullAndPartialSpans() {
+ Spannable text = new SpannableString("blue text with yellow and green");
+ text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(new ForegroundColorSpan(Color.BLUE), 0, text.length(),
+ Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ assertThat(Notification.Builder.getFullLengthSpanColor(text)).isEqualTo(Color.BLUE);
+ }
+
+ @Test
+ public void testBuilder_getFullLengthSpanColor_worksWithTextAppearance() {
+ Spannable text = new SpannableString("title text with yellow and green");
+ text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ TextAppearanceSpan textAppearanceSpan = new TextAppearanceSpan(mContext,
+ R.style.TextAppearance_DeviceDefault_Notification_Title);
+ int expectedTextColor = textAppearanceSpan.getTextColor().getDefaultColor();
+ text.setSpan(textAppearanceSpan, 0, text.length(),
+ Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ assertThat(Notification.Builder.getFullLengthSpanColor(text)).isEqualTo(expectedTextColor);
+ }
+
+ @Test
+ public void testBuilder_ensureColorSpanContrast_removesAllFullLengthColorSpans() {
+ Spannable text = new SpannableString("blue text with yellow and green");
+ text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(new ForegroundColorSpan(Color.BLUE), 0, text.length(),
+ Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ TextAppearanceSpan taSpan = new TextAppearanceSpan(mContext,
+ R.style.TextAppearance_DeviceDefault_Notification_Title);
+ assertThat(taSpan.getTextColor()).isNotNull(); // it must be set to prove it is cleared.
+ text.setSpan(taSpan, 0, text.length(),
+ Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ Spannable result = (Spannable) ensureColorSpanContrast(text, Color.BLACK);
+ Object[] spans = result.getSpans(0, result.length(), Object.class);
+ assertThat(spans).hasLength(3);
+
+ assertThat(result.getSpanStart(spans[0])).isEqualTo(15);
+ assertThat(result.getSpanEnd(spans[0])).isEqualTo(21);
+ assertThat(((ForegroundColorSpan) spans[0]).getForegroundColor()).isEqualTo(Color.YELLOW);
+
+ assertThat(result.getSpanStart(spans[1])).isEqualTo(0);
+ assertThat(result.getSpanEnd(spans[1])).isEqualTo(31);
+ assertThat(spans[1]).isNotSameInstanceAs(taSpan); // don't mutate the existing span
+ assertThat(((TextAppearanceSpan) spans[1]).getFamily()).isEqualTo(taSpan.getFamily());
+ assertThat(((TextAppearanceSpan) spans[1]).getTextColor()).isNull();
+
+ assertThat(result.getSpanStart(spans[2])).isEqualTo(26);
+ assertThat(result.getSpanEnd(spans[2])).isEqualTo(31);
+ assertThat(((ForegroundColorSpan) spans[2]).getForegroundColor()).isEqualTo(Color.GREEN);
+ }
+
+ @Test
+ public void testBuilder_ensureColorSpanContrast_partialLength_adjusted() {
+ int background = 0xFFFF0101; // Slightly lighter red
+ CharSequence text = new SpannableStringBuilder()
+ .append("text with ")
+ .append("some red", new ForegroundColorSpan(Color.RED),
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ CharSequence result = ensureColorSpanContrast(text, background);
+
+ // ensure the span has been updated to have > 1.3:1 contrast ratio with fill color
+ Object[] spans = ((Spannable) result).getSpans(0, result.length(), Object.class);
+ assertThat(spans).hasLength(1);
+ int foregroundColor = ((ForegroundColorSpan) spans[0]).getForegroundColor();
+ assertContrastIsWithinRange(foregroundColor, background, 3, 3.2);
+ }
+
+ @Test
+ public void testBuilder_ensureColorSpanContrast_worksWithComplexInput() {
+ Spannable text = new SpannableString("blue text with yellow and green and cyan");
+ text.setSpan(new ForegroundColorSpan(Color.YELLOW), 15, 21,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(new ForegroundColorSpan(Color.BLUE), 0, text.length(),
+ Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ // cyan TextAppearanceSpan
+ TextAppearanceSpan taSpan = new TextAppearanceSpan(mContext,
+ R.style.TextAppearance_DeviceDefault_Notification_Title);
+ taSpan = new TextAppearanceSpan(taSpan.getFamily(), taSpan.getTextStyle(),
+ taSpan.getTextSize(), ColorStateList.valueOf(Color.CYAN), null);
+ text.setSpan(taSpan, 36, 40,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(new ForegroundColorSpan(Color.GREEN), 26, 31,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ Spannable result = (Spannable) ensureColorSpanContrast(text, Color.GRAY);
+ Object[] spans = result.getSpans(0, result.length(), Object.class);
+ assertThat(spans).hasLength(3);
+
+ assertThat(result.getSpanStart(spans[0])).isEqualTo(15);
+ assertThat(result.getSpanEnd(spans[0])).isEqualTo(21);
+ assertThat(((ForegroundColorSpan) spans[0]).getForegroundColor()).isEqualTo(Color.YELLOW);
+
+ assertThat(result.getSpanStart(spans[1])).isEqualTo(36);
+ assertThat(result.getSpanEnd(spans[1])).isEqualTo(40);
+ assertThat(spans[1]).isNotSameInstanceAs(taSpan); // don't mutate the existing span
+ assertThat(((TextAppearanceSpan) spans[1]).getFamily()).isEqualTo(taSpan.getFamily());
+ ColorStateList newCyanList = ((TextAppearanceSpan) spans[1]).getTextColor();
+ assertThat(newCyanList).isNotNull();
+ assertContrastIsWithinRange(newCyanList.getDefaultColor(), Color.GRAY, 3, 3.2);
+
+ assertThat(result.getSpanStart(spans[2])).isEqualTo(26);
+ assertThat(result.getSpanEnd(spans[2])).isEqualTo(31);
+ int newGreen = ((ForegroundColorSpan) spans[2]).getForegroundColor();
+ assertThat(newGreen).isNotEqualTo(Color.GREEN);
+ assertContrastIsWithinRange(newGreen, Color.GRAY, 3, 3.2);
+ }
+
+ @Test
+ public void testBuilder_ensureButtonFillContrast_adjustsDarker() {
+ int background = Color.LTGRAY;
+ int foreground = Color.LTGRAY;
+ int result = Notification.Builder.ensureButtonFillContrast(foreground, background);
+ assertContrastIsWithinRange(result, background, 1.3, 1.5);
+ assertThat(ContrastColorUtil.calculateLuminance(result))
+ .isLessThan(ContrastColorUtil.calculateLuminance(background));
+ }
+
+ @Test
+ public void testBuilder_ensureButtonFillContrast_adjustsLighter() {
+ int background = Color.DKGRAY;
+ int foreground = Color.DKGRAY;
+ int result = Notification.Builder.ensureButtonFillContrast(foreground, background);
+ assertContrastIsWithinRange(result, background, 1.3, 1.5);
+ assertThat(ContrastColorUtil.calculateLuminance(result))
+ .isGreaterThan(ContrastColorUtil.calculateLuminance(background));
+ }
+
+ @Test
public void testColors_ensureColors_dayMode_producesValidPalette() {
Notification.Colors c = new Notification.Colors();
boolean colorized = false;
@@ -437,16 +606,6 @@
assertContrastIsAtLeast(c.getOnAccentTextColor(), c.getTertiaryAccentColor(), 4.5);
}
- private void assertContrastIsAtLeast(int foreground, int background, double minContrast) {
- try {
- assertThat(calculateContrast(foreground, background)).isAtLeast(minContrast);
- } catch (AssertionError e) {
- throw new AssertionError(
- String.format("Insufficient contrast: foreground=#%08x background=#%08x",
- foreground, background), e);
- }
- }
-
private void resolveColorsInNightMode(boolean nightMode, Notification.Colors c, int rawColor,
boolean colorized) {
runInNightMode(nightMode,
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index 97652a9..75d2025 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -384,10 +384,10 @@
info = createPackageManagerMockedInfo(true);
pg = new ResolveInfoPresentationGetter(
info.ctx, 0, info.resolveInfo);
- assertThat("With override permission label should match resolve info label if set",
- pg.getLabel().equals(info.setResolveInfoLabel));
- assertThat("With override permission sublabel should be empty",
- TextUtils.isEmpty(pg.getSubLabel()));
+ assertThat("With override permission label should match activity label if set",
+ pg.getLabel().equals(info.setActivityLabel));
+ assertThat("With override permission the sublabel should be the resolve info label",
+ pg.getSubLabel().equals(info.setResolveInfoLabel));
}
@Test
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
index dac35e5..eb3bae0 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
@@ -16,6 +16,8 @@
package com.android.internal.os;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -24,7 +26,6 @@
import android.util.SparseArray;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.os.KernelSingleUidTimeReader.Injector;
@@ -279,6 +280,46 @@
0, lastUidCpuTimes.size());
}
+ @Test
+ public void testAddDeltaFromBpf() {
+ LongArrayMultiStateCounter counter = new LongArrayMultiStateCounter(2, 5, 0, 0);
+
+ // Nanoseconds
+ mInjector.setCpuTimeInStatePerClusterNs(
+ new long[][]{
+ {1_000_000, 2_000_000, 3_000_000},
+ {4_000_000, 5_000_000}});
+
+ boolean success = mInjector.addDelta(TEST_UID, counter, 2000);
+ assertThat(success).isTrue();
+
+ LongArrayMultiStateCounter.LongArrayContainer array =
+ new LongArrayMultiStateCounter.LongArrayContainer(5);
+ long[] out = new long[5];
+
+ counter.getCounts(array, 0);
+ array.getValues(out);
+ assertThat(out).isEqualTo(new long[]{1, 2, 3, 4, 5});
+
+ counter.setState(1, 3000);
+
+ mInjector.setCpuTimeInStatePerClusterNs(
+ new long[][]{
+ {11_000_000, 22_000_000, 33_000_000},
+ {44_000_000, 55_000_000}});
+
+ success = mInjector.addDelta(TEST_UID, counter, 4000);
+ assertThat(success).isTrue();
+
+ counter.getCounts(array, 0);
+ array.getValues(out);
+ assertThat(out).isEqualTo(new long[]{1 + 5, 2 + 10, 3 + 15, 4 + 20, 5 + 25});
+
+ counter.getCounts(array, 1);
+ array.getValues(out);
+ assertThat(out).isEqualTo(new long[]{5, 10, 15, 20, 25});
+ }
+
private void assertCpuTimesEqual(long[] expected, long[] actual) {
assertArrayEquals("Expected=" + Arrays.toString(expected)
+ ", Actual=" + Arrays.toString(actual), expected, actual);
@@ -288,6 +329,7 @@
private byte[] mData;
private long[] mBpfData;
private boolean mThrowExcpetion;
+ private long[][] mCpuTimeInStatePerClusterNs;
@Override
public byte[] readData(String procFile) throws IOException {
@@ -316,8 +358,17 @@
mBpfData = cpuTimes.clone();
}
+ public void setCpuTimeInStatePerClusterNs(long[][] cpuTimeInStatePerClusterNs) {
+ mCpuTimeInStatePerClusterNs = cpuTimeInStatePerClusterNs;
+ }
+
public void letReadDataThrowException(boolean throwException) {
mThrowExcpetion = throwException;
}
+
+ @Override
+ public boolean addDelta(int uid, LongArrayMultiStateCounter counter, long timestampMs) {
+ return addDeltaForTest(uid, counter, timestampMs, mCpuTimeInStatePerClusterNs);
+ }
}
}
diff --git a/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java b/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java
index 9da720c..cfe660c 100644
--- a/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java
@@ -70,13 +70,13 @@
assertContrastIsWithinRange(selfContrastColor, lightBg, 4.5, 4.75);
}
- private void assertContrastIsWithinRange(int foreground, int background,
+ public static void assertContrastIsWithinRange(int foreground, int background,
double minContrast, double maxContrast) {
assertContrastIsAtLeast(foreground, background, minContrast);
assertContrastIsAtMost(foreground, background, maxContrast);
}
- private void assertContrastIsAtLeast(int foreground, int background, double minContrast) {
+ public static void assertContrastIsAtLeast(int foreground, int background, double minContrast) {
try {
assertThat(calculateContrast(foreground, background)).isAtLeast(minContrast);
} catch (AssertionError e) {
@@ -86,7 +86,7 @@
}
}
- private void assertContrastIsAtMost(int foreground, int background, double maxContrast) {
+ public static void assertContrastIsAtMost(int foreground, int background, double maxContrast) {
try {
assertThat(calculateContrast(foreground, background)).isAtMost(maxContrast);
} catch (AssertionError e) {
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 0d7225b..119c9391 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1207,6 +1207,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-779535710": {
+ "message": "Transition %d: Set %s as transient-launch",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/Transition.java"
+ },
"-775004869": {
"message": "Not a match: %s",
"level": "DEBUG",
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java
index 9212a0f..46c8ffe 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java
@@ -210,17 +210,17 @@
void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
@NonNull IBinder primary, @Nullable IBinder secondary, @Nullable SplitRule splitRule) {
- WindowContainerTransaction.TaskFragmentAdjacentOptions adjacentOptions = null;
+ WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = null;
final boolean finishSecondaryWithPrimary =
splitRule != null && SplitContainer.shouldFinishSecondaryWithPrimary(splitRule);
final boolean finishPrimaryWithSecondary =
splitRule != null && SplitContainer.shouldFinishPrimaryWithSecondary(splitRule);
if (finishSecondaryWithPrimary || finishPrimaryWithSecondary) {
- adjacentOptions = new WindowContainerTransaction.TaskFragmentAdjacentOptions();
- adjacentOptions.setDelayPrimaryLastActivityRemoval(finishSecondaryWithPrimary);
- adjacentOptions.setDelaySecondaryLastActivityRemoval(finishPrimaryWithSecondary);
+ adjacentParams = new WindowContainerTransaction.TaskFragmentAdjacentParams();
+ adjacentParams.setShouldDelayPrimaryLastActivityRemoval(finishSecondaryWithPrimary);
+ adjacentParams.setShouldDelaySecondaryLastActivityRemoval(finishPrimaryWithSecondary);
}
- wct.setAdjacentTaskFragments(primary, secondary, adjacentOptions);
+ wct.setAdjacentTaskFragments(primary, secondary, adjacentParams);
}
TaskFragmentCreationParams createFragmentOptions(IBinder fragmentToken, IBinder ownerToken,
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index e0654bd..ad5a68e40 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -61,7 +61,7 @@
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> સેટિંગ"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"બબલને છોડી દો"</string>
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"વાતચીતને બબલ કરશો નહીં"</string>
- <string name="bubbles_user_education_title" msgid="2112319053732691899">"બબલનો ઉપયોગ કરીને ચેટ કરો"</string>
+ <string name="bubbles_user_education_title" msgid="2112319053732691899">"બબલનો ઉપયોગ કરીને ચૅટ કરો"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"નવી વાતચીત ફ્લોટિંગ આઇકન અથવા બબલ જેવી દેખાશે. બબલને ખોલવા માટે ટૅપ કરો. તેને ખસેડવા માટે ખેંચો."</string>
<string name="bubbles_user_education_manage_title" msgid="7042699946735628035">"બબલને કોઈપણ સમયે નિયંત્રિત કરો"</string>
<string name="bubbles_user_education_manage" msgid="3460756219946517198">"આ ઍપમાંથી બબલને બંધ કરવા માટે મેનેજ કરો પર ટૅપ કરો"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
index 9c97ffe..3c8aaa4 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
@@ -18,7 +18,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="pip_phone_close" msgid="5783752637260411309">"Fechar"</string>
- <string name="pip_phone_expand" msgid="2579292903468287504">"Expandir"</string>
+ <string name="pip_phone_expand" msgid="2579292903468287504">"Abrir"</string>
<string name="pip_phone_settings" msgid="5468987116750491918">"Configurações"</string>
<string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
<string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml
index 9c97ffe..3c8aaa4 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings.xml
@@ -18,7 +18,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="pip_phone_close" msgid="5783752637260411309">"Fechar"</string>
- <string name="pip_phone_expand" msgid="2579292903468287504">"Expandir"</string>
+ <string name="pip_phone_expand" msgid="2579292903468287504">"Abrir"</string>
<string name="pip_phone_settings" msgid="5468987116750491918">"Configurações"</string>
<string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
<string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string>
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 0c422df..b348a6e 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -341,6 +341,7 @@
sk_sp<SkImage> snapshot = layerSurface->makeImageSnapshot();
const auto subset = SkIRect::MakeWH(properties().getWidth(),
properties().getHeight());
+ uint32_t layerSurfaceGenerationId = layerSurface->generationID();
// If we don't have an ImageFilter just return the snapshot
if (imageFilter == nullptr) {
mSnapshotResult.snapshot = snapshot;
@@ -348,9 +349,10 @@
mSnapshotResult.outOffset = SkIPoint::Make(0.0f, 0.0f);
mImageFilterClipBounds = clipBounds;
mTargetImageFilter = nullptr;
- } else if (mSnapshotResult.snapshot == nullptr ||
- imageFilter != mTargetImageFilter.get() ||
- mImageFilterClipBounds != clipBounds) {
+ mTargetImageFilterLayerSurfaceGenerationId = 0;
+ } else if (mSnapshotResult.snapshot == nullptr || imageFilter != mTargetImageFilter.get() ||
+ mImageFilterClipBounds != clipBounds ||
+ mTargetImageFilterLayerSurfaceGenerationId != layerSurfaceGenerationId) {
// Otherwise create a new snapshot with the given filter and snapshot
mSnapshotResult.snapshot =
snapshot->makeWithFilter(context,
@@ -361,6 +363,7 @@
&mSnapshotResult.outOffset);
mTargetImageFilter = sk_ref_sp(imageFilter);
mImageFilterClipBounds = clipBounds;
+ mTargetImageFilterLayerSurfaceGenerationId = layerSurfaceGenerationId;
}
return mSnapshotResult;
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 45a4f6c..da04762 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -396,6 +396,7 @@
* SkImageFilter used to create the mSnapshotResult
*/
sk_sp<SkImageFilter> mTargetImageFilter;
+ uint32_t mTargetImageFilterLayerSurfaceGenerationId = 0;
/**
* Clip bounds used to create the mSnapshotResult
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index dbf2621..637f905 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -358,7 +358,7 @@
}
/**
- * Gets the data of the reported GPS message.
+ * Gets the data of the reported GNSS message.
*
* <p>The bytes (or words) specified using big endian format (MSB first).
*
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 91834fb..81e29e7 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2457,8 +2457,7 @@
/**
* Return a handle to the optional platform's {@link Spatializer}
- * @return {@code null} if spatialization is not supported, the {@code Spatializer} instance
- * otherwise.
+ * @return the {@code Spatializer} instance.
*/
public @Nullable Spatializer getSpatializer() {
int level = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
diff --git a/media/java/android/media/IMediaRouterClient.aidl b/media/java/android/media/IMediaRouterClient.aidl
index 6b754e1..9b49123 100644
--- a/media/java/android/media/IMediaRouterClient.aidl
+++ b/media/java/android/media/IMediaRouterClient.aidl
@@ -23,5 +23,4 @@
void onStateChanged();
void onRestoreRoute();
void onGroupRouteSelected(String routeId);
- void onGlobalA2dpChanged(boolean a2dpOn);
}
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index a15529e..458821e 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -928,7 +928,7 @@
private @NonNull List<Bitmap> getFramesAtIndexInternal(
int frameIndex, int numFrames, @Nullable BitmapParams params) {
if (!"yes".equals(extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO))) {
- throw new IllegalStateException("Does not contail video or image sequences");
+ throw new IllegalStateException("Does not contain video or image sequences");
}
int frameCount = Integer.parseInt(
extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT));
@@ -1046,7 +1046,7 @@
private Bitmap getImageAtIndexInternal(int imageIndex, @Nullable BitmapParams params) {
if (!"yes".equals(extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_IMAGE))) {
- throw new IllegalStateException("Does not contail still images");
+ throw new IllegalStateException("Does not contain still images");
}
String imageCount = extractMetadata(MediaMetadataRetriever.METADATA_KEY_IMAGE_COUNT);
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 4de63f9..62b9cb0 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -654,9 +654,12 @@
final class Client extends IMediaRouterClient.Stub {
@Override
public void onStateChanged() {
- mHandler.post(() -> {
- if (Client.this == mClient) {
- updateClientState();
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (Client.this == mClient) {
+ updateClientState();
+ }
}
});
}
@@ -690,26 +693,6 @@
}
});
}
-
- // Called when the selection of a connected device (phone speaker or BT devices)
- // is changed.
- @Override
- public void onGlobalA2dpChanged(boolean a2dpOn) {
- mHandler.post(() -> {
- if (mSelectedRoute == null || mBluetoothA2dpRoute == null) {
- return;
- }
- if (mSelectedRoute.isDefault() && a2dpOn) {
- setSelectedRoute(mBluetoothA2dpRoute, /*explicit=*/ false);
- dispatchRouteUnselected(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo);
- dispatchRouteSelected(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute);
- } else if (mSelectedRoute.isBluetooth() && !a2dpOn) {
- setSelectedRoute(mDefaultAudioVideo, /*explicit=*/ false);
- dispatchRouteUnselected(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute);
- dispatchRouteSelected(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo);
- }
- });
- }
}
}
@@ -1367,9 +1350,6 @@
}
static void dispatchRouteSelected(int type, RouteInfo info) {
- if (DEBUG) {
- Log.d(TAG, "Dispatching route selected: " + info);
- }
for (CallbackInfo cbi : sStatic.mCallbacks) {
if (cbi.filterRouteEvent(info)) {
cbi.cb.onRouteSelected(cbi.router, type, info);
@@ -1378,9 +1358,6 @@
}
static void dispatchRouteUnselected(int type, RouteInfo info) {
- if (DEBUG) {
- Log.d(TAG, "Dispatching route unselected: " + info);
- }
for (CallbackInfo cbi : sStatic.mCallbacks) {
if (cbi.filterRouteEvent(info)) {
cbi.cb.onRouteUnselected(cbi.router, type, info);
diff --git a/media/java/android/media/Spatializer.java b/media/java/android/media/Spatializer.java
index 3ed8b58..c64bf2c 100644
--- a/media/java/android/media/Spatializer.java
+++ b/media/java/android/media/Spatializer.java
@@ -114,6 +114,7 @@
/** @hide */
@IntDef(flag = false, value = {
+ SPATIALIZER_IMMERSIVE_LEVEL_OTHER,
SPATIALIZER_IMMERSIVE_LEVEL_NONE,
SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL,
})
@@ -122,21 +123,46 @@
/**
* @hide
+ * Constant indicating the {@code Spatializer} on this device supports a spatialization
+ * mode that differs from the ones available at this SDK level.
+ * @see #getImmersiveAudioLevel()
+ */
+ public static final int SPATIALIZER_IMMERSIVE_LEVEL_OTHER = -1;
+
+ /**
+ * @hide
* Constant indicating there are no spatialization capabilities supported on this device.
- * @see AudioManager#getImmersiveAudioLevel()
+ * @see #getImmersiveAudioLevel()
*/
public static final int SPATIALIZER_IMMERSIVE_LEVEL_NONE = 0;
/**
* @hide
- * Constant indicating the {@link Spatializer} on this device supports multichannel
+ * Constant indicating the {@code Spatializer} on this device supports multichannel
* spatialization.
- * @see AudioManager#getImmersiveAudioLevel()
+ * @see #getImmersiveAudioLevel()
*/
public static final int SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL = 1;
/**
* @hide
+ * Return the level of support for the spatialization feature on this device.
+ * This level of support is independent of whether the {@code Spatializer} is currently
+ * enabled or available and will not change over time.
+ * @return the level of spatialization support
+ * @see #isEnabled()
+ * @see #isAvailable()
+ */
+ public @ImmersiveAudioLevel int getImmersiveAudioLevel() {
+ int level = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
+ try {
+ level = mAm.getService().getSpatializerImmersiveAudioLevel();
+ } catch (Exception e) { /* using NONE */ }
+ return level;
+ }
+
+ /**
+ * @hide
* Enables / disables the spatializer effect.
* Changing the enabled state will trigger the public
* {@link OnSpatializerStateChangedListener#onSpatializerEnabledChanged(Spatializer, boolean)}
diff --git a/mms/OWNERS b/mms/OWNERS
index 7f05a2a..2e419c1 100644
--- a/mms/OWNERS
+++ b/mms/OWNERS
@@ -9,10 +9,10 @@
jminjie@google.com
satk@google.com
shuoq@google.com
-nazaninb@google.com
sarahchin@google.com
xiaotonj@google.com
huiwang@google.com
jayachandranc@google.com
chinmayd@google.com
amruthr@google.com
+sasindran@google.com
diff --git a/packages/CarrierDefaultApp/OWNERS b/packages/CarrierDefaultApp/OWNERS
index 0d23f05..a2352e2 100644
--- a/packages/CarrierDefaultApp/OWNERS
+++ b/packages/CarrierDefaultApp/OWNERS
@@ -8,11 +8,11 @@
jminjie@google.com
satk@google.com
shuoq@google.com
-nazaninb@google.com
sarahchin@google.com
xiaotonj@google.com
huiwang@google.com
jayachandranc@google.com
chinmayd@google.com
amruthr@google.com
+sasindran@google.com
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
index c24782e..3636f8f 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
@@ -38,7 +38,6 @@
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
-import android.companion.Association;
import android.companion.AssociationRequest;
import android.companion.BluetoothDeviceFilter;
import android.companion.BluetoothLeDeviceFilter;
@@ -95,7 +94,7 @@
DeviceFilterPair mSelectedDevice;
IFindDeviceCallback mFindCallback;
- AndroidFuture<Association> mServiceCallback;
+ AndroidFuture<String> mServiceCallback;
boolean mIsScanning = false;
@Nullable
CompanionDeviceActivity mActivity = null;
@@ -106,7 +105,7 @@
public void startDiscovery(AssociationRequest request,
String callingPackage,
IFindDeviceCallback findCallback,
- AndroidFuture serviceCallback) {
+ AndroidFuture<String> serviceCallback) {
Log.i(LOG_TAG,
"startDiscovery() called with: filter = [" + request
+ "], findCallback = [" + findCallback + "]"
@@ -320,9 +319,7 @@
if (callingPackage == null || deviceAddress == null) {
return;
}
- mServiceCallback.complete(new Association(
- getUserId(), deviceAddress, callingPackage, mRequest.getDeviceProfile(), false,
- System.currentTimeMillis()));
+ mServiceCallback.complete(deviceAddress);
}
void onCancel() {
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java b/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java
index 1ecc422..1d1316a 100644
--- a/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java
@@ -191,6 +191,13 @@
? View.VISIBLE : View.GONE);
}
+ /**
+ * Returns whether this preference is a checkbox.
+ */
+ public boolean isCheckBox() {
+ return mIsCheckBox;
+ }
+
private void init() {
if (mIsCheckBox) {
setWidgetLayoutResource(R.layout.preference_widget_checkbox);
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index f895636..dde780a 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -272,9 +272,9 @@
<string name="oem_unlock_enable_summary" msgid="5857388174390953829">"Tillad, at startindlæseren låses op"</string>
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"Vil du tillade OEM-oplåsning?"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"ADVARSEL! Funktioner, der beskytter enheden, fungerer ikke på denne enhed, når denne indstilling er aktiveret."</string>
- <string name="mock_location_app" msgid="6269380172542248304">"Vælg app til falsk placering"</string>
- <string name="mock_location_app_not_set" msgid="6972032787262831155">"Der er ikke angivet nogen app til falsk placering"</string>
- <string name="mock_location_app_set" msgid="4706722469342913843">"App til falsk placering: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="mock_location_app" msgid="6269380172542248304">"Vælg app til falsk lokation"</string>
+ <string name="mock_location_app_not_set" msgid="6972032787262831155">"Der er ikke angivet nogen app til falsk lokation"</string>
+ <string name="mock_location_app_set" msgid="4706722469342913843">"App til falsk lokation: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"Netværk"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"Certificering af trådløs skærm"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Aktivér detaljeret Wi-Fi-logføring"</string>
@@ -322,8 +322,8 @@
<string name="select_logpersist_dialog_title" msgid="7745193591195485594">"Vælg logbuffere, der skal gemmes permanent på enheden"</string>
<string name="select_usb_configuration_title" msgid="6339801314922294586">"Vælg USB-konfiguration"</string>
<string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"Vælg USB-konfiguration"</string>
- <string name="allow_mock_location" msgid="2102650981552527884">"Imiterede placeringer"</string>
- <string name="allow_mock_location_summary" msgid="179780881081354579">"Tillad imiterede placeringer"</string>
+ <string name="allow_mock_location" msgid="2102650981552527884">"Imiterede lokationer"</string>
+ <string name="allow_mock_location_summary" msgid="179780881081354579">"Tillad imiterede lokationer"</string>
<string name="debug_view_attributes" msgid="3539609843984208216">"Aktivér visning af attributinspektion"</string>
<string name="mobile_data_always_on_summary" msgid="1112156365594371019">"Hold altid mobildata aktiveret, selv når Wi-Fi er aktiveret (for at skifte hurtigt mellem netværk)."</string>
<string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Brug hardwareacceleration ved netdeling, hvis det er muligt"</string>
@@ -359,7 +359,7 @@
<string name="debug_monitoring_category" msgid="1597387133765424994">"Overvågning"</string>
<string name="strict_mode" msgid="889864762140862437">"Striks tilstand aktiveret"</string>
<string name="strict_mode_summary" msgid="1838248687233554654">"Blink med skærmen, når apps foretager handlinger på hovedtråd"</string>
- <string name="pointer_location" msgid="7516929526199520173">"Markørens placering"</string>
+ <string name="pointer_location" msgid="7516929526199520173">"Markørens lokation"</string>
<string name="pointer_location_summary" msgid="957120116989798464">"Skærmoverlejringen viser de aktuelle berøringsdata"</string>
<string name="show_touches" msgid="8437666942161289025">"Vis tryk"</string>
<string name="show_touches_summary" msgid="3692861665994502193">"Vis visuel feedback ved tryk"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 229ed45..80439d9 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -74,7 +74,7 @@
<string name="private_dns_broken" msgid="1984159464346556931">"Жеке DNS серверіне кіру мүмкін емес."</string>
<string name="wifi_limited_connection" msgid="1184778285475204682">"Шектеулі байланыс"</string>
<string name="wifi_status_no_internet" msgid="3799933875988829048">"Интернетпен байланыс жоқ"</string>
- <string name="wifi_status_sign_in_required" msgid="2236267500459526855">"Есептік жазбаға кіру керек"</string>
+ <string name="wifi_status_sign_in_required" msgid="2236267500459526855">"Аккаунтқа кіру керек"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5885145407184194503">"Кіру нүктесі уақытша бос емес"</string>
<string name="connected_via_carrier" msgid="1968057009076191514">"%1$s арқылы қосылды"</string>
<string name="available_via_carrier" msgid="465598683092718294">"%1$s арқылы қолжетімді"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 485f40a..4365b20 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -579,7 +579,7 @@
<string name="user_setup_dialog_message" msgid="269931619868102841">"तो वापरकर्ता डिव्हाइसजवळ आहे आणि त्याचे स्थान सेट करण्यासाठी उपलब्ध आहे याची खात्री करा"</string>
<string name="user_setup_profile_dialog_message" msgid="4788197052296962620">"आता प्रोफाईल सेट करायचा?"</string>
<string name="user_setup_button_setup_now" msgid="1708269547187760639">"आता सेट करा"</string>
- <string name="user_setup_button_setup_later" msgid="8712980133555493516">"आत्ता नाही"</string>
+ <string name="user_setup_button_setup_later" msgid="8712980133555493516">"आता नको"</string>
<string name="user_add_user_type_title" msgid="551279664052914497">"जोडा"</string>
<string name="user_new_user_name" msgid="60979820612818840">"नवीन वापरकर्ता"</string>
<string name="user_new_profile_name" msgid="2405500423304678841">"नवीन प्रोफाईल"</string>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index c062007..35cc015 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -59,7 +59,7 @@
<item msgid="6421717003037072581">"Vždy používať kontrolu HDCP"</item>
</string-array>
<string-array name="bt_hci_snoop_log_entries">
- <item msgid="695678520785580527">"Deaktivované"</item>
+ <item msgid="695678520785580527">"Vypnuté"</item>
<item msgid="6336372935919715515">"Aktivované filtrované"</item>
<item msgid="2779123106632690576">"Aktivované"</item>
</string-array>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 421a428..b189595 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -322,8 +322,8 @@
<string name="select_logpersist_dialog_title" msgid="7745193591195485594">"పరికరంలో నిరంతరం నిల్వ చేయాల్సిన లాగ్ బఫర్లను ఎంచుకోండి"</string>
<string name="select_usb_configuration_title" msgid="6339801314922294586">"USB కాన్ఫిగరేషన్ని ఎంచుకోండి"</string>
<string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"USB కాన్ఫిగరేషన్ని ఎంచుకోండి"</string>
- <string name="allow_mock_location" msgid="2102650981552527884">"అనుకృత స్థానాలను అనుమతించు"</string>
- <string name="allow_mock_location_summary" msgid="179780881081354579">"అనుకృత స్థానాలను అనుమతించు"</string>
+ <string name="allow_mock_location" msgid="2102650981552527884">"డమ్మీ లొకేషన్లను అనుమతించండి"</string>
+ <string name="allow_mock_location_summary" msgid="179780881081354579">"డమ్మీ లొకేషన్లను అనుమతించండి"</string>
<string name="debug_view_attributes" msgid="3539609843984208216">"వీక్షణ అట్రిబ్యూట్ పర్యవేక్షణను ఎనేబుల్ చేయి"</string>
<string name="mobile_data_always_on_summary" msgid="1112156365594371019">"ఎల్లప్పుడూ మొబైల్ డేటాను యాక్టివ్గా ఉంచు, Wi‑Fi యాక్టివ్గా ఉన్నా కూడా (వేగవంతమైన నెట్వర్క్ మార్పు కోసం)."</string>
<string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"అందుబాటులో ఉంటే టెథెరింగ్ హార్డ్వేర్ వేగవృద్ధిని ఉపయోగించండి"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/SignalIcon.java b/packages/SettingsLib/src/com/android/settingslib/SignalIcon.java
index bc0c6f3..aba06056 100644
--- a/packages/SettingsLib/src/com/android/settingslib/SignalIcon.java
+++ b/packages/SettingsLib/src/com/android/settingslib/SignalIcon.java
@@ -139,17 +139,15 @@
public static class MobileIconGroup extends IconGroup {
public final int dataContentDescription; // mContentDescriptionDataType
public final int dataType;
- public final boolean isWide;
public final int qsDataType;
public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
- int discContentDesc, int dataContentDesc, int dataType, boolean isWide) {
+ int discContentDesc, int dataContentDesc, int dataType) {
super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState,
qsDiscState, discContentDesc);
this.dataContentDescription = dataContentDesc;
this.dataType = dataType;
- this.isWide = isWide;
this.qsDataType = dataType; // TODO: remove this field
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java b/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
index f8565bc..d4e58f7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
@@ -50,178 +50,194 @@
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.carrier_network_change_mode,
- 0,
- false);
+ 0
+ );
public static final MobileIconGroup THREE_G = new MobileIconGroup(
"3G",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_3g,
- TelephonyIcons.ICON_3G,
- true);
+ TelephonyIcons.ICON_3G
+ );
public static final MobileIconGroup WFC = new MobileIconGroup(
"WFC",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- 0, 0, false);
+ 0,
+ 0);
public static final MobileIconGroup UNKNOWN = new MobileIconGroup(
"Unknown",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
- 0, 0, false);
+ 0,
+ 0);
public static final MobileIconGroup E = new MobileIconGroup(
"E",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_edge,
- TelephonyIcons.ICON_E,
- false);
+ TelephonyIcons.ICON_E
+ );
public static final MobileIconGroup ONE_X = new MobileIconGroup(
"1X",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_cdma,
- TelephonyIcons.ICON_1X,
- true);
+ TelephonyIcons.ICON_1X
+ );
public static final MobileIconGroup G = new MobileIconGroup(
"G",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_gprs,
- TelephonyIcons.ICON_G,
- false);
+ TelephonyIcons.ICON_G
+ );
public static final MobileIconGroup H = new MobileIconGroup(
"H",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_3_5g,
- TelephonyIcons.ICON_H,
- false);
+ TelephonyIcons.ICON_H
+ );
public static final MobileIconGroup H_PLUS = new MobileIconGroup(
"H+",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_3_5g_plus,
- TelephonyIcons.ICON_H_PLUS,
- false);
+ TelephonyIcons.ICON_H_PLUS
+ );
public static final MobileIconGroup FOUR_G = new MobileIconGroup(
"4G",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_4g,
- TelephonyIcons.ICON_4G,
- true);
+ TelephonyIcons.ICON_4G
+ );
public static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup(
"4G+",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_4g_plus,
- TelephonyIcons.ICON_4G_PLUS,
- true);
+ TelephonyIcons.ICON_4G_PLUS
+ );
public static final MobileIconGroup LTE = new MobileIconGroup(
"LTE",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_lte,
- TelephonyIcons.ICON_LTE,
- true);
+ TelephonyIcons.ICON_LTE
+ );
public static final MobileIconGroup LTE_PLUS = new MobileIconGroup(
"LTE+",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_lte_plus,
- TelephonyIcons.ICON_LTE_PLUS,
- true);
+ TelephonyIcons.ICON_LTE_PLUS
+ );
public static final MobileIconGroup LTE_CA_5G_E = new MobileIconGroup(
"5Ge",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_5ge_html,
- TelephonyIcons.ICON_5G_E,
- true);
+ TelephonyIcons.ICON_5G_E
+ );
public static final MobileIconGroup NR_5G = new MobileIconGroup(
"5G",
@@ -234,8 +250,8 @@
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_5g,
- TelephonyIcons.ICON_5G,
- true);
+ TelephonyIcons.ICON_5G
+ );
public static final MobileIconGroup NR_5G_PLUS = new MobileIconGroup(
"5G_PLUS",
@@ -248,34 +264,36 @@
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_5g_plus,
- TelephonyIcons.ICON_5G_PLUS,
- true);
+ TelephonyIcons.ICON_5G_PLUS
+ );
public static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
"DataDisabled",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.cell_data_off_content_description,
- 0,
- false);
+ 0
+ );
public static final MobileIconGroup NOT_DEFAULT_DATA = new MobileIconGroup(
"NotDefaultData",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0, 0,
+ 0,
+ 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.not_default_data_content_description,
- 0,
- false);
+ 0
+ );
public static final MobileIconGroup CARRIER_MERGED_WIFI = new MobileIconGroup(
"CWF",
@@ -288,8 +306,8 @@
/* qsDiscState= */ 0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
R.string.data_connection_carrier_wifi,
- TelephonyIcons.ICON_CWF,
- /* isWide= */ true);
+ TelephonyIcons.ICON_CWF
+ );
// When adding a new MobileIconGround, check if the dataContentDescription has to be filtered
// in QSCarrier#hasValidTypeContentDescription
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index 80b7e10..6f42d59 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -81,6 +81,9 @@
Settings.Global.POWER_BUTTON_LONG_PRESS,
Settings.Global.AUTOMATIC_POWER_SAVE_MODE,
Settings.Global.ADVANCED_BATTERY_USAGE_AMOUNT,
- Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS
+ Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS,
+ Settings.Global.USER_PREFERRED_REFRESH_RATE,
+ Settings.Global.USER_PREFERRED_RESOLUTION_HEIGHT,
+ Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH,
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 0a75eb8..93f900d 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -21,6 +21,7 @@
import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_FLOAT_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.PERCENTAGE_INTEGER_VALIDATOR;
@@ -321,6 +322,9 @@
VALIDATORS.put(Global.Wearable.COMBINED_LOCATION_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.Wearable.WRIST_ORIENTATION_MODE,
new DiscreteValueValidator(new String[] {"0", "1", "2", "3"}));
+ VALIDATORS.put(Global.USER_PREFERRED_REFRESH_RATE, NON_NEGATIVE_FLOAT_VALIDATOR);
+ VALIDATORS.put(Global.USER_PREFERRED_RESOLUTION_HEIGHT, ANY_INTEGER_VALIDATOR);
+ VALIDATORS.put(Global.USER_PREFERRED_RESOLUTION_WIDTH, ANY_INTEGER_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
index 223cc51..49012b0 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
@@ -74,6 +74,20 @@
}
};
+ public static final Validator NON_NEGATIVE_FLOAT_VALIDATOR = new Validator() {
+ @Override
+ public boolean validate(@Nullable String value) {
+ if (value == null) {
+ return true;
+ }
+ try {
+ return Float.parseFloat(value) >= 0.0f;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+ };
+
public static final Validator URI_VALIDATOR = new Validator() {
@Override
public boolean validate(@Nullable String value) {
diff --git a/packages/Shell/res/values-da/strings.xml b/packages/Shell/res/values-da/strings.xml
index c23efc3..049d2ac 100644
--- a/packages/Shell/res/values-da/strings.xml
+++ b/packages/Shell/res/values-da/strings.xml
@@ -28,7 +28,7 @@
<string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Vælg for at dele din fejlrapport uden et screenshot, eller vent på, at et screenshot er klar"</string>
<string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et screenshot, eller vent på, at screenshott fuldføres"</string>
<string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et screenshot, eller vent på, at screenshott fuldføres"</string>
- <string name="bugreport_confirm" msgid="5917407234515812495">"Fejlrapporter indeholder data fra systemets forskellige logfiler, og der kan være følsomme data imellem (f.eks. appforbrug og placeringsdata). Del kun fejlrapporter med personer og apps, du har tillid til."</string>
+ <string name="bugreport_confirm" msgid="5917407234515812495">"Fejlrapporter indeholder data fra systemets forskellige logfiler, og der kan være følsomme data imellem (f.eks. appforbrug og lokationsdata). Del kun fejlrapporter med personer og apps, du har tillid til."</string>
<string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Vis ikke igen"</string>
<string name="bugreport_storage_title" msgid="5332488144740527109">"Fejlrapporter"</string>
<string name="bugreport_unreadable_text" msgid="586517851044535486">"Fejlrapportfilen kunne ikke læses"</string>
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index 31cf530..45e0345 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -22,6 +22,9 @@
},
{
"exclude-annotation": "android.platform.test.annotations.Postsubmit"
+ },
+ {
+ "exclude-annotation": "android.platform.test.scenario.annotation.LargeScreenOnly"
}
]
},
@@ -94,6 +97,9 @@
},
{
"exclude-annotation": "android.platform.helpers.Staging"
+ },
+ {
+ "exclude-annotation": "android.platform.test.scenario.annotation.LargeScreenOnly"
}
]
}
@@ -110,6 +116,9 @@
},
{
"exclude-annotation": "org.junit.Ignore"
+ },
+ {
+ "exclude-annotation": "android.platform.test.scenario.annotation.LargeScreenOnly"
}
]
}
@@ -126,5 +135,24 @@
}
]
}
+ ],
+ "large-screen-postsubmit": [
+ {
+ "name": "PlatformScenarioTests",
+ "options" : [
+ {
+ "include-filter": "android.platform.test.scenario.sysui"
+ },
+ {
+ "include-annotation": "android.platform.test.scenario.annotation.LargeScreenOnly"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
]
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
index 883f4de..94fdbae 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
@@ -183,12 +183,6 @@
public boolean canBeDismissed();
/**
- * Informs the menu whether dismiss gestures are left-to-right or right-to-left.
- */
- default void setDismissRtl(boolean dismissRtl) {
- }
-
- /**
* Determines whether the menu should remain open given its current state, or snap closed.
* @return true if the menu should remain open, false otherwise.
*/
diff --git a/packages/SystemUI/res-keyguard/values-sw720dp/bools.xml b/packages/SystemUI/res-keyguard/values-sw720dp/bools.xml
new file mode 100644
index 0000000..e09bf7e
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/values-sw720dp/bools.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <bool name="can_use_one_handed_bouncer">true</bool>
+</resources>
diff --git a/packages/SystemUI/res-product/values-kk/strings.xml b/packages/SystemUI/res-product/values-kk/strings.xml
index d2aec4b..2629667 100644
--- a/packages/SystemUI/res-product/values-kk/strings.xml
+++ b/packages/SystemUI/res-product/values-kk/strings.xml
@@ -38,8 +38,8 @@
<string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Телефон құлпын ашуға <xliff:g id="NUMBER_0">%1$d</xliff:g> рет сәтсіз әрекет жасалды. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string>
<string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Планшет құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string>
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефон құлпын ашуға <xliff:g id="NUMBER">%d</xliff:g> рет сәтсіз әрекет жасалды. Жұмыс профилі өшіріліп, оның бүкіл деректері жойылады."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін планшетті есептік жазба арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін телефонды есептік жазба арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін планшетті аккаунт арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. <xliff:g id="NUMBER_1">%2$d</xliff:g> әрекет қалды. Одан кейін телефонды аккаунт арқылы ашу сұралады. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Басқа опцияларды көру үшін телефон құлпын ашыңыз."</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Басқа опцияларды көру үшін планшет құлпын ашыңыз."</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Басқа опцияларды көру үшін құрылғы құлпын ашыңыз."</string>
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index eb76382..850b017 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -30,7 +30,6 @@
android:id="@+id/status_icon_area"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:paddingEnd="@dimen/system_icons_keyguard_padding_end"
android:paddingTop="@dimen/status_bar_padding_top"
android:layout_alignParentEnd="true"
android:gravity="center_vertical|end" >
@@ -39,6 +38,7 @@
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginStart="@dimen/system_icons_super_container_margin_start"
+ android:layout_marginEnd="@dimen/status_bar_padding_end"
android:gravity="center_vertical|end">
<include layout="@layout/system_icons" />
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/udfps_view.xml b/packages/SystemUI/res/layout/udfps_view.xml
index 687830d..0fcbfa1 100644
--- a/packages/SystemUI/res/layout/udfps_view.xml
+++ b/packages/SystemUI/res/layout/udfps_view.xml
@@ -20,7 +20,7 @@
android:id="@+id/udfps_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- systemui:sensorTouchAreaCoefficient="0.75"
+ systemui:sensorTouchAreaCoefficient="1.0"
android:contentDescription="@string/accessibility_fingerprint_label">
<ViewStub
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 028f14a..85e2ee7 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Dit deblokkeer toegang vir alle programme en dienste wat toegelaat word om jou mikrofoon te gebruik."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dit deblokkeer toegang vir alle programme en dienste wat toegelaat word om jou kamera te gebruik."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dit deblokkeer toegang vir alle programme en dienste wat toegelaat word om jou kamera of mikrofoon te gebruik."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Toestel"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Ander toestel"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Wissel oorsig"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Gelaai"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Laai tans"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> wil die volgende teël by Kitsinstellings voeg"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Voeg teël by"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Moenie teël byvoeg nie"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Kies gebruiker"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 798e0c3..4a6110b 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ይህ የእርስዎን ማይክሮፎን እንዲጠቀሙ የተፈቀደላቸው የሁሉም መተግበሪያዎች እና አገልግሎቶች መዳረሻ እገዳን ያነሳል።"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ይህ ካሜራዎን እንዲጠቀሙ ለተፈቀደላቸው ሁሉም መተግበሪያዎች እና አገልግሎቶች መዳረሻን እገዳ ያነሳል።"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ይህ የእርስዎን ካሜራ ወይም ማይክሮፎን እንዲጠቀሙ የተፈቀደላቸው የሁሉም መተግበሪያዎች እና አገልግሎቶች መዳረሻ እገዳን ያነሳል።"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"መሣሪያ"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"ሌላ መሣሪያ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"አጠቃላይ እይታን ቀያይር"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ባትሪ ሞልቷል"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ኃይል በመሙላት ላይ"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"የተንቀሳቃሽ ስልክ ውሂብ"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"ተገናኝቷል"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"የተንቀሳቃሽ ስልክ ውሂብ በራስ-ሰር አይገናኝም"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"ግንኙነት የለም"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"ሌላ አውታረ መረብ የሉም"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"ምንም አውታረ መረቦች የሉም"</string>
@@ -1180,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> የሚከተለውን ሰቅ ወደ ፈጣን ቅንብሮች ማከል ይፈልጋል"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"ሰቅ አክል"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"ሰቅ አታክል"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ተጠቃሚን ይምረጡ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 6f5d73c..98ffae5 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -443,7 +443,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"يؤدي هذا الخيار إلى إزالة حظر الوصول بالنسبة إلى كل التطبيقات والخدمات المسموح لها باستخدام الميكروفون."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"يؤدي هذا الخيار إلى إزالة حظر الوصول بالنسبة إلى كل التطبيقات والخدمات المسموح لها باستخدام الكاميرا."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"يؤدي هذا الخيار إلى إزالة حظر الوصول بالنسبة إلى كل التطبيقات والخدمات المسموح لها باستخدام الكاميرا أو الميكروفون."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"الجهاز"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"جهاز آخر"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تبديل \"النظرة العامة\""</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"تم الشحن"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"جارٍ الشحن"</string>
@@ -1203,4 +1203,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"يريد تطبيق <xliff:g id="APPNAME">%1$s</xliff:g> إضافة المربّع التالي إلى \"الإعدادات السريعة\""</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"إضافة مربّع"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"عدم إضافة مربّع"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"اختيار المستخدم"</string>
</resources>
diff --git a/packages/SystemUI/res/values-as-land/strings.xml b/packages/SystemUI/res/values-as-land/strings.xml
index d5bf35a..6fa43cc 100644
--- a/packages/SystemUI/res/values-as-land/strings.xml
+++ b/packages/SystemUI/res/values-as-land/strings.xml
@@ -19,5 +19,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="toast_rotation_locked" msgid="4914046305911646988">"স্ক্ৰীণখন এতিয়া লেণ্ডস্কেপ স্ক্ৰীণৰ দিশত লক কৰা অৱস্থাত আছে"</string>
+ <string name="toast_rotation_locked" msgid="4914046305911646988">"স্ক্ৰীনখন এতিয়া লেণ্ডস্কে\'প স্ক্ৰীনৰ দিশত লক কৰা অৱস্থাত আছে"</string>
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 614e4d8..fbf1fb4 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -74,8 +74,8 @@
<string name="usb_port_enabled" msgid="531823867664717018">"চাৰ্জাৰ আৰু আনুষংগিক সামগ্ৰী চিনাক্ত কৰিবলৈ USB প’ৰ্ট সক্ষম কৰা হ’ল"</string>
<string name="usb_disable_contaminant_detection" msgid="3827082183595978641">"USB সক্ষম কৰক"</string>
<string name="learn_more" msgid="4690632085667273811">"অধিক জানক"</string>
- <string name="compat_mode_on" msgid="4963711187149440884">"স্ক্ৰীণ পূর্ণ কৰিবলৈ জুম কৰক"</string>
- <string name="compat_mode_off" msgid="7682459748279487945">"স্ক্ৰীণ পূর্ণ কৰিবলৈ প্ৰসাৰিত কৰক"</string>
+ <string name="compat_mode_on" msgid="4963711187149440884">"স্ক্ৰীন পূর্ণ কৰিবলৈ জুম কৰক"</string>
+ <string name="compat_mode_off" msgid="7682459748279487945">"স্ক্ৰীন পূর্ণ কৰিবলৈ প্ৰসাৰিত কৰক"</string>
<string name="global_action_screenshot" msgid="2760267567509131654">"স্ক্ৰীনশ্বট"</string>
<string name="global_action_smart_lock_disabled" msgid="9097102067802412936">"Smart Lock অক্ষম কৰা হৈছে"</string>
<string name="remote_input_image_insertion_text" msgid="4850791636452521123">"এখন প্ৰতিচ্ছবি পঠিয়াইছে"</string>
@@ -99,7 +99,7 @@
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"সোঁফালৰ সীমা <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"স্ক্ৰীন ৰেকৰ্ডাৰ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রীন ৰেকৰ্ডিঙৰ প্ৰক্ৰিয়াকৰণ হৈ আছে"</string>
- <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রীণ ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string>
+ <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রীন ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"ৰেকৰ্ড কৰা আৰম্ভ কৰিবনে?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"ৰেকৰ্ড কৰি থাকোঁতে, Android Systemএ আপোনাৰ স্ক্রীনত দৃশ্যমান হোৱা অথবা আপোনাৰ ডিভাইচত প্লে’ হৈ থকা যিকোনো সংবেনদশীল তথ্য কেপচাৰ কৰিব পাৰে। এইটোত পাছৱর্ড, পৰিশোধৰ তথ্য, ফট’, বার্তাসমূহ আৰু অডিঅ’ অন্তর্ভুক্ত হয়।"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"অডিঅ’ ৰেকৰ্ড কৰক"</string>
@@ -117,10 +117,10 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"ৰখোৱাৰ পৰা পুনৰ আৰম্ভ কৰক"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"বাতিল কৰক"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"শ্বেয়াৰ কৰক"</string>
- <string name="screenrecord_cancel_success" msgid="1775448688137393901">"স্ক্রীণ ৰেকৰ্ড কৰাটো বাতিল কৰা হ’ল"</string>
+ <string name="screenrecord_cancel_success" msgid="1775448688137393901">"স্ক্রীন ৰেকৰ্ড কৰাটো বাতিল কৰা হ’ল"</string>
<string name="screenrecord_save_title" msgid="1886652605520893850">"স্ক্ৰীন ৰেকৰ্ডিং ছেভ কৰা হ’ল"</string>
<string name="screenrecord_save_text" msgid="3008973099800840163">"চাবলৈ টিপক"</string>
- <string name="screenrecord_delete_error" msgid="2870506119743013588">"স্ক্রীণ ৰেকৰ্ডিং মচি থাকোঁতে কিবা আসোঁৱাহ হ’ল"</string>
+ <string name="screenrecord_delete_error" msgid="2870506119743013588">"স্ক্রীন ৰেকৰ্ডিং মচি থাকোঁতে কিবা আসোঁৱাহ হ’ল"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"অনুমতি পাব পৰা নগ\'ল"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"স্ক্রীন ৰেকৰ্ড কৰা আৰম্ভ কৰোঁতে আসোঁৱাহ হৈছে"</string>
<string name="usb_preference_title" msgid="1439924437558480718">"ইউএছবিৰে ফাইল স্থানান্তৰণৰ বিকল্পসমূহ"</string>
@@ -131,7 +131,7 @@
<string name="accessibility_home" msgid="5430449841237966217">"গৃহ পৃষ্ঠাৰ বুটাম"</string>
<string name="accessibility_menu" msgid="2701163794470513040">"মেনু"</string>
<string name="accessibility_accessibility_button" msgid="4089042473497107709">"দিব্যাংগসকলৰ বাবে থকা সুবিধাসমূহ"</string>
- <string name="accessibility_rotate_button" msgid="1238584767612362586">"স্ক্ৰীণ ঘূৰাওক"</string>
+ <string name="accessibility_rotate_button" msgid="1238584767612362586">"স্ক্ৰীন ঘূৰাওক"</string>
<string name="accessibility_recent" msgid="901641734769533575">"অৱলোকন"</string>
<string name="accessibility_search_light" msgid="524741790416076988">"সন্ধান কৰক"</string>
<string name="accessibility_camera_button" msgid="2938898391716647247">"কেমেৰা"</string>
@@ -190,7 +190,7 @@
<string name="face_dialog_looking_for_face" msgid="2656848512116189509">"আপোনাৰ মুখমণ্ডল বিচাৰি আছে…"</string>
<string name="accessibility_face_dialog_face_icon" msgid="8335095612223716768">"মুখমণ্ডলৰ আইকন"</string>
<string name="accessibility_compatibility_zoom_button" msgid="5845799798708790509">"উপযোগিতা অনুসৰি জুম কৰা বুটাম।"</string>
- <string name="accessibility_compatibility_zoom_example" msgid="2617218726091234073">"স্ক্ৰীণৰ আকাৰ ডাঙৰ কৰিবলৈ জুম কৰক।"</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="2617218726091234073">"স্ক্ৰীনৰ আকাৰ ডাঙৰ কৰিবলৈ জুম কৰক।"</string>
<string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ব্লুটুথ সংযোগ হ’ল।"</string>
<string name="accessibility_bluetooth_disconnected" msgid="7195823280221275929">"ব্লুটুথ সংযোগ বিচ্ছিন্ন কৰা হ’ল।"</string>
<string name="accessibility_no_battery" msgid="3789287732041910804">"বেটাৰি শেষ"</string>
@@ -249,10 +249,10 @@
<string name="accessibility_notification_dismissed" msgid="4411652015138892952">"জাননী অগ্ৰাহ্য কৰা হৈছে।"</string>
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"জাননী পেনেল।"</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ক্ষিপ্ৰ ছেটিংসমূহ।"</string>
- <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"বন্ধ স্ক্ৰীণ।"</string>
+ <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"বন্ধ স্ক্ৰীন।"</string>
<string name="accessibility_desc_settings" msgid="6728577365389151969">"ছেটিংসমূহ"</string>
<string name="accessibility_desc_recent_apps" msgid="1748675199348914194">"অৱলোকন।"</string>
- <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কৰ্মস্থানৰ প্ৰ\'ফাইলৰ লক স্ক্ৰীণ"</string>
+ <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কৰ্মস্থানৰ প্ৰ\'ফাইলৰ লক স্ক্ৰীন"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ কৰক"</string>
<string name="accessibility_quick_settings_wifi" msgid="167707325133803052">"<xliff:g id="SIGNAL">%1$s</xliff:g>."</string>
<string name="accessibility_quick_settings_wifi_changed_off" msgid="2230487165558877262">"ৱাই-ফাই অফ কৰা হ’ল।"</string>
@@ -292,7 +292,7 @@
<string name="accessibility_quick_settings_color_inversion_changed_on" msgid="4711141858364404084">"ৰং বিপৰীতকৰণ অন কৰা হ’ল।"</string>
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="7002061268910095176">"ম’বাইল হটস্পট অফ কৰা হ’ল।"</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2576895346762408840">"ম’বাইল হটস্পট অন কৰা হ’ল।"</string>
- <string name="accessibility_casting_turned_off" msgid="1387906158563374962">"স্ক্ৰীণ কাষ্টিং বন্ধ কৰা হ’ল।"</string>
+ <string name="accessibility_casting_turned_off" msgid="1387906158563374962">"স্ক্ৰীন কাষ্টিং বন্ধ কৰা হ’ল।"</string>
<string name="accessibility_quick_settings_work_mode_changed_off" msgid="6422896967647049692">"কৰ্মস্থান ম’ড পজ হৈ আছে।"</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="1105258550138313384">"কৰ্মস্থান ম\'ড অন কৰা হ’ল।"</string>
<string name="accessibility_quick_settings_data_saver_changed_off" msgid="4910847127871603832">"ডেটা সঞ্চয়কাৰী সুবিধা অফ কৰা হ’ল।"</string>
@@ -320,14 +320,14 @@
<string name="notification_summary_message_format" msgid="5158219088501909966">"<xliff:g id="CONTACT_NAME">%1$s</xliff:g>: <xliff:g id="MESSAGE_CONTENT">%2$s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="6818779631806163080">"জাননীৰ ছেটিংসমূহ"</string>
<string name="status_bar_notification_app_settings_title" msgid="5050006438806013903">"<xliff:g id="APP_NAME">%s</xliff:g> ছেটিংসমূহ"</string>
- <string name="accessibility_rotation_lock_off" msgid="3880436123632448930">"আপোনাৰ ফ\'নৰ স্ক্ৰীণ স্বয়ংক্ৰিয়ভাৱে ঘূৰিব৷"</string>
- <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"স্ক্ৰীণ লেণ্ডস্কেপ দিশত লক কৰা হ’ল।"</string>
- <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"স্ক্ৰীণ প\'ৰ্ট্ৰেইট দিশত লক কৰা হ’ল।"</string>
- <string name="accessibility_rotation_lock_off_changed" msgid="5772498370935088261">"আপোনাৰ ফ\'নৰ স্ক্ৰীণ এতিয়া স্বয়ংক্ৰিয়ভাৱে ঘূৰিব৷"</string>
- <string name="accessibility_rotation_lock_on_landscape_changed" msgid="5785739044300729592">"স্ক্ৰীণখন এতিয়া লেণ্ডস্কেইপ দিশত লক কৰা অৱস্থাত আছে।"</string>
- <string name="accessibility_rotation_lock_on_portrait_changed" msgid="5580170829728987989">"স্ক্ৰীণখন এতিয়া প\'ৰ্ট্ৰেইট দিশত লক কৰা অৱস্থাত আছে।"</string>
+ <string name="accessibility_rotation_lock_off" msgid="3880436123632448930">"আপোনাৰ ফ\'নৰ স্ক্ৰীন স্বয়ংক্ৰিয়ভাৱে ঘূৰিব।"</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"স্ক্ৰীন লেণ্ডস্কে\'প দিশত লক কৰা হ’ল।"</string>
+ <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"স্ক্ৰীন প\'ৰ্ট্ৰেইট দিশত লক কৰা হ’ল।"</string>
+ <string name="accessibility_rotation_lock_off_changed" msgid="5772498370935088261">"আপোনাৰ ফ\'নৰ স্ক্ৰীন এতিয়া স্বয়ংক্ৰিয়ভাৱে ঘূৰিব৷"</string>
+ <string name="accessibility_rotation_lock_on_landscape_changed" msgid="5785739044300729592">"স্ক্ৰীনখন এতিয়া লেণ্ডস্কে\'প স্ক্ৰীনৰ দিশত লক কৰা অৱস্থাত আছে"</string>
+ <string name="accessibility_rotation_lock_on_portrait_changed" msgid="5580170829728987989">"স্ক্ৰীনখন এতিয়া প\'ৰ্ট্ৰেইট দিশত লক কৰা অৱস্থাত আছে।"</string>
<string name="dessert_case" msgid="9104973640704357717">"মিষ্টান্ন ভাণ্ডাৰ"</string>
- <string name="start_dreams" msgid="9131802557946276718">"স্ক্ৰীণ ছেভাৰ"</string>
+ <string name="start_dreams" msgid="9131802557946276718">"স্ক্ৰীন ছেভাৰ"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ইথাৰনেট"</string>
<string name="quick_settings_header_onboarding_text" msgid="1918085351115504765">"অধিক বিকল্পৰ বাবে আইকনসমূহ স্পৰ্শ কৰি হেঁচি ধৰক"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"অসুবিধা নিদিব"</string>
@@ -376,7 +376,7 @@
<string name="quick_settings_wifi_on_label" msgid="2489928193654318511">"ৱাই-ফাই অন হৈ আছে"</string>
<string name="quick_settings_wifi_detail_empty_text" msgid="483130889414601732">"কোনো ৱাই-ফাই নেটৱৰ্ক নাই"</string>
<string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"অন কৰি থকা হৈছে…"</string>
- <string name="quick_settings_cast_title" msgid="2279220930629235211">"স্ক্ৰীণ কাষ্ট"</string>
+ <string name="quick_settings_cast_title" msgid="2279220930629235211">"স্ক্ৰীন কাষ্ট"</string>
<string name="quick_settings_casting" msgid="1435880708719268055">"কাষ্টিং"</string>
<string name="quick_settings_cast_device_default_name" msgid="6988469571141331700">"নাম নথকা ডিভাইচ"</string>
<string name="quick_settings_cast_device_default_description" msgid="2580520859212250265">"কাষ্টৰ বাবে সাজু"</string>
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"এইটোৱে আপোনাৰ মাইক্ৰ\'ফ\'ন ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়া আটাইবোৰ এপ্ আৰু সেৱাৰ বাবে এক্সেছ অৱৰোধৰ পৰা আঁতৰায়।"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"এইটোৱে আপোনাৰ কেমেৰা ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়া আটাইবোৰ এপ্ আৰু সেৱাৰ বাবে এক্সেছ অৱৰোধৰ পৰা আঁতৰায়।"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"এইটোৱে আপোনাৰ কেমেৰা অথবা মাইক্ৰ\'ফ\'ন ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়া আটাইবোৰ এপ্ আৰু সেৱাৰ বাবে এক্সেছ অৱৰোধৰ পৰা আঁতৰায়।"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"ডিভাইচ"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"অন্য ডিভাইচ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"অৱলোকন ট’গল কৰক"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"চ্চার্জ হ’ল"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"চ্চার্জ হৈ আছে"</string>
@@ -464,7 +464,7 @@
<string name="phone_hint" msgid="6682125338461375925">"ফ\'নৰ বাবে আইকনৰপৰা ছোৱাইপ কৰক"</string>
<string name="voice_hint" msgid="7476017460191291417">"কণ্ঠধ্বনিৰে সহায়ৰ বাবে আইকনৰ পৰা ছোৱাইপ কৰক"</string>
<string name="camera_hint" msgid="4519495795000658637">"কেমেৰা খুলিবলৈ আইকনৰপৰা ছোৱাইপ কৰক"</string>
- <string name="interruption_level_none_with_warning" msgid="8394434073508145437">"সম্পূর্ণ নিৰৱতা। এই কার্যই স্ক্ৰীণ ৰীডাৰসমূহকো নিৰৱ কৰিব।"</string>
+ <string name="interruption_level_none_with_warning" msgid="8394434073508145437">"সম্পূর্ণ নীৰৱতা। এই কার্যই স্ক্ৰীন ৰীডাৰসমূহকো নীৰৱ কৰিব।"</string>
<string name="interruption_level_none" msgid="219484038314193379">"সম্পূর্ণ নিৰৱতা"</string>
<string name="interruption_level_priority" msgid="661294280016622209">"কেৱল গুৰুত্বপূৰ্ণ"</string>
<string name="interruption_level_alarms" msgid="2457850481335846959">"কেৱল এলাৰ্মসমূহ"</string>
@@ -710,7 +710,7 @@
<string name="tuner_full_importance_settings" msgid="1388025816553459059">"জাননী নিয়ন্ত্ৰণৰ অধিক কৰ্তৃত্ব"</string>
<string name="tuner_full_importance_settings_on" msgid="917981436602311547">"অন"</string>
<string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"অফ"</string>
- <string name="power_notification_controls_description" msgid="1334963837572708952">"জাননী নিয়ন্ত্ৰণৰ অধিক কৰ্তৃত্বৰ সৈতে আপুনি এটা এপৰ জাননীৰ গুৰুত্বৰ স্তৰ ০ৰ পৰা ৫লৈ ছেট কৰিব পাৰে।\n\n"<b>"স্তৰ ৫"</b>" \n- জাননী তালিকাৰ একেবাৰে ওপৰত দেখুৱাওক \n- সম্পূৰ্ণ স্ক্ৰীণত থাকোঁতে ব্যাঘাত জন্মাবলৈ অনুমতি দিয়ক\n- সদায় ভুমুকি মাৰিবলৈ দিয়ক\n\n"<b>"স্তৰ ৪"</b>" \n- সম্পূৰ্ণ স্ক্ৰীণত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- সদায় ভুমুকি মাৰিবলৈ দিয়ক\n\n"<b>"স্তৰ ৩"</b>" \n- সম্পূৰ্ণ স্ক্ৰীণত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n\n"<b>"স্তৰ ২"</b>" \n- সম্পূর্ণ স্ক্ৰীণত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব \n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n- কেতিয়াও শব্দ আৰু কম্পন কৰিবলৈ নিদিব\n\n"<b>" স্তৰ ১"</b>" \n- সম্পূৰ্ণ স্ক্ৰীণত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n-কেতিয়াও শব্দ আৰু কম্পন কৰিবলৈ নিদিব \n- লক স্ক্ৰীণ আৰু স্থিতি দণ্ডৰ পৰা লুকুৱাই ৰাখক \n- জাননী তালিকাৰ একেবাৰে তলত দেখুৱাওক\n\n"<b>"স্তৰ ০"</b>" \n- এই এপৰ সকলো জাননী অৱৰোধ কৰক"</string>
+ <string name="power_notification_controls_description" msgid="1334963837572708952">"জাননী নিয়ন্ত্ৰণৰ অধিক কৰ্তৃত্বৰ সৈতে আপুনি এটা এপৰ জাননীৰ গুৰুত্বৰ স্তৰ ০ৰ পৰা ৫লৈ ছেট কৰিব পাৰে।\n\n"<b>"স্তৰ ৫"</b>" \n- জাননী তালিকাৰ একেবাৰে ওপৰত দেখুৱাওক \n- সম্পূৰ্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ অনুমতি দিয়ক\n- সদায় ভুমুকি মাৰিবলৈ দিয়ক\n\n"<b>"স্তৰ ৪"</b>" \n- সম্পূৰ্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- সদায় ভুমুকি মাৰিবলৈ দিয়ক\n\n"<b>"স্তৰ ৩"</b>" \n- সম্পূৰ্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n\n"<b>"স্তৰ ২"</b>" \n- সম্পূর্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব \n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n- কেতিয়াও শব্দ আৰু কম্পন কৰিবলৈ নিদিব\n\n"<b>" স্তৰ ১"</b>" \n- সম্পূৰ্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n-কেতিয়াও শব্দ আৰু কম্পন কৰিবলৈ নিদিব \n- লক স্ক্ৰীন আৰু স্থিতি দণ্ডৰ পৰা লুকুৱাই ৰাখক \n- জাননী তালিকাৰ একেবাৰে তলত দেখুৱাওক\n\n"<b>"স্তৰ ০"</b>" \n- এই এপৰ আটাইবোৰ জাননী অৱৰোধ কৰক"</string>
<string name="notification_header_default_channel" msgid="225454696914642444">"জাননীসমূহ"</string>
<string name="notification_channel_disabled" msgid="928065923928416337">"আপোনাক এই জাননীসমূহ আৰু দেখুওৱা নহ’ব"</string>
<string name="notification_channel_minimized" msgid="6892672757877552959">"এই জাননীসমূহ মিনিমাইজ কৰি থোৱা হ\'ব"</string>
@@ -758,11 +758,11 @@
<string name="see_more_title" msgid="7409317011708185729">"অধিক চাওক"</string>
<string name="appops_camera" msgid="5215967620896725715">"এই এপে কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string>
<string name="appops_microphone" msgid="8805468338613070149">"এই এপে মাইক্ৰ\'ফ\'ন ব্য়ৱহাৰ কৰি আছে।"</string>
- <string name="appops_overlay" msgid="4822261562576558490">"এই এপটো আপোনাৰ স্ক্ৰীণত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ আছে।"</string>
+ <string name="appops_overlay" msgid="4822261562576558490">"এই এপটো আপোনাৰ স্ক্ৰীনত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ আছে।"</string>
<string name="appops_camera_mic" msgid="7032239823944420431">"এই এপে মাইক্ৰ\'ন আৰু কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string>
- <string name="appops_camera_overlay" msgid="6466845606058816484">"এই এপে আপোনাৰ স্ক্ৰীণত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string>
- <string name="appops_mic_overlay" msgid="4609326508944233061">"এই এপে আপোনাৰ স্ক্ৰীণত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ মাইক্ৰ\'ফ\'ন ব্য়ৱহাৰ কৰি আছে।"</string>
- <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"এই এপে আপোনাৰ স্ক্ৰীণত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ মাইক্ৰ\'ফ\'ন আৰু কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string>
+ <string name="appops_camera_overlay" msgid="6466845606058816484">"এই এপে আপোনাৰ স্ক্ৰীনত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string>
+ <string name="appops_mic_overlay" msgid="4609326508944233061">"এই এপে আপোনাৰ স্ক্ৰীনত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ মাইক্ৰ\'ফ\'ন ব্য়ৱহাৰ কৰি আছে।"</string>
+ <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"এই এপে আপোনাৰ স্ক্ৰীনত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ মাইক্ৰ\'ফ\'ন আৰু কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"ছেটিংসমূহ"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ঠিক আছে"</string>
<string name="feedback_alerted" msgid="5192459808484271208">"ছিষ্টেমটোৱে স্বয়ংক্ৰিয়ভাৱে এই জাননীটোৰ ক্ষেত্ৰত দিয়া <b>গুৰুত্ব ডিফ’ল্ট</b>লৈ বৃদ্ধি কৰিছে।"</string>
@@ -935,7 +935,7 @@
<string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"ছেটিংসমূহৰ ক্ৰম সম্পাদনা কৰক।"</string>
<string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"পাৱাৰ মেনু"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>ৰ পৃষ্ঠা <xliff:g id="ID_1">%1$d</xliff:g>"</string>
- <string name="tuner_lock_screen" msgid="2267383813241144544">"লক স্ক্ৰীণ"</string>
+ <string name="tuner_lock_screen" msgid="2267383813241144544">"লক স্ক্ৰীন"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"আপোনাৰ ফ\'নটো গৰম হোৱাৰ কাৰণে অফ কৰা হৈছিল"</string>
<string name="thermal_shutdown_message" msgid="6142269839066172984">"আপোনাৰ ফ’নটো এতিয়া স্বাভাৱিকভাৱে চলি আছে।\nঅধিক তথ্যৰ বাবে টিপক"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"আপোনাৰ ফ\'নটো অত্যধিক গৰম হোৱাৰ বাবে ইয়াক ঠাণ্ডা কৰিবলৈ অফ কৰা হৈছিল। আপোনাৰ ফ\'নটো এতিয়া স্বাভাৱিকভাৱে চলি আছে।\n\nআপোনাৰ ফ\'নটো গৰম হ\'ব পাৰে, যদিহে আপুনি:\n • ফ\'নটোৰ হাৰ্ডৱেৰ অত্যধিক মাত্ৰাত ব্যৱহাৰ কৰা এপসমূহ চলালে (যেনে, ভিডিঅ\' গেইম, ভিডিঅ\', দিক্-নিৰ্দেশনা এপসমূহ)\n • খুউব ডাঙৰ আকাৰৰ ফাইল আপল\'ড বা ডাউনল’ড কৰিলে\n • আপোনাৰ ফ\'নটো উচ্চ তাপমাত্ৰাৰ পৰিৱেশত ব্যৱহাৰ কৰিলে"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"ম’বাইল ডেটা"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"সংযোজিত হৈ আছে"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"ম’বাইল ডেটা স্বয়ংক্ৰিয়ভাৱে সংযুক্ত নহ’ব"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"সংযোগ নাই"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"অন্য কোনো নেটৱৰ্ক উপলব্ধ নহয়"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"কোনো নেটৱৰ্ক উপলব্ধ নহয়"</string>
@@ -1180,4 +1179,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g>এ ক্ষিপ্ৰ ছেটিঙত এই টাইলটো যোগ দিব বিচাৰিছে"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"টাইল যোগ দিয়ক"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"টাইল যোগ নিদিব"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 7cd3b32..44e6474 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Kamera və mikrofon istifadə edən bütün tətbiq və xidmətlərə giriş verir."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kamera və mikrofon istifadə edən bütün tətbiq və xidmətlərə giriş verir."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kamera və mikrofon istifadə edən bütün tətbiq və xidmətlərə giriş verir."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Cihaz"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Digər cihaz"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"İcmala Keçin"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Enerji yığılıb"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Enerji doldurulur"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> aşağıdakı mozaiki Sürətli Ayarlara əlavə etmək istəyir"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Mozaik əlavə edin"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Mozaik əlavə etməyin"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"İstifadəçi seçin"</string>
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index f155b76..b40f48d 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -437,7 +437,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Ovim će se odblokirati pristup za sve aplikacije i usluge koje imaju dozvolu za korišćenje mikrofona."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ovim će se odblokirati pristup za sve aplikacije i usluge koje imaju dozvolu za korišćenje kamere."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ovim će se odblokirati pristup za sve aplikacije i usluge koje imaju dozvolu za korišćenje kamere ili mikrofona."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Drugi uređaj"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Uključi/isključi pregled"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Napunjena je"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Puni se"</string>
@@ -1185,4 +1185,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> želi da doda sledeću pločicu u Brza podešavanja"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Dodaj pločicu"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Ne dodaj pločicu"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Izaberite korisnika"</string>
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index ab3940b..29f46ba 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -439,7 +439,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Доступ адкрыецца для ўсіх праграм і сэрвісаў, якім дазволена выкарыстоўваць мікрафон."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Доступ адкрыецца для ўсіх праграм і сэрвісаў, якім дазволена выкарыстоўваць камеру."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Доступ адкрыецца для ўсіх праграм і сэрвісаў, якім дазволена выкарыстоўваць камеру ці мікрафон."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Прылада"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Іншая прылада"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Уключыць/выключыць агляд"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Зараджаны"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарадка"</string>
@@ -1191,4 +1191,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> запытвае дазвол на дадаванне ў Хуткія налады наступнай пліткі"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Дадаць плітку"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Не дадаваць плітку"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Выбар карыстальніка"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 2d698ee..43f4bd7 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Това действие отблокира достъпа за всички приложения и услуги, които имат разрешение да използват микрофона ви."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Това действие отблокира достъпа за всички приложения и услуги, които имат разрешение да използват камерата ви."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Това действие отблокира достъпа за всички приложения и услуги, които имат разрешение да използват камерата или микрофона ви."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Устройство"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Друго устройство"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Превключване на общия преглед"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Заредена"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарежда се"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> иска да добави следния панел към бързите настройки"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Добавяне на панел"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Отмяна на добавянето"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Избор на потребител"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 46172bd..05cbfc0 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"এটার জন্য মাইক্রোফোনের অ্যাক্সেস সেই সব অ্যাপ এবং পরিষেবার জন্য আনব্লক হয়ে যাবে, যাতে আপনার মাইক্রোফোন ব্যবহার করার অনুমতি দেওয়া হয়েছে।"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"এটার জন্য ক্যামেরার অ্যাক্সেস সেই সব অ্যাপ এবং পরিষেবার জন্য আনব্লক হয়ে যাবে, যাতে আপনার ক্যামেরা ব্যবহারের অনুমতি দেওয়া হয়েছে।"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"এটার জন্য ক্যামেরা অথবা মাইক্রোফোনের অ্যাক্সেস সেই সব অ্যাপ এবং পরিষেবার জন্য আনব্লক হয়ে যাবে, যাতে আপনার ক্যামেরা অথবা মাইক্রোফোন ব্যবহারের অনুমতি দেওয়া হয়েছে।"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"ডিভাইস"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"অন্য ডিভাইস"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"\'এক নজরে\' বৈশিষ্ট্যটি চালু বা বন্ধ করুন"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"চার্জ হয়েছে"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"চার্জ হচ্ছে"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"মোবাইল ডেটা"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"কানেক্ট করা আছে"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"মোবাইল ডেটা নিজে থেকে কানেক্ট হবে না"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"কানেকশন নেই"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"অন্য কোনও নেটওয়ার্ক উপলভ্য নেই"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"কোনও নেটওয়ার্ক উপলভ্য নেই"</string>
@@ -1180,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> নিম্নলিখিত টাইল দ্রুত সেটিংস মেনুতে যোগ করতে চায়"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"টাইল যোগ করুন"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"টাইল যোগ করবেন না"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ব্যবহারকারী বেছে নিন"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index d6a6602..81b0274 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -437,7 +437,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Ovim se deblokira pristup za sve aplikacije i usluge kojima je dozvoljeno da koriste vaš mikrofon."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ovim se deblokira pristup za sve aplikacije i usluge kojima je dozvoljeno da koriste vašu kameru."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ovim se deblokira pristup za sve aplikacije i usluge kojima je dozvoljeno da koriste vašu kameru ili mikrofon."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Drugi uređaj"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Pregled uključivanja/isključivanja"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Napunjeno"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Punjenje"</string>
@@ -1185,4 +1185,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> želi dodati sljedeću karticu u Brze postavke"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Dodaj karticu"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Nemoj dodati karticu"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Odaberite korisnika"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index ea91dc1..59fef13 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Aquesta opció desbloqueja l\'accés de tots els serveis i aplicacions que tenen permís per utilitzar el micròfon."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Aquesta opció desbloqueja l\'accés de tots els serveis i aplicacions que tenen permís per utilitzar la càmera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Aquesta opció desbloqueja l\'accés de tots els serveis i aplicacions que tenen permís per utilitzar la càmera o el micròfon."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositiu"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Un altre dispositiu"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activa o desactiva Aplicacions recents"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregada"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"S\'està carregant"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> vol afegir la icona següent a la configuració ràpida"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Afegeix la icona"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"No afegeixis la icona"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Selecciona un usuari"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index c9021f8..b04559a 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -439,7 +439,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Tímto odblokujete přístup všem aplikacím a službám, které mají povoleno používat váš mikrofon."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tímto odblokujete přístup všem aplikacím a službám, které mají povoleno používat váš fotoaparát."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tímto odblokujete přístup všem aplikacím a službám, které mají povoleno používat váš fotoaparát či mikrofon."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Zařízení"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Další zařízení"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Přepnout přehled"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Nabito"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Nabíjení"</string>
@@ -1191,4 +1191,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"Aplikace <xliff:g id="APPNAME">%1$s</xliff:g> chce do Rychlého nastavení přidat následující dlaždici"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Přidat dlaždici"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Nepřidávat dlaždici"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Zvolte uživatele"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index c7214ff..afe693a 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -275,10 +275,10 @@
<string name="accessibility_quick_settings_bluetooth_connected" msgid="5237625393869747261">"Der er oprettet forbindelse til Bluetooth."</string>
<string name="accessibility_quick_settings_bluetooth_changed_off" msgid="3344226652293797283">"Bluetooth er slået fra."</string>
<string name="accessibility_quick_settings_bluetooth_changed_on" msgid="1263282011749437549">"Bluetooth er slået til."</string>
- <string name="accessibility_quick_settings_location_off" msgid="6122523378294740598">"Placeringsrapportering er slået fra."</string>
- <string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"Placeringsrapportering er slået til."</string>
- <string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"Placeringsrapportering er slået fra."</string>
- <string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"Placeringsrapportering er slået til."</string>
+ <string name="accessibility_quick_settings_location_off" msgid="6122523378294740598">"Lokationsrapportering er slået fra."</string>
+ <string name="accessibility_quick_settings_location_on" msgid="6869947200325467243">"Lokationsrapportering er slået til."</string>
+ <string name="accessibility_quick_settings_location_changed_off" msgid="5132776369388699133">"Lokationsrapportering er slået fra."</string>
+ <string name="accessibility_quick_settings_location_changed_on" msgid="7159115433070112154">"Lokationsrapportering er slået til."</string>
<string name="accessibility_quick_settings_alarm" msgid="558094529584082090">"Alarmen er indstillet til <xliff:g id="TIME">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_close" msgid="2974895537860082341">"Luk panelet."</string>
<string name="accessibility_quick_settings_more_time" msgid="7646479831704665284">"Mere tid."</string>
@@ -309,7 +309,7 @@
<string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"Genoptag"</string>
<string name="gps_notification_searching_text" msgid="231304732649348313">"Søger efter GPS"</string>
<string name="gps_notification_found_text" msgid="3145873880174658526">"Placeringen er angivet ved hjælp af GPS"</string>
- <string name="accessibility_location_active" msgid="2845747916764660369">"Aktive placeringsanmodninger"</string>
+ <string name="accessibility_location_active" msgid="2845747916764660369">"Aktive lokationsanmodninger"</string>
<string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensorer er slået fra"</string>
<string name="accessibility_clear_all" msgid="970525598287244592">"Ryd alle notifikationer."</string>
<string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> mere"</string>
@@ -352,8 +352,8 @@
<string name="quick_settings_rotation_locked_portrait_label" msgid="1194988975270484482">"Stående"</string>
<string name="quick_settings_rotation_locked_landscape_label" msgid="2000295772687238645">"Liggende"</string>
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Inputmetode"</string>
- <string name="quick_settings_location_label" msgid="2621868789013389163">"Placering"</string>
- <string name="quick_settings_location_off_label" msgid="7923929131443915919">"Placering fra"</string>
+ <string name="quick_settings_location_label" msgid="2621868789013389163">"Lokation"</string>
+ <string name="quick_settings_location_off_label" msgid="7923929131443915919">"Lokation fra"</string>
<string name="quick_settings_camera_label" msgid="5612076679385269339">"Kameraadgang"</string>
<string name="quick_settings_mic_label" msgid="8392773746295266375">"Mikrofonadgang"</string>
<string name="quick_settings_camera_mic_available" msgid="1453719768420394314">"Tilgængelig"</string>
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Dette fjerner adgangsblokeringen for alle apps og tjenester, der har tilladelse til at bruge din mikrofon."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dette fjerner adgangsblokeringen for alle apps og tjenester, der har tilladelse til at bruge dit kamera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dette fjerner adgangsblokeringen for alle apps og tjenester, der har tilladelse til at bruge dit kamera eller din mikrofon."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Enhed"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Anden enhed"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Slå Oversigt til/fra"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Opladet"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Oplader"</string>
@@ -555,9 +555,9 @@
<string name="disconnect_vpn" msgid="26286850045344557">"Afbryd VPN-forbindelse"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Se politikker"</string>
<string name="monitoring_button_view_controls" msgid="8316440345340701117">"Se indstillinger"</string>
- <string name="monitoring_description_named_management" msgid="505833016545056036">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nDin it-administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er tilknyttet din enhed, og din enheds placeringsdata.\n\nKontakt din it-administrator for at få mere at vide."</string>
+ <string name="monitoring_description_named_management" msgid="505833016545056036">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nDin it-administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er tilknyttet din enhed, og din enheds lokationsdata.\n\nKontakt din it-administrator for at få mere at vide."</string>
<string name="monitoring_financed_description_named_management" msgid="6108439201399938668">"<xliff:g id="ORGANIZATION_NAME_0">%1$s</xliff:g> kan muligvis administrere apps, få adgang til data, der er tilknyttet denne enhed, og ændre enhedens indstillinger.\n\nKontakt <xliff:g id="ORGANIZATION_NAME_1">%2$s</xliff:g>, hvis du har spørgsmål."</string>
- <string name="monitoring_description_management" msgid="4308879039175729014">"Denne enhed tilhører din organisation.\n\nDin it-administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er tilknyttet din enhed, og din enheds placeringsdata.\n\nKontakt din it-administrator for at få mere at vide."</string>
+ <string name="monitoring_description_management" msgid="4308879039175729014">"Denne enhed tilhører din organisation.\n\nDin it-administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er tilknyttet din enhed, og din enheds lokationsdata.\n\nKontakt din it-administrator for at få mere at vide."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Din organisation har installeret et nøglecenter på denne enhed. Din sikre netværkstrafik kan overvåges eller ændres."</string>
<string name="monitoring_description_managed_profile_ca_certificate" msgid="7904323416598435647">"Din organisation har installeret et nøglecenter på din arbejdsprofil. Din sikre netværkstrafik kan overvåges eller ændres."</string>
<string name="monitoring_description_ca_certificate" msgid="448923057059097497">"Der er installeret et nøglecenter på denne enhed. Din sikre netværkstrafik kan overvåges eller ændres."</string>
@@ -569,7 +569,7 @@
<string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"Din personlige profil har forbindelse til <xliff:g id="VPN_APP">%1$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. mails, apps og websites."</string>
<string name="monitoring_description_do_header_generic" msgid="6130190408164834986">"Din enhed administreres af <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string>
<string name="monitoring_description_do_header_with_name" msgid="2696255132542779511">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> bruger <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> til at administrere din enhed."</string>
- <string name="monitoring_description_do_body" msgid="7700878065625769970">"Din administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps og data, der er knyttet til denne enhed, samt enhedens placeringsoplysninger."</string>
+ <string name="monitoring_description_do_body" msgid="7700878065625769970">"Din administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps og data, der er knyttet til denne enhed, samt enhedens lokationsoplysninger."</string>
<string name="monitoring_description_do_learn_more_separator" msgid="1467280496376492558">" "</string>
<string name="monitoring_description_do_learn_more" msgid="645149183455573790">"Få flere oplysninger"</string>
<string name="monitoring_description_do_body_vpn" msgid="7699280130070502303">"Du har forbindelse til <xliff:g id="VPN_APP">%1$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. e-mails, apps og websites."</string>
@@ -580,7 +580,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Din administrator har aktiveret netværksregistrering, som overvåger trafik på din enhed.\n\nKontakt din administrator for at få flere oplysninger."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Du gav en app tilladelse til at konfigurere en VPN-forbindelse.\n\nDenne app kan overvåge din enhed og netværksaktivitet, bl.a. e-mails, apps og websites."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Din arbejdsprofil administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nDin administrator kan overvåge din netværksaktivitet, bl.a. e-mails, apps og websites.\n\nKontakt din administrator for at få flere oplysninger.\n\nDu har også forbindelse til et VPN, som kan overvåge din netværksaktivitet."</string>
- <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Denne enhed administreres af din forælder. Din forælder kan se og administrere oplysninger såsom de apps, du bruger, din placering og din skærmtid."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Denne enhed administreres af din forælder. Din forælder kan se og administrere oplysninger såsom de apps, du bruger, din lokation og din skærmtid."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Du har forbindelse til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. mails, apps og websites."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Du har forbindelse til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåge din private netværksaktivitet, bl.a. e-mails, apps og websites."</string>
@@ -916,8 +916,8 @@
<string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Flyt felt"</string>
<string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"Tilføj felt"</string>
<string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Flyt til <xliff:g id="POSITION">%1$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Føj til placering <xliff:g id="POSITION">%1$d</xliff:g>"</string>
- <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Placering <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Føj til lokation <xliff:g id="POSITION">%1$d</xliff:g>"</string>
+ <string name="accessibility_qs_edit_position" msgid="4509277359815711830">"Lokation <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_qs_edit_tile_added" msgid="9067146040380836334">"Feltet blev tilføjet"</string>
<string name="accessibility_qs_edit_tile_removed" msgid="1175925632436612036">"Feltet blev fjernet"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redigeringsværktøj til Kvikmenu."</string>
@@ -1015,7 +1015,7 @@
<string name="ongoing_privacy_dialog_phonecall" msgid="4487370562589839298">"Telefonopkald"</string>
<string name="ongoing_privacy_dialog_attribution_text" msgid="4738795925380373994">"(via <xliff:g id="APPLICATION_NAME_S_">%s</xliff:g>)"</string>
<string name="privacy_type_camera" msgid="7974051382167078332">"kameraet"</string>
- <string name="privacy_type_location" msgid="7991481648444066703">"placering"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"lokation"</string>
<string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofonen"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Deaktiver sensorer"</string>
<string name="device_services" msgid="1549944177856658705">"Enhedstjenester"</string>
@@ -1133,8 +1133,8 @@
<string name="upcoming_birthday_status_content_description" msgid="2165036816803797148">"<xliff:g id="NAME">%1$s</xliff:g> har snart fødselsdag"</string>
<string name="anniversary_status" msgid="1790034157507590838">"Årsdag"</string>
<string name="anniversary_status_content_description" msgid="8212171790843327442">"<xliff:g id="NAME">%1$s</xliff:g> har jubilæum i dag"</string>
- <string name="location_status" msgid="1294990572202541812">"Deler placering"</string>
- <string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g> deler sin placering"</string>
+ <string name="location_status" msgid="1294990572202541812">"Deler lokation"</string>
+ <string name="location_status_content_description" msgid="2982386178160071305">"<xliff:g id="NAME">%1$s</xliff:g> deler sin lokation"</string>
<string name="new_story_status" msgid="9012195158584846525">"Ny historie"</string>
<string name="new_story_status_content_description" msgid="4963137422622516708">"<xliff:g id="NAME">%1$s</xliff:g> har delt en ny historie"</string>
<string name="video_status" msgid="4548544654316843225">"Ser"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> vil gerne føje dette handlingsfelt til Kvikmenu"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Tilføj handlingsfelt"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Tilføj ikke felt"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Vælg bruger"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 6b5281e..20e967d 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Dadurch wird die Blockierung des Zugriffs für alle Apps und Dienste aufgehoben, die dein Mikrofon verwenden dürfen."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dadurch wird die Blockierung des Zugriffs für alle Apps und Dienste aufgehoben, die deine Kamera verwenden dürfen."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dadurch wird die Blockierung des Zugriffs für alle Apps und Dienste aufgehoben, die deine Kamera oder dein Mikrofon verwenden dürfen."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Gerät"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Sonstiges Gerät"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Übersicht ein-/ausblenden"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Aufgeladen"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Wird aufgeladen"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile Daten"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Verbunden"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"Keine automatische Verbindung über mobile Daten"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"Keine Verbindung"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"Keine anderen Netzwerke verfügbar"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"Keine Netzwerke verfügbar"</string>
@@ -1180,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> möchte die folgende Kachel den Schnelleinstellungen hinzufügen"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Kachel hinzufügen"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Kachel nicht hinzu"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Nutzer auswählen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index b55256c..5a11e3d 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Με αυτόν τον τρόπο καταργείται ο αποκλεισμός της πρόσβασης για όλες τις εφαρμογές και υπηρεσίες που επιτρέπεται να χρησιμοποιούν το μικρόφωνό σας."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Με αυτόν τον τρόπο καταργείται ο αποκλεισμός της πρόσβασης για όλες τις εφαρμογές και υπηρεσίες που επιτρέπεται να χρησιμοποιούν την κάμερά σας."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Με αυτόν τον τρόπο καταργείται ο αποκλεισμός της πρόσβασης για όλες τις εφαρμογές και υπηρεσίες που επιτρέπεται να χρησιμοποιούν την κάμερα ή το μικρόφωνό σας."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Συσκευή"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Άλλη συσκευή"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Εναλλαγή επισκόπησης"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Φορτίστηκε"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Φόρτιση"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"Η εφαρμογή <xliff:g id="APPNAME">%1$s</xliff:g> θέλει να προσθέσει το παρακάτω πλακίδιο στις Γρήγορες ρυθμίσεις"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Προσθήκη πλακιδίου"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Χωρίς προσθ. πλακιδ."</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Επιλογή χρήστη"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 081bfcb..8e9c550 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"This unblocks access for all apps and services allowed to use your microphone."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> wants to add the following tile to Quick Settings"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Add tile"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Do not add tile"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Select user"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 4e32027..9d8008b 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"This unblocks access for all apps and services allowed to use your microphone."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> wants to add the following tile to Quick Settings"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Add tile"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Do not add tile"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Select user"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 081bfcb..8e9c550 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"This unblocks access for all apps and services allowed to use your microphone."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> wants to add the following tile to Quick Settings"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Add tile"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Do not add tile"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Select user"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 081bfcb..8e9c550 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"This unblocks access for all apps and services allowed to use your microphone."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> wants to add the following tile to Quick Settings"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Add tile"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Do not add tile"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Select user"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 6641705..fd5faaf 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"This unblocks access for all apps and services allowed to use your microphone."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"This unblocks access for all apps and services allowed to use your camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"This unblocks access for all apps and services allowed to use your camera or microphone."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Charged"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charging"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> wants to add the following tile to Quick Settings"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Add tile"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Do not add tile"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Select user"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 154248c..335a66b 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Esta acción desbloquea el acceso para todos los servicios y las apps que tengan permitido usar el micrófono."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Esta acción desbloquea el acceso para todos los servicios y las apps que tengan permitido usar la cámara."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Esta acción permite que todas las aplicaciones y servicios que tengan permiso puedan usar la cámara o el micrófono."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Otro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Ocultar o mostrar Recientes"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Cargada"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Cargando"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> quiere agregar el siguiente azulejo a la Configuración rápida"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Agregar azulejo"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"No agregar azulejo"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Seleccionar usuario"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 8e19028..b5cb7c4 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Si lo haces, todas las aplicaciones y servicios que tengan permiso podrán usar tu micrófono."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Si lo haces, todas las aplicaciones y servicios que tengan permiso podrán usar tu cámara."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Si lo haces, todas las aplicaciones y servicios que tengan permiso podrán usar tu cámara o tu micrófono."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Otro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Mostrar u ocultar aplicaciones recientes"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Cargada"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Cargando"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> quiere añadir el siguiente recuadro a ajustes rápidos"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Añadir recuadro"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"No añadir recuadro"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Seleccionar usuario"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index d603182..3bcf351 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Sellega tühistatakse juurdepääsu blokeerimine kõikide rakenduste ja teenuste puhul, millel on lubatud mikrofoni kasutada."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Sellega tühistatakse juurdepääsu blokeerimine kõikide rakenduste ja teenuste puhul, millel on lubatud kaamerat kasutada."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Sellega tühistatakse juurdepääsu blokeerimine kõikide rakenduste ja teenuste puhul, millel on lubatud kaamerat või mikrofoni kasutada."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Seade"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Muu seade"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Lehe Ülevaade sisse- ja väljalülitamine"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Laetud"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Laadimine"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> soovib kiirseadetesse lisada järgmise paani"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Lisa paan"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Ära lisa paani"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Kasutaja valimine"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index d59dc7a..5003b4e 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -305,7 +305,7 @@
<string name="data_usage_disabled_dialog_4g_title" msgid="1490779000057752281">"4G datuen erabilera pausatu da"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="2286843518689837719">"Datu-konexioa pausatu egin da"</string>
<string name="data_usage_disabled_dialog_title" msgid="9131615296036724838">"Datuen erabilera pausatu da"</string>
- <string name="data_usage_disabled_dialog" msgid="7933201635215099780">"Iritsi zara ezarri zenuen datu-mugara. Datu-konexioa erabiltzeari utzi diozu.\n\nDatu-konexioa erabiltzeari berrekiten badiozu, datuen erabileragatiko gastuak izango dituzu."</string>
+ <string name="data_usage_disabled_dialog" msgid="7933201635215099780">"Iritsi zara ezarri zenuen datu-mugara. Datu-konexioa erabiltzeari utzi diozu.\n\nDatu-konexioa erabiltzeari berrekiten badiozu, baliteke zerbait ordaindu behar izatea datuak erabiltzeagatik."</string>
<string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"Jarraitu erabiltzen"</string>
<string name="gps_notification_searching_text" msgid="231304732649348313">"GPS seinalearen bila"</string>
<string name="gps_notification_found_text" msgid="3145873880174658526">"Kokapena GPS bidez ezarri da"</string>
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Mikrofonoa atzitzeko baimena duten aplikazio eta zerbitzu guztiek erabili ahalko dute."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kamera atzitzeko baimena duten aplikazio eta zerbitzu guztiek erabili ahalko dute."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kamera edo mikrofonoa atzitzeko baimena duten aplikazio eta zerbitzu guztiek erabili ahalko dituzte."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Gailua"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Beste gailu bat"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aldatu ikuspegi orokorra"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Kargatuta"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Kargatzen"</string>
@@ -999,7 +999,7 @@
<string name="slice_permission_deny" msgid="6870256451658176895">"Ukatu"</string>
<string name="auto_saver_title" msgid="6873691178754086596">"Sakatu bateria-aurrezlea noiz aktibatu programatzeko"</string>
<string name="auto_saver_text" msgid="3214960308353838764">"Aktibatu aurrezlea bateria agortzeko arriskua dagoenean"</string>
- <string name="no_auto_saver_action" msgid="7467924389609773835">"Ez"</string>
+ <string name="no_auto_saver_action" msgid="7467924389609773835">"Ez, eskerrik asko"</string>
<string name="auto_saver_enabled_title" msgid="4294726198280286333">"Bateria-aurrezlea aktibatu da"</string>
<string name="auto_saver_enabled_text" msgid="7889491183116752719">"Bateria-aurrezlea automatikoki aktibatuko da bateriaren %% <xliff:g id="PERCENTAGE">%d</xliff:g> gelditzen denean."</string>
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ezarpenak"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> aplikazioak lauza hau gehitu nahi du Ezarpen bizkorrak menuan:"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Gehitu lauza"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Ez gehitu lauza"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Hautatu erabiltzaile bat"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 62281ef..abe01d5 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"با این کار دسترسی برای همه برنامهها و سرویسهایی که مجاز هستند از میکروفونتان استفاده کنند لغو انسداد میشود."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"با این کار دسترسی برای همه برنامهها و سرویسهایی که مجاز هستند از دوربینتان استفاده کنند لغو انسداد میشود."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"با این کار دسترسی برای همه برنامهها و دستگاههایی که مجاز هستند از دوربین یا میکروفونتان استفاده کنند لغو انسداد میشود."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"دستگاه"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"دستگاه دیگر"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تغییر وضعیت نمای کلی"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"شارژ کامل شد"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"در حال شارژ شدن"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> میخواهد کاشی زیر را به «تنظیمات فوری» اضافه کند"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"افزودن کاشی"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"کاشی اضافه نشود"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"انتخاب کاربر"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 629b1ff..db11c26 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Tämä kumoaa kaikkien sellaisten sovellusten ja palveluiden eston, joilla on lupa käyttää mikrofoniasi."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tämä kumoaa kaikkien sellaisten sovellusten ja palveluiden eston, joilla on lupa käyttää kameraasi."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tämä kumoaa eston kaikkien sellaisten sovellusten ja palveluiden osalta, joilla on lupa käyttää kameraasi tai mikrofoniasi."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Laite"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Muu laite"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Näytä/piilota viimeisimmät"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Ladattu"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Ladataan"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> haluaa lisätä seuraavan laatan pika-asetuksiin"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Lisää laatta"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Älä lisää laattaa"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Valitse käyttäjä"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index a13f849..35ca25a 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Cette action débloque l\'accès pour toutes les applications et tous les services autorisés à utiliser le microphone."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Cette action débloque l\'accès pour toutes les applications et pour tous les services autorisés à utiliser l\'appareil photo."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Cette action débloque l\'accès pour toutes les applications et tous les services autorisés à utiliser l\'appareil photo ou le microphone."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Appareil"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Autre appareil"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Basculer l\'aperçu"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Chargée"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Charge en cours..."</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Données cellulaires"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Connexion active"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"Aucune connexion auto. des données cellulaires"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"Aucune connexion"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"Aucun autre réseau n\'est accessible"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"Aucun réseau n\'est accessible"</string>
@@ -1180,4 +1179,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"L\'application <xliff:g id="APPNAME">%1$s</xliff:g> veut ajouter la tuile suivante au menu Paramètres rapides"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Ajouter la tuile"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Ne pas ajouter tuile"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index f0bc8be..47b1b45 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Cette action débloque l\'accès à tous les services et applis autorisés à utiliser votre micro."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Cette action débloque l\'accès à tous les services et applis autorisés à utiliser votre appareil photo."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Cette action débloque l\'accès pour tous les services et applis autorisés à utiliser votre appareil photo ou votre micro."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Appareil"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Autre appareil"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activer/Désactiver l\'aperçu"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Chargé"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"En charge"</string>
@@ -1179,4 +1179,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> veut ajouter le bloc suivant aux Réglages rapides"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Ajouter un bloc"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Ne pas ajouter bloc"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index d6f8036..b36173d 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Con esta acción desbloquearase o acceso ao micrófono para todas as aplicacións e servizos que teñan permiso para utilizalo."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Con esta acción desbloquearase o acceso á cámara para todas as aplicacións e servizos que teñan permiso para utilizala."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Con esta acción desbloquearase o acceso á cámara ou ao micrófono para todas as aplicacións e servizos que teñan permiso para utilizalos."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activar/desactivar Visión xeral"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Cargado"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Cargando"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móbiles"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Conectada"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"Os datos móbiles non se conectarán automaticamente"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"Sen conexión"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"Non hai outras redes dispoñibles"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"Non hai redes dispoñibles"</string>
@@ -1180,4 +1179,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> solicita a túa aprobación para engadir o seguinte atallo a Configuración rápida"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Engadir atallo"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Non engadir atallo"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 11fe9b9..d51cce9 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -147,7 +147,7 @@
<string name="accessibility_manage_notification" msgid="582215815790143983">"નોટિફિકેશનને મેનેજ કરો"</string>
<string name="phone_label" msgid="5715229948920451352">"ફોન ખોલો"</string>
<string name="voice_assist_label" msgid="3725967093735929020">"વૉઇસ સહાય ખોલો"</string>
- <string name="camera_label" msgid="8253821920931143699">"કૅમેરો ખોલો"</string>
+ <string name="camera_label" msgid="8253821920931143699">"કૅમેરા ખોલો"</string>
<string name="cancel" msgid="1089011503403416730">"રદ કરો"</string>
<string name="biometric_dialog_confirm" msgid="2005978443007344895">"કન્ફર્મ કરો"</string>
<string name="biometric_dialog_try_again" msgid="8575345628117768844">"ફરી પ્રયાસ કરો"</string>
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"આ તમારા માઇક્રોફોનનો ઉપયોગ કરવાની મંજૂરી ધરાવતી તમામ ઍપ અને સેવાઓ માટે ઍક્સેસને અનબ્લૉક કરે છે."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"આ તમારા કૅમેરાનો ઉપયોગ કરવાની મંજૂરી ધરાવતી તમામ ઍપ અને સેવાઓ માટે ઍક્સેસને અનબ્લૉક કરે છે."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"આ તમારા કૅમેરા અથવા માઇક્રોફોનનો ઉપયોગ કરવાની મંજૂરી ધરાવતી તમામ ઍપ અને સેવાઓ માટે ઍક્સેસને અનબ્લૉક કરે છે."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"ડિવાઇસ"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"અન્ય ડિવાઇસ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ઝલકને ટૉગલ કરો"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ચાર્જ થઈ ગયું"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ચાર્જ થઈ રહ્યું છે"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"મોબાઇલ ડેટા"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"કનેક્ટ કરેલું"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"મોબાઇલ ડેટા ઑટોમૅટિક રીતે કનેક્ટ થશે નહીં"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"કોઈ કનેક્શન નથી"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"બીજાં કોઈ નેટવર્ક ઉપલબ્ધ નથી"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"કોઈ નેટવર્ક ઉપલબ્ધ નથી"</string>
@@ -1180,4 +1179,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"ઝડપી સેટિંગમાં <xliff:g id="APPNAME">%1$s</xliff:g> નીચે જણાવેલા ટાઇલ ઉમેરવા માગે છે"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"ટાઇલ ઉમેરો"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"ટાઇલ ઉમેરશો નહીં"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 44100dc..1726b81 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ऐसा करने से, माइक्रोफ़ोन का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें माइक्रोफ़ोन का इस्तेमाल करने की अनुमति दी गई है."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ऐसा करने से, कैमरे का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें कैमरे का इस्तेमाल करने की अनुमति दी गई है."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ऐसा करने से, कैमरा या माइक्रोफ़ोन का ऐक्सेस उन सभी ऐप्लिकेशन और सेवाओं के लिए अनब्लॉक हो जाएगा जिन्हें ये इस्तेमाल करने की अनुमति है."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"डिवाइस"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"अन्य डिवाइस"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"खास जानकारी टॉगल करें"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"चार्ज हो गई है"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"चार्ज हो रही है"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> इस टाइल को \'फटाफट सेटिंग\' में जोड़ने के लिए अनुमति चाहता है"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"टाइल जोड़ें"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"टाइल न जोड़ें"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"उपयोगकर्ता चुनें"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index ed1f3cb..2a69589 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -437,7 +437,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Time se deblokira pristup za sve aplikacije i usluge kojima je dopuštena upotreba vašeg mikrofona."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Time se deblokira pristup za sve aplikacije i usluge kojima je dopuštena upotreba vašeg fotoaparata."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Time se deblokira pristup za sve aplikacije i usluge kojima je dopuštena upotreba vašeg fotoaparata ili mikrofona."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Uređaj"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Ostali uređaji"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Uključivanje/isključivanje pregleda"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Napunjeno"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Punjenje"</string>
@@ -1171,7 +1171,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilni podaci"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string>
- <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilni podaci neće se automatski povezati"</string>
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobilna veza neće se automatski uspostaviti"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"Niste povezani"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nije dostupna nijedna druga mreža"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"Nema dostupnih mreža"</string>
@@ -1185,4 +1185,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> želi dodati sljedeću pločicu u Brze postavke"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Dodaj pločicu"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Nemoj dodati pločicu"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Odabir korisnika"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index b47e75b..d964611 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Ezzel feloldja a hozzáférés letiltását az összes olyan alkalmazás és szolgáltatás esetében, amelyek számára engedélyezte a mikrofon használatát."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ezzel feloldja a hozzáférés letiltását az összes olyan alkalmazás és szolgáltatás esetében, amelyek számára engedélyezte a kamera használatát."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ezzel feloldja a hozzáférés letiltását az összes olyan alkalmazás és szolgáltatás esetében, amelyek számára engedélyezte a kamera vagy a mikrofon használatát."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Eszköz"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Más eszköz"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Áttekintés be- és kikapcsolása"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Feltöltve"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Töltés"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> a következő mozaikot szeretné hozzáadni a Gyorsbeállításokhoz"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Mozaik hozzáadása"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Ne legyen hozzáadva"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Felhasználóválasztás"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 0fcfd65..2372265 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Սա բացում է մուտքը բոլոր հավելվածների և ծառայությունների համար, որոնք ունեն ձեր խոսափողն օգտագործելու թույլտվություն։"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Սա բացում է մուտքը բոլոր հավելվածների և ծառայությունների համար, որոնք ունեն ձեր տեսախցիկն օգտագործելու թույլտվություն։"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Սա բացում է մուտքը բոլոր հավելվածների և ծառայությունների համար, որոնք ունեն ձեր տեսախցիկը կամ խոսափողն օգտագործելու թույլտվություն։"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Սարք"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Այլ սարք"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Միացնել/անջատել համատեսքը"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Լիցքավորված է"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Լիցքավորվում է"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> հավելվածն ուզում է ավելացնել հետևյալ սալիկը Արագ կարգավորումներում"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Ավելացնել սալիկ"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Չավելացնել սալիկ"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Ընտրեք օգտատեր"</string>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 6486b0b..7de4c70 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan mikrofon."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan kamera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Langkah ini akan berhenti memblokir akses untuk semua aplikasi dan layanan yang diizinkan menggunakan kamera atau mikrofon."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Perangkat"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Perangkat lainnya"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aktifkan Ringkasan"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Terisi penuh"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Mengisi daya"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> ingin menambahkan kartu berikut ke Setelan Cepat"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Tambahkan kartu"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Jangan tambah kartu"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Pilih pengguna"</string>
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 0af672c..9805fe9 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Þetta veitir öllum forritum og þjónustum aðgang að hljóðnemanum þínum."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Þetta veitir öllum forritum og þjónustum aðgang að myndavélinni þinni."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Þetta veitir öllum forritum og þjónustum aðgang að myndavélinni og hljóðnemanum þínum."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Tæki"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Annað tæki"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Kveikja/slökkva á yfirliti"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Fullhlaðin"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Í hleðslu"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> vill bæta eftirfarandi reit við flýtistillingar"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Bæta reit við"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Ekki bæta reit við"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Velja notanda"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index d2f6335..e97a9a5 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Viene sbloccato l\'accesso per tutti i servizi e le app autorizzati a usare il microfono."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Viene sbloccato l\'accesso per tutti i servizi e le app autorizzati a usare la fotocamera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Viene sbloccato l\'accesso per tutti i servizi e le app autorizzati a usare la fotocamera o il microfono."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Altro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Attiva/disattiva la panoramica"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carica"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"In carica"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> vuole aggiungere il seguente riquadro alle Impostazioni rapide"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Aggiungi riquadro"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Non aggiungerlo"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Seleziona utente"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 78370d6..ae5dc08 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -439,7 +439,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"הפעולה הזו מבטלת את חסימת הגישה של כל האפליקציות והשירותים שמורשים להשתמש במיקרופון."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"הפעולה הזו מבטלת את חסימת הגישה של כל האפליקציות והשירותים שמורשים להשתמש במצלמה."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"הפעולה הזו מבטלת את חסימת הגישה של כל האפליקציות והשירותים שמורשים להשתמש במצלמה או במיקרופון."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"מכשיר"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"מכשיר אחר"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"החלפת מצב של מסכים אחרונים"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"הסוללה טעונה"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"בטעינה"</string>
@@ -1191,4 +1191,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"האפליקציה <xliff:g id="APPNAME">%1$s</xliff:g> מבקשת להוסיף להגדרות המהירות את האריח הבא"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"הוספת אריח"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"אין להוסיף אריח"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 7e8c6a1..8f07a2c 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"マイクの使用が許可されているすべてのアプリとサービスでアクセスのブロックが解除されます。"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"カメラの使用が許可されているすべてのアプリとサービスでアクセスのブロックが解除されます。"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"カメラやマイクの使用が許可されているすべてのアプリとサービスでアクセスのブロックが解除されます。"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"デバイス"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"その他のデバイス"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"概要を切り替え"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"充電が完了しました"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"充電しています"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> が以下のタイルをクイック設定に追加しようとしています"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"タイルを追加"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"タイルを追加しない"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ユーザーの選択"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index f7bcf7f..c6e2bec 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ამ მოქმედების მეშვეობით განიბლოკება ყველა აპსა და მომსახურებაზე წვდომა, რომელთაც აქვთ თქვენი მიკროფონის გამოყენების უფლება."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ამ მოქმედების მეშვეობით განიბლოკება ყველა აპსა და მომსახურებაზე წვდომა, რომელთაც აქვთ თქვენი კამერის გამოყენების უფლება."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ამ მოქმედების მეშვეობით განიბლოკება ყველა აპსა და მომსახურებაზე წვდომა, რომელთაც აქვთ თქვენი კამერის ან მიკროფონის გამოყენების უფლება."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"მოწყობილობა"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"სხვა მოწყობილობა"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"მიმოხილვის გადართვა"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"დატენილია"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"მიმდინარეობს დატენვა"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g>-ს სურს, დაამატოს შემდეგი მოზაიკა სწრაფ პარამეტრებში"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"მოზაიკის დამატება"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"არ დაემატოს მოზაიკა"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"მომხმარებლის არჩევა"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 92b93a0..4fb68e9 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Микрофоныңызды пайдалануға рұқсат берілген барлық қолданба мен қызметтің бөгеуі алынады."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Камераңызды пайдалануға рұқсат берілген барлық қолданба мен қызметтің бөгеуі алынады."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Камераңызды немесе микрофоныңызды пайдалануға рұқсат берілген барлық қолданба мен қызметтің бөгеуі алынады."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Құрылғы"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Басқа құрылғы"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Шолуды қосу/өшіру"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Зарядталды"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарядталуда"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> Жылдам параметрлерге келесі бөлшекті қосқысы келеді."</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Бөлшек қосу"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Бөлшек қоспау"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Пайдаланушыны таңдау"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 2b25be6..5e734f6 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ការធ្វើបែបនេះនឹងឈប់ទប់ស្កាត់ការចូលប្រើសម្រាប់កម្មវិធី និងសេវាកម្មទាំងអស់ ដែលត្រូវបានអនុញ្ញាតឱ្យប្រើមីក្រូហ្វូនរបស់អ្នក។"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ការធ្វើបែបនេះនឹងឈប់ទប់ស្កាត់ការចូលប្រើសម្រាប់កម្មវិធី និងសេវាកម្មទាំងអស់ ដែលត្រូវបានអនុញ្ញាតឱ្យប្រើកាមេរ៉ារបស់អ្នក។"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ការធ្វើបែបនេះនឹងឈប់ទប់ស្កាត់ការចូលប្រើសម្រាប់កម្មវិធី និងសេវាកម្មទាំងអស់ ដែលត្រូវបានអនុញ្ញាតឱ្យប្រើកាមេរ៉ា ឬមីក្រូហ្វូនរបស់អ្នក។"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"ឧបករណ៍"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"ឧបករណ៍ផ្សេងទៀត"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"បិទ/បើកទិដ្ឋភាពរួម"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"បានសាកថ្មពេញ"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"កំពុងសាកថ្ម"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> ចង់បញ្ចូលប្រអប់ខាងក្រោមទៅក្នុងការកំណត់រហ័ស"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"បញ្ចូលប្រអប់"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"កុំបញ្ចូលប្រអប់"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ជ្រើសរើសអ្នកប្រើប្រាស់"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 13b4bd7..798ea99 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ಇದು ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳಿಗೆ ಹಾಗೂ ಸೇವೆಗಳಿಗೆ ನಿಮ್ಮ ಮೈಕ್ರೋಫೋನ್ ಬಳಸುವುದಕ್ಕಾಗಿ ಇರುವ ಪ್ರವೇಶದ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ಇದು ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳಿಗೆ ಹಾಗೂ ಸೇವೆಗಳಿಗೆ ನಿಮ್ಮ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸುವುದಕ್ಕಾಗಿ ಇರುವ ಪ್ರವೇಶದ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ಇದು ಎಲ್ಲಾ ಆ್ಯಪ್ಗಳಿಗೆ ಹಾಗೂ ಸೇವೆಗಳಿಗೆ ನಿಮ್ಮ ಕ್ಯಾಮರಾ ಅಥವಾ ಮೈಕ್ರೋಫೋನ್ ಬಳಸುವುದಕ್ಕಾಗಿ ಇರುವ ಪ್ರವೇಶದ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"ಸಾಧನ"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"ಅನ್ಯ ಸಾಧನ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ಟಾಗಲ್ ನ ಅವಲೋಕನ"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"ಮೊಬೈಲ್ ಡೇಟಾ"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"ಮೊಬೈಲ್ ಡೇಟಾ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕನೆಕ್ಟ್ ಆಗುವುದಿಲ್ಲ"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"ಯಾವುದೇ ಕನೆಕ್ಷನ್ ಇಲ್ಲ"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"ಇತರ ಯಾವುದೇ ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿಲ್ಲ"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"ಯಾವುದೇ ನೆಟ್ವರ್ಕ್ಗಳು ಲಭ್ಯವಿಲ್ಲ"</string>
@@ -1180,4 +1179,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> ಈ ಕೆಳಗಿನ ಟೈಲ್ ಅನ್ನು ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಸೇರಿಸಲು ಬಯಸುತ್ತದೆ"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"ಟೈಲ್ ಅನ್ನು ಸೇರಿಸಿ"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"ಟೈಲ್ ಅನ್ನು ಸೇರಿಸಬೇಡಿ"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 81b0ec0..de38570 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"마이크를 사용할 수 있는 모든 앱 및 서비스에 대해 액세스가 차단 해제됩니다."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"카메라를 사용할 수 있는 모든 앱 및 서비스에 대해 액세스가 차단 해제됩니다."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"카메라 또는 마이크를 사용할 수 있는 모든 앱 및 서비스에 대해 액세스가 차단 해제됩니다."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"기기"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"기타 기기"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"최근 사용 버튼 전환"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"충전됨"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"충전 중"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g>에서 빠른 설정에 다음 타일을 추가하려고 합니다."</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"타일 추가"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"타일 추가 안함"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"사용자 선택"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 3161270..90f4689 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Микрофонуңузду колдонууга уруксат алган бардык колдонмолор менен кызматтар бөгөттөн чыгат."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Камераны колдонууга уруксат алган бардык колдонмолор менен кызматтар бөгөттөн чыгат."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Камераңызды же микрофонуңузду колдонууга уруксат алган бардык колдонмолор менен кызматтар бөгөттөн чыгат."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Түзмөк"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Башка түзмөк"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Назар режимин өчүрүү/күйгүзүү"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Кубатталды"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Кубатталууда"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> төмөнкү ыкчам баскычты Ыкчам жөндөөлөргө кошкону жатат"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Ыкчам баскыч кошуу"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Ыкчам баскыч кошулбасын"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Колдонуучуну тандоо"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 509a6f8..7f20d1f 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ນີ້ຈະຍົກເລີກການບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ໄມໂຄຣໂຟນຂອງທ່ານ."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ນີ້ຈະຍົກເລີກການບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ກ້ອງຖ່າຍຮູບຂອງທ່ານ."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ນີ້ຈະປົດບລັອກການເຂົ້າເຖິງແອັບ ແລະ ບໍລິການທັງໝົດທີ່ອະນຸຍາດໃຫ້ໃຊ້ກ້ອງຖ່າຍຮູບ ຫຼື ໄມໂຄຣໂຟນຂອງທ່ານ."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"ອຸປະກອນ"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"ອຸປະກອນອື່ນໆ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ສະຫຼັບພາບຮວມ"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ສາກເຕັມແລ້ວ."</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ກຳລັງສາກໄຟ"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> ຕ້ອງການເພີ່ມແຜ່ນຕໍ່ໄປນີ້ໃສ່ການຕັ້ງຄ່າດ່ວນ"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"ເພີ່ມແຜ່ນ"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"ຢ່າເພີ່ມແຜ່ນ"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ເລືອກຜູ້ໃຊ້"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 87d67b7..03858d5 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -439,7 +439,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Tai atlikus visų programų ir paslaugų prieigos blokavimas panaikinamas ir joms leidžiama naudoti mikrofoną."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tai atlikus visų programų ir paslaugų prieigos blokavimas panaikinamas ir joms leidžiama naudoti fotoaparatą."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tai atlikus visų programų ir paslaugų prieigos blokavimas panaikinamas ir joms leidžiama naudoti fotoaparatą ar mikrofoną."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Įrenginys"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Kitas įrenginys"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Perjungti apžvalgą"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Įkrautas"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Kraunamas"</string>
@@ -1191,4 +1191,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"„<xliff:g id="APPNAME">%1$s</xliff:g>“ nori prie sparčiųjų nustatymų pridėti toliau pateiktą išklotinės elementą"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Pridėti išklotinės elementą"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Nepridėti išklotinės elemento"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Naudotojo pasirinkimas"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 242d6ba..2db4fd4 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -437,7 +437,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Visas lietotnes un pakalpojumi, kurām ir atļauts izmantot mikrofonu, varēs tam piekļūt."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Visas lietotnes un pakalpojumi, kuriem ir atļauts izmantot kameru, varēs tai piekļūt."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Visas lietotnes un pakalpojumi, kuriem ir atļauts izmantot kameru vai mikrofonu, varēs tiem piekļūt."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Ierīce"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Cita ierīce"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Pārskata pārslēgšana"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Akumulators uzlādēts"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Notiek uzlāde"</string>
@@ -1185,4 +1185,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> pieprasa atļauju pievienot tālāk norādīto elementu ātrajiem iestatījumiem"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Pievienot elementu"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Nepievienot elementu"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Lietotāja atlase"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index fe4040e..b1a5a5e 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Ова ќе го одблокира пристапот за сите апликации и услуги на кои им е дозволено користење на микрофонот."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ова ќе го одблокира пристапот за сите апликации и услуги на кои им е дозволено користење на камерата."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ова ќе го одблокира пристапот за сите апликации и услуги на кои им е дозволено користење на камерата или микрофонот."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Уред"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Друг уред"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Вклучи/исклучи преглед"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Наполнета"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Се полни"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> сака да ја додаде следнава плочка на „Брзите поставки“"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Додајте плочка"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Не додавајте плочка"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Изберете корисник"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index db170de..dd937a8 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"നിങ്ങളുടെ മൈക്രോഫോൺ ഉപയോഗിക്കാൻ അനുവദിച്ചിരിക്കുന്ന എല്ലാ ആപ്പുകൾക്കും സേവനങ്ങൾക്കുമുള്ള ആക്സസ് ഇത് അൺബ്ലോക്ക് ചെയ്യുന്നു."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"നിങ്ങളുടെ ക്യാമറ ഉപയോഗിക്കാൻ അനുവദിച്ചിരിക്കുന്ന എല്ലാ ആപ്പുകൾക്കും സേവനങ്ങൾക്കുമുള്ള ആക്സസ് ഇത് അൺബ്ലോക്ക് ചെയ്യുന്നു."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"നിങ്ങളുടെ ക്യാമറയോ മൈക്രോഫോണോ ഉപയോഗിക്കാൻ അനുവദിച്ചിരിക്കുന്ന എല്ലാ ആപ്പുകൾക്കും സേവനങ്ങൾക്കുമുള്ള ആക്സസ് ഇത് അൺബ്ലോക്ക് ചെയ്യുന്നു."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"ഉപകരണം"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"മറ്റ് ഉപകരണം"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"അവലോകനം മാറ്റുക"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ചാർജായി"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ചാർജ് ചെയ്യുന്നു"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"ദ്രുത ക്രമീകരണത്തിലേക്ക് ഇനിപ്പറയുന്ന ടൈൽ ചേർക്കാൻ <xliff:g id="APPNAME">%1$s</xliff:g> ആവശ്യപ്പെടുന്നു"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"ടൈൽ ചേർക്കുക"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"ടൈൽ ചേർക്കരുത്"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ഉപയോക്താവിനെ തിരഞ്ഞെടുക്കൂ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index aed89bb..341b22d 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Энэ нь таны микрофоныг ашиглах зөвшөөрөлтэй бүх апп болон үйлчилгээний хандалтыг блокоос гаргана."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Энэ нь таны камерыг ашиглах зөвшөөрөлтэй бүх апп болон үйлчилгээний хандалтыг блокоос гаргана."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Энэ нь таны камер эсвэл микрофоныг ашиглах зөвшөөрөлтэй бүх апп болон үйлчилгээний хандалтыг блокоос гаргана."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Төхөөрөмж"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Бусад төхөөрөмж"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Тоймыг асаах/унтраах"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Цэнэглэгдсэн"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Цэнэглэж байна"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> нь дараах хавтанг Шуурхай тохиргоонд нэмэх хүсэлтэй байна"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Хавтан нэмэх"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Хавтанг бүү нэм"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Хэрэглэгч сонгох"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 633519a..c071582 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -248,7 +248,7 @@
<skip />
<string name="accessibility_notification_dismissed" msgid="4411652015138892952">"सूचना डिसमिस केल्या."</string>
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना शेड."</string>
- <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"द्रुत सेटिंग्ज."</string>
+ <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"क्विक सेटिंग्ज."</string>
<string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"लॉक स्क्रीन."</string>
<string name="accessibility_desc_settings" msgid="6728577365389151969">"सेटिंग्ज"</string>
<string name="accessibility_desc_recent_apps" msgid="1748675199348914194">"अवलोकन."</string>
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"हे तुमचा मायक्रोफोन वापरण्याची परवानगी असलेल्या सर्व ॲप्स आणि सेवांसाठी अॅक्सेस अनब्लॉक करते."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"हे तुमचा कॅमेरा वापरण्याची परवानगी असलेल्या सर्व ॲप्स आणि सेवांसाठी अॅक्सेस अनब्लॉक करते."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"हे तुमचा कॅमेरा आणि मायक्रोफोन वापरण्याची परवानगी असलेल्या सर्व ॲप्स व सेवांसाठी अॅक्सेस अनब्लॉक करते."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"डिव्हाइस"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"इतर डिव्हाइस"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"अवलोकन टॉगल करा."</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"चार्ज झाली"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"चार्ज होत आहे"</string>
@@ -659,7 +659,7 @@
<string name="system_ui_tuner" msgid="1471348823289954729">"सिस्टम UI ट्युनर"</string>
<string name="show_battery_percentage" msgid="6235377891802910455">"एम्बेडेड बॅटरी टक्केवारी दर्शवा"</string>
<string name="show_battery_percentage_summary" msgid="9053024758304102915">"चार्ज होत नसताना स्टेटस बार चिन्हामध्ये बॅटरी पातळी टक्केवारी दर्शवा"</string>
- <string name="quick_settings" msgid="6211774484997470203">"द्रुत सेटिंग्ज"</string>
+ <string name="quick_settings" msgid="6211774484997470203">"क्विक सेटिंग्ज"</string>
<string name="status_bar" msgid="4357390266055077437">"स्टेटस बार"</string>
<string name="overview" msgid="3522318590458536816">"अवलोकन"</string>
<string name="demo_mode" msgid="263484519766901593">"सिस्टम UI डेमो मोड"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"कनेक्ट केले आहे"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"मोबाइल डेटा ऑटो-कनेक्ट होणार नाही"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"कोणतेही कनेक्शन नाही"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"इतर कोणतेही नेटवर्क उपलब्ध नाहीत"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"कोणतेही नेटवर्क उपलब्ध नाही"</string>
@@ -1180,4 +1179,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> ला क्विक सेटिंग्जमध्ये पुढील टाइल जोडायची आहे"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"टाइल जोडा"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"टाइल जोडू नका"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index a689bb3..8388cdd 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Tindakan ini menyahsekat akses bagi semua apl dan perkhidmatan yang dibenarkan untuk menggunakan mikrofon anda."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Tindakan ini menyahsekat akses bagi semua apl dan perkhidmatan yang dibenarkan untuk menggunakan kamera anda."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Tindakan ini menyahsekat akses bagi semua apl dan perkhidmatan yang dibenarkan untuk menggunakan kamera atau mikrofon anda."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Peranti"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Peranti lain"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Togol Ikhtisar"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Sudah dicas"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Mengecas"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> mahu menambah jubin yang berikut kepada Tetapan Pantas"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Tambahkan jubin"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Jangan tambah jubin"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Pilih pengguna"</string>
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 4975a0a..a40f944 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"၎င်းက သင့်မိုက်ခရိုဖုန်းသုံးရန် ခွင့်ပြုထားသော အက်ပ်နှင့် ဝန်ဆောင်မှုအားလုံးအတွက် သုံးခွင့်ကို ပြန်ဖွင့်ပေးသည်။"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"၎င်းက သင့်ကင်မရာသုံးရန် ခွင့်ပြုထားသော အက်ပ်နှင့် ဝန်ဆောင်မှုအားလုံးအတွက် သုံးခွင့်ကို ပြန်ဖွင့်ပေးသည်။"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"၎င်းက သင့်ကင်မရာ (သို့) မိုက်ခရိုဖုန်းသုံးရန် ခွင့်ပြုထားသော အက်ပ်နှင့် ဝန်ဆောင်မှုအားလုံးအတွက် သုံးခွင့်ကို ပြန်ဖွင့်ပေးသည်။"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"စက်"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"အခြားစက်ပစ္စည်း"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ဖွင့်၊ ပိတ် အနှစ်ချုပ်"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"အားသွင်းပြီး"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"အားသွင်းနေ"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> က ‘အမြန် ဆက်တင်များ’ တွင် အောက်ပါအကွက်ငယ်ကို ထည့်လိုသည်"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"အကွက်ငယ် ထည့်ရန်"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"အကွက်ငယ် မထည့်ပါ"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"အသုံးပြုသူ ရွေးခြင်း"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index af8d47b..5542ad3 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Dette opphever blokkeringen av tilgang for alle apper og tjenester som har tillatelse til å bruke mikrofonen."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Dette opphever blokkeringen av tilgang for alle apper og tjenester som har tillatelse til å bruke kameraet."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Dette opphever blokkeringen av tilgang for alle apper og tjenester som har tillatelse til å bruke kameraet eller mikrofonen."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Enhet"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Annen enhet"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Slå oversikten av eller på"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Oppladet"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Lader"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> vil legge til denne brikken i Hurtiginnstillinger"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Legg til brikke"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Ikke legg til brikke"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Velg bruker"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index b6a186e..9a2e9a1 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"यसो गर्नुभयो भने माइक्रोफोन प्रयोग गर्ने अनुमति दिइएका सबै एप तथा सेवाहरूका लागि सो अनुमति अनब्लक गरिन्छ।"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"यसो गर्नुभयो भने क्यामेरा प्रयोग गर्ने अनुमति दिइएका सबै एप तथा सेवाहरूका लागि सो अनुमति अनब्लक गरिन्छ।"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"यसो गर्नुभयो भने क्यामेरा वा माइक्रोफोन प्रयोग गर्ने अनुमति दिइएका सबै एप तथा सेवाहरूका लागि सो अनुमति अनब्लक गरिन्छ।"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"यन्त्र"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"अर्को डिभाइड"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"परिदृश्य टगल गर्नुहोस्"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"चार्ज भयो"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"चार्ज हुँदै छ"</string>
@@ -1179,4 +1179,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> द्रुत सेटिङमा निम्न टाइल हाल्न चाहन्छ"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"टाइल हाल्नुहोस्"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"टाइल नहाल्नुहोस्"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 135ca57..8851c70e 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Hiermee hef je de toegangsblokkering op voor alle apps en services die rechten hebben om je microfoon te gebruiken."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Hiermee hef je de toegangsblokkering op voor alle apps en services die rechten hebben om je camera te gebruiken."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Hiermee hef je de toegangsblokkering op voor alle apps en services die rechten hebben om je camera of microfoon te gebruiken."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Apparaat"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Ander apparaat"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Overzicht aan- of uitzetten"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Opgeladen"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Opladen"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> wil de volgende tegel toevoegen aan Snelle instellingen"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Tegel toevoegen"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Tegel niet toevoegen"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Gebruiker selecteren"</string>
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 1d5ff4b..3b2f79d 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ଆପଣଙ୍କ ମାଇକ୍ରୋଫୋନକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ୍ କରେ।"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ଆପଣଙ୍କ କ୍ୟାମେରାକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ୍ କରେ।"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ଆପଣଙ୍କ କ୍ୟାମେରା କିମ୍ବା ମାଇକ୍ରୋଫୋନକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇଥିବା ସମସ୍ତ ଆପ୍ ଓ ସେବା ପାଇଁ ଏହା ଆକ୍ସେସକୁ ଅନବ୍ଲକ୍ କରେ।"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"ଡିଭାଇସ୍"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"ଅନ୍ୟ ଡିଭାଇସ୍"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ସଂକ୍ଷିପ୍ତ ବିବରଣୀକୁ ଟୋଗଲ୍ କରନ୍ତୁ"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ଚାର୍ଜ ହୋଇଗଲା"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ଚାର୍ଜ କରାଯାଉଛି"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"ମୋବାଇଲ ଡାଟା"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"ସଂଯୋଗ କରାଯାଇଛି"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"ମୋବାଇଲ ଡାଟା ସ୍ୱତଃ-ସଂଯୋଗ ହେବ ନାହିଁ"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"ସଂଯୋଗ ନାହିଁ"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"ଅନ୍ୟ କୌଣସି ନେଟୱାର୍କ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"କୌଣସି ନେଟୱାର୍କ ଉପଲବ୍ଧ ନାହିଁ"</string>
@@ -1180,4 +1179,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> କ୍ୱିକ୍ ସେଟିଂସରେ ନିମ୍ନୋକ୍ତ ଟାଇଲ୍ ଯୋଗ କରିବାକୁ ଚାହେଁ"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"ଟାଇଲ୍ ଯୋଗ କରନ୍ତୁ"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"ଟାଇଲ୍ ଯୋଗ କର ନାହିଁ"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 055d75b..88d158d 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"ਇਹ ਉਹਨਾਂ ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ ਪਹੁੰਚ ਨੂੰ ਅਣਬਲਾਕ ਕਰਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨੂੰ ਤੁਹਾਡਾ ਕੈਮਰਾ ਜਾਂ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੱਤੀ ਗਈ ਹੈ।"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"ਡੀਵਾਈਸ"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"ਹੋਰ ਡੀਵਾਈਸ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ਰੂਪ-ਰੇਖਾ ਨੂੰ ਟੌਗਲ ਕਰੋ"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ਚਾਰਜ ਹੋਇਆ"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ਚਾਰਜ ਕਰ ਰਿਹਾ ਹੈ"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"ਮੋਬਾਈਲ ਡਾਟਾ"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"ਕਨੈਕਟ ਹੈ"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"ਮੋਬਾਈਲ ਡਾਟਾ ਸਵੈ-ਕਨੈਕਟ ਨਹੀਂ ਹੋਵੇਗਾ"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"ਕੋਈ ਕਨੈਕਸ਼ਨ ਨਹੀਂ"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"ਕੋਈ ਹੋਰ ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"ਕੋਈ ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
@@ -1180,4 +1179,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> ਅੱਗੇ ਦਿੱਤੀ ਟਾਇਲ ਨੂੰ ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰਨਾ ਚਾਹੁੰਦੀ ਹੈ"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"ਟਾਇਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"ਟਾਇਲ ਸ਼ਾਮਲ ਨਾ ਕਰੋ"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index fc32959..969b38b 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -439,7 +439,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Spowoduje to odblokowanie dostępu dla wszystkich aplikacji i usług, które mają uprawnienia do korzystania z mikrofonu."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Spowoduje to odblokowanie dostępu dla wszystkich aplikacji i usług, które mają uprawnienia do korzystania z aparatu."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Spowoduje to odblokowanie dostępu dla wszystkich aplikacji i usług, które mają uprawnienia do korzystania z aparatu lub mikrofonu."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Urządzenie"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Inne urządzenie"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Przełącz Przegląd"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Naładowana"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Ładowanie"</string>
@@ -1191,4 +1191,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"Aplikacja <xliff:g id="APPNAME">%1$s</xliff:g> chce dodać do Szybkich ustawień ten kafelek"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Dodaj kafelek"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Nie dodawaj kafelka"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Wybierz użytkownika"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 24880122..9546571 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar seu microfone."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera ou seu microfone."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Alternar Visão geral"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregado"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Carregando"</string>
@@ -597,7 +597,7 @@
<string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
<string name="volume_zen_end_now" msgid="5901885672973736563">"Desativar agora"</string>
<string name="accessibility_volume_settings" msgid="1458961116951564784">"Configurações de som"</string>
- <string name="accessibility_volume_expand" msgid="7653070939304433603">"Expandir"</string>
+ <string name="accessibility_volume_expand" msgid="7653070939304433603">"Abrir"</string>
<string name="accessibility_volume_collapse" msgid="2746845391013829996">"Recolher"</string>
<string name="volume_odi_captions_tip" msgid="8825655463280990941">"Transcrição automática"</string>
<string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"Dica de legenda"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"O app <xliff:g id="APPNAME">%1$s</xliff:g> quer adicionar o bloco a seguir às Configurações rápidas"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Adicionar bloco"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Não adicionar bloco"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Selecionar usuário"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 68d306d..173eaa5 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Isto desbloqueia o acesso a todas as apps e serviços com autorização para utilizar o seu microfone."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Isto desbloqueia o acesso a todas as apps e serviços com autorização para utilizar a sua câmara."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Isto desbloqueia o acesso a todas as apps e serviços com autorização para utilizar a sua câmara ou microfone."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Ativar/desativar Vista geral"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregada"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"A carregar"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"A app <xliff:g id="APPNAME">%1$s</xliff:g> pretende adicionar o seguinte mosaico às Definições rápidas"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Adicionar mosaico"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Não adicion. mosaico"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Selecione utilizador"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 24880122..9546571 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar seu microfone."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Essa ação desbloqueia o acesso para todos os apps e serviços com autorização para usar sua câmera ou seu microfone."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispositivo"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Alternar Visão geral"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Carregado"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Carregando"</string>
@@ -597,7 +597,7 @@
<string name="zen_mode_and_condition" msgid="5043165189511223718">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
<string name="volume_zen_end_now" msgid="5901885672973736563">"Desativar agora"</string>
<string name="accessibility_volume_settings" msgid="1458961116951564784">"Configurações de som"</string>
- <string name="accessibility_volume_expand" msgid="7653070939304433603">"Expandir"</string>
+ <string name="accessibility_volume_expand" msgid="7653070939304433603">"Abrir"</string>
<string name="accessibility_volume_collapse" msgid="2746845391013829996">"Recolher"</string>
<string name="volume_odi_captions_tip" msgid="8825655463280990941">"Transcrição automática"</string>
<string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"Dica de legenda"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"O app <xliff:g id="APPNAME">%1$s</xliff:g> quer adicionar o bloco a seguir às Configurações rápidas"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Adicionar bloco"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Não adicionar bloco"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Selecionar usuário"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 169108a..3bca61f 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -437,7 +437,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Astfel, deblocați accesul pentru toate aplicațiile și serviciile care au permisiunea de a folosi microfonul."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Astfel, deblocați accesul pentru toate aplicațiile și serviciile care au permisiunea de a folosi camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Astfel, deblocați accesul pentru toate aplicațiile și serviciile care au permisiunea de a folosi camera sau microfonul."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Dispozitiv"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Alt dispozitiv"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Comutați secțiunea Recente"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Încărcată"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Se încarcă"</string>
@@ -1185,4 +1185,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> vrea să adauge următorul card la Setări rapide"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Adăugați un card"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Nu adăugați un card"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Alegeți utilizatorul"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 1859acd..84d4210 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -439,7 +439,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Будет снята блокировка доступа для всех приложений и сервисов с разрешением на использование микрофона."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Будет снята блокировка доступа для всех приложений и сервисов с разрешением на использование камеры."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Будет снята блокировка доступа для всех приложений и сервисов с разрешением на использование камеры или микрофона."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Устройство"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Другое устройство"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Переключить режим обзора"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Батарея заряжена"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Зарядка батареи"</string>
@@ -1191,4 +1191,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"Приложение \"<xliff:g id="APPNAME">%1$s</xliff:g>\" хочет добавить в меню \"Быстрые настройки\" указанный параметр."</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Добавить параметр"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Не добавлять"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Выберите профиль"</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 2df39d7..65855f4 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"මෙය ඔබගේ මයික්රෆෝනය භාවිත කිරීමට ඉඩ දී ඇති සියලු යෙදුම් සහ සේවා සඳහා ප්රවේශය අවහිර කිරීම ඉවත් කරයි."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"මෙය ඔබගේ කැමරාව භාවිතා කිරීමට ඉඩ දී ඇති සියලු යෙදුම් සහ සේවා සඳහා ප්රවේශය අවහිර කිරීම ඉවත් කරයි."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"මෙය ඔබගේ කැමරාව හෝ මයික්රෆෝනය භාවිත කිරීමට ඉඩ දී ඇති සියලු යෙදුම් සහ සේවා සඳහා ප්රවේශය අවහිර කිරීම ඉවත් කරයි."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"උපාංගය"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"වෙනත් උපාංගය"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"දළ විශ්ලේෂණය ටොගල කරන්න"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"අරෝපිතයි"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ආරෝපණය වෙමින්"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> හට ක්ෂණික සැකසීම් වෙත පහත ටයිල් එක් කිරීමට අවශ්යයි"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"ටයිල් එක් කරන්න"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"ටයිල් එක් නොකරන්න"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"පරිශීලක තෝරන්න"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 6ef5ad5..1202041 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -439,7 +439,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať mikrofón."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať fotoaparát."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Táto akcia odblokuje prístup všetkým aplikáciám a službám, ktoré majú povolené používať fotoaparát alebo mikrofón."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Zariadenie"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Iné zariadenie"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Prepnúť prehľad"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Nabitá"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Nabíja sa"</string>
@@ -1191,4 +1191,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"Aplikácia <xliff:g id="APPNAME">%1$s</xliff:g> chce pridať do rýchlych nastavení túto kartu"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Pridať kartu"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Nepridať kartu"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Vyberte používateľa"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 977104c..94437330 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -439,7 +439,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"S tem boste odblokirali dostop za vse aplikacije in storitve, ki imajo dovoljenje za uporabo mikrofona."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"S tem boste odblokirali dostop za vse aplikacije in storitve, ki imajo dovoljenje za uporabo fotoaparata."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"S tem boste odblokirali dostop za vse aplikacije in storitve, ki imajo dovoljenje za uporabo fotoaparata ali mikrofona."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Naprava"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Druga naprava"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Vklop/izklop pregleda"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Baterija napolnjena"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Polnjenje"</string>
@@ -1191,4 +1191,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"Aplikacija <xliff:g id="APPNAME">%1$s</xliff:g> želi dodati to ploščico v hitre nastavitve."</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Dodaj ploščico"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Ne dodaj ploščice"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Izberite uporabnika"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 970b84c..b6789a8 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Kjo zhbllokon qasjen për të gjitha aplikacionet dhe shërbimet që lejohen të përdorin mikrofonin tënd."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kjo zhbllokon qasjen për të gjitha aplikacionet dhe shërbimet që lejohen të përdorin kamerën tënde."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kjo zhbllokon qasjen për të gjitha aplikacionet dhe shërbimet që lejohen të përdorin kamerën ose mikrofonin tënd."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Pajisja"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Pajisje tjetër"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Kalo te përmbledhja"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"I karikuar"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Po karikohet"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Të dhënat celulare"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Lidhur"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"Të dhënat celulare nuk do të lidhen automatikisht"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"Nuk ka lidhje"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"Nuk ofrohet asnjë rrjet tjetër"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"Nuk ofrohet asnjë rrjet"</string>
@@ -1180,4 +1179,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> dëshiron të shtojë pllakëzën e mëposhtme te \"Cilësimet e shpejta\""</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Shto një pllakëz"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Mos e shto pllakëzën"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index e83b423..e4e324b 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -437,7 +437,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Овим ће се одблокирати приступ за све апликације и услуге које имају дозволу за коришћење микрофона."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Овим ће се одблокирати приступ за све апликације и услуге које имају дозволу за коришћење камере."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Овим ће се одблокирати приступ за све апликације и услуге које имају дозволу за коришћење камере или микрофона."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Уређај"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Други уређај"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Укључи/искључи преглед"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Напуњена је"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Пуни се"</string>
@@ -1185,4 +1185,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> жели да дода следећу плочицу у Брза подешавања"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Додај плочицу"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Не додај плочицу"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Изаберите корисника"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index bd819e5..b3dc3fc 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Detta återaktiverar åtkomsten för alla appar och tjänster som tillåts att använda mikrofonen."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Detta återaktiverar åtkomsten för alla appar och tjänster som tillåts att använda kameran."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Detta återaktiverar åtkomsten för alla appar och tjänster som tillåts att använda kameran eller mikrofonen."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Enhet"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Annan enhet"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aktivera och inaktivera översikten"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Laddat"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Laddar"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> vill lägga till följande ruta i snabbinställningarna"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Lägg till ruta"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Lägg inte till ruta"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Välj användare"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 121bcd2..fbf3094 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Hatua hii huruhusu programu na huduma zote zenye idhini zitumie maikrofoni yako."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Hatua hii huruhusu programu na huduma zote zenye idhini zitumie kamera yako."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Hatua hii huruhusu programu na huduma zote zenye idhini zitumie kamera au maikrofoni yako."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Kifaa"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Kifaa kingine"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Washa Muhtasari"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Betri imejaa"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Inachaji"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> ingependa kuongeza kigae kifuatacho kwenye Mipangilio ya Haraka"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Ongeza kigae"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Usiongeze kigae"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Chagua mtumiaji"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 74bdd32..18f94ac 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"உங்கள் மைக்ரோஃபோனைப் பயன்படுத்த அனுமதிக்கப்பட்டுள்ள அனைத்து ஆப்ஸ் மற்றும் சேவைகளை அணுகுவதற்கான தடுப்பை இது நீக்கும்."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"உங்கள் கேமராவைப் பயன்படுத்த அனுமதிக்கப்பட்டுள்ள அனைத்து ஆப்ஸ் மற்றும் சேவைகளை அணுகுவதற்கான தடுப்பை இது நீக்கும்."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"உங்கள் கேமராவையோ மைக்ரோஃபோனையோ பயன்படுத்த அனுமதிக்கப்பட்டுள்ள அனைத்து ஆப்ஸ் மற்றும் சேவைகளை அணுகுவதற்கான தடுப்பை இது நீக்கும்."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"சாதனம்"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"பிற சாதனம்"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"மேலோட்டப் பார்வையை நிலைமாற்று"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"சார்ஜ் செய்யப்பட்டது"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"சார்ஜ் ஆகிறது"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"விரைவு அமைப்புகளில் பின்வரும் கட்டத்தைச் சேர்க்க <xliff:g id="APPNAME">%1$s</xliff:g> ஆப்ஸ் விரும்புகிறது"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"கட்டத்தைச் சேர்"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"கட்டத்தை சேர்க்காதே"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"பயனரைத் தேர்வுசெய்க"</string>
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index b643685..ec279d0 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"మీ మైక్రోఫోన్ను ఉపయోగించడానికి అనుమతి పొందిన అన్ని యాప్లు, సర్వీస్లకు యాక్సెస్ను ఇది అన్బ్లాక్ చేస్తుంది."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"మీ కెమెరాను ఉపయోగించడానికి అనుమతి పొందిన అన్ని యాప్లు, సర్వీస్లకు యాక్సెస్ను ఇది అన్బ్లాక్ చేస్తుంది."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"మీ కెమెరాను లేదా మైక్రోఫోన్ను ఉపయోగించడానికి అనుమతి పొందిన అన్ని యాప్లు, సర్వీస్లకు యాక్సెస్ను ఇది అన్బ్లాక్ చేస్తుంది."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"పరికరం"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"ఇతర పరికరం"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"స్థూలదృష్టిని టోగుల్ చేయి"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ఛార్జ్ చేయబడింది"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"ఛార్జ్ అవుతోంది"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"మొబైల్ డేటా"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"కనెక్ట్ చేయబడింది"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"మొబైల్ డేటా ఆటోమెటిక్గా కనెక్ట్ అవ్వదు"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"కనెక్షన్ లేదు"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"ఇతర నెట్వర్క్లేవీ అందుబాటులో లేవు"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"నెట్వర్క్లు అందుబాటులో లేవు"</string>
@@ -1180,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"కింది టైల్ను క్విక్ సెట్టింగ్లకు జోడించడానికి <xliff:g id="APPNAME">%1$s</xliff:g> అనుమతి కోరుతోంది"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"టైల్ను జోడించండి"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"టైల్ను జోడించవద్దు"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"యూజర్ను ఎంచుకోండి"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index b27cd3e..639432d 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"การดำเนินการนี้จะเลิกบล็อกสิทธิ์เข้าถึงของแอปและบริการทั้งหมดที่ได้รับอนุญาตให้ใช้ไมโครโฟนของคุณ"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"การดำเนินการนี้จะเลิกบล็อกสิทธิ์เข้าถึงของแอปและบริการทั้งหมดที่ได้รับอนุญาตให้ใช้กล้องของคุณ"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"การดำเนินการนี้จะเลิกบล็อกสิทธิ์เข้าถึงของแอปและบริการทั้งหมดที่ได้รับอนุญาตให้ใช้กล้องหรือไมโครโฟนของคุณ"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"อุปกรณ์"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"อุปกรณ์อื่น"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"สลับภาพรวม"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"ชาร์จแล้ว"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"กำลังชาร์จ"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> ต้องการเพิ่มชิ้นส่วนต่อไปนี้ในการตั้งค่าด่วน"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"เพิ่มชิ้นส่วน"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"ไม่ต้องเพิ่มชิ้นส่วน"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"เลือกผู้ใช้"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 11a23f8..4da06b8 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Ina-unblock nito ang access para sa lahat ng app at serbisyong pinapayagang gumamit ng iyong mikropono."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Ina-unblock nito ang access para sa lahat ng app at serbisyong pinapayagang gumamit ng iyong camera."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Ina-unblock nito ang access para sa lahat ng app at serbisyong pinapayagang gumamit ng iyong camera o mikropono."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Device"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Iba pang device"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"I-toggle ang Overview"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Tapos nang mag-charge"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Nagcha-charge"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"Gustong idagdag ng <xliff:g id="APPNAME">%1$s</xliff:g> ang sumusunod na tile sa Mga Mabilisang Setting"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Idagdag ang tile"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Huwag idagdag"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Pumili ng user"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index a5c06f1..88665e0 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Bu işlem, mikrofonunuzu kullanmasına izin verilen tüm uygulama ve hizmetlere erişimin engellemesini kaldırır."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Bu işlem, kameranızı kullanmasına izin verilen tüm uygulama ve hizmetlere erişimin engellemesini kaldırır."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Bu işlem, kamera veya mikrofonunuzu kullanmasına izin verilen tüm uygulama ve hizmetlere erişimin engellemesini kaldırır."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Cihaz"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Diğer cihaz"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Genel bakışı aç/kapat"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Şarj oldu"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Şarj oluyor"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> aşağıdaki kartı Hızlı Ayarlar\'a eklemek istiyor"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Kart ekle"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Kart ekleme"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Kullanıcı seçin"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 616b0f2..267fe09 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -439,7 +439,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Усі додатки та сервіси, яким дозволено користуватися вашим мікрофоном, отримають доступ."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Усі додатки та сервіси, яким дозволено користуватися вашою камерою, отримають доступ."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Усі додатки та сервіси, яким дозволено користуватися вашою камерою чи мікрофоном, отримають доступ."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Пристрій"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Інший пристрій"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Увімкнути або вимкнути огляд"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Заряджено"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Заряджається"</string>
@@ -1191,4 +1191,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"Додаток <xliff:g id="APPNAME">%1$s</xliff:g> хоче додати такий параметр у меню швидких налаштувань:"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Додати параметр"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Не додавати параметр"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Виберіть користувача"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index a42729e..f8e5ca1 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"اس سے آپ کا مائیکروفون استعمال کرنے کے لیے اجازت یافتہ سبھی ایپس اور سروسز کے لیے رسائی غیر مسدود ہو جاتی ہے۔"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"اس سے آپ کا کیمرا استعمال کرنے کے لیے اجازت یافتہ سبھی ایپس اور سروسز کے لیے رسائی غیر مسدود ہو جاتی ہے۔"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"اس سے آپ کا کیمرا یا مائیکروفون استعمال کرنے کے لیے اجازت یافتہ سبھی ایپس اور سروسز کے لیے رسائی غیر مسدود ہو جاتی ہے۔"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"آلہ"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"دوسرا آلہ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"مجموعی جائزہ ٹوگل کریں"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"چارج ہوگئی"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"چارج ہو رہی ہے"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"موبائل ڈیٹا"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="NETWORKMODE">%2$s</xliff:g> / <xliff:g id="STATE">%1$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"منسلک ہے"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"موبائل ڈیٹا خودکار طور پر منسلک نہیں ہوگا"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"کوئی کنکشن نہیں"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"کوئی دوسرا نیٹ ورک دستیاب نہیں ہے"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"کوئی نیٹ ورکس دستیاب نہیں ہیں"</string>
@@ -1180,4 +1179,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> درج ذیل ٹائل کو فوری ترتیبات میں شامل کرنا چاہتی ہے"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"ٹائل شامل کریں"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"ٹائل شامل نہ کریں"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index e91ec32..b3a605c 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Mikrofoningizdan foydalanishga ruxsat berilgan barcha ilovalar va xizmatlar uchun ruxsatni blokdan chiqaradi."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Kamerangizdan foydalanishga ruxsat berilgan barcha ilovalar va xizmatlar uchun ruxsatni blokdan chiqaradi."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Kamera va mikrofoningizdan foydalanishga ruxsat berilgan barcha ilovalar va xizmatlar uchun ruxsatni blokdan chiqaradi."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Qurilma"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Boshqa qurilma"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Umumiy nazar rejimini almashtirish"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Quvvat oldi"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Quvvat olmoqda"</string>
@@ -1165,8 +1165,7 @@
<string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil internet"</string>
<string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
<string name="mobile_data_connection_active" msgid="944490013299018227">"Ulandi"</string>
- <!-- no translation found for mobile_data_off_summary (3663995422004150567) -->
- <skip />
+ <string name="mobile_data_off_summary" msgid="3663995422004150567">"Mobil internetga avtomatik ulanmaydi"</string>
<string name="mobile_data_no_connection" msgid="1713872434869947377">"Internetga ulanmagansiz"</string>
<string name="non_carrier_network_unavailable" msgid="770049357024492372">"Boshqa tarmoqlar mavjud emas"</string>
<string name="all_network_unavailable" msgid="4112774339909373349">"Hech qanday tarmoq mavjud emas"</string>
@@ -1180,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> ilovasi Tezkor sozlamalarga quyidagi tugmani kiritmoqchi"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Tugma kiritish"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Tugma kiritilmasin"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Foydalanuvchini tanlang"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index a52c999..e952e83 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Thao tác này sẽ bỏ chặn quyền truy cập cho mọi ứng dụng và dịch vụ được phép sử dụng micrô của bạn."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Thao tác này sẽ bỏ chặn quyền truy cập cho mọi ứng dụng và dịch vụ được phép sử dụng máy ảnh của bạn."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Thao tác này sẽ bỏ chặn quyền truy cập cho mọi ứng dụng và dịch vụ được phép sử dụng máy ảnh hoặc micrô của bạn."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Thiết bị"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Thiết bị khác"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Bật/tắt chế độ xem Tổng quan"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Đã sạc đầy"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Đang sạc"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"<xliff:g id="APPNAME">%1$s</xliff:g> muốn thêm ô bên dưới vào trình đơn Cài đặt nhanh"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Thêm ô"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Không thêm ô"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Chọn người dùng"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index d9fadf6..eab642c 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"这将会为所有获准使用您麦克风的应用和服务启用这项权限。"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"这将会为所有获准使用您摄像头的应用和服务启用这项权限。"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"这将会为所有获准使用您的摄像头或麦克风的应用和服务启用这项权限。"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"设备"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"其他设备"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切换概览"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"已充满"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"正在充电"</string>
@@ -1179,4 +1179,6 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"“<xliff:g id="APPNAME">%1$s</xliff:g>”希望将以下图块添加到“快捷设置”"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"添加图块"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"不添加图块"</string>
+ <!-- no translation found for qs_user_switch_dialog_title (3045189293587781366) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index ee853ce..b25851b 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"解除封鎖後,凡有存取權的應用程式和服務都可使用您的麥克風。"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"解除封鎖後,凡有存取權的應用程式和服務都可使用您的相機。"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"解除封鎖後,凡有存取權的應用程式和服務都可使用您的相機或麥克風。"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"裝置"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"其他裝置"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換概覽"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"已完成充電"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"充電中"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"「<xliff:g id="APPNAME">%1$s</xliff:g>」想在「快速設定」選單新增以下圖塊"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"新增圖塊"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"不要新增圖塊"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"選取使用者"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index dccbcc4..4ef03a6 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"這麼做可允許所有應用程式和服務使用麥克風。"</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"這麼做可允許所有應用程式和服務使用相機。"</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"這麼做可允許所有應用程式和服務使用相機或麥克風。"</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"裝置"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"其他裝置"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換總覽"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"已充飽"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"充電中"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"「<xliff:g id="APPNAME">%1$s</xliff:g>」想在快速設定選單新增以下設定方塊"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"新增設定方塊"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"不要新增設定方塊"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"選取使用者"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 683890f..30f0f4e 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -435,7 +435,7 @@
<string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"Lokhu kuvulela ukufinyelela kwawo wonke ama-app namasevisi avunyelwe ukusebenzisa imakrofoni yakho."</string>
<string name="sensor_privacy_start_use_camera_dialog_content" msgid="4704948062372435963">"Lokhu kuvulela ukufinyelela kwawo wonke ama-app namasevisi avunyelwe ukusebenzisa ikhamera yakho."</string>
<string name="sensor_privacy_start_use_mic_camera_dialog_content" msgid="3577642558418404919">"Lokhu kuvulela ukufinyelela kwawo wonke ama-app namasevisi avunyelwe ukusebenzisa ikhamera yakho noma imakrofoni."</string>
- <string name="media_seamless_remote_device" msgid="177033467332920464">"Idivayisi"</string>
+ <string name="media_seamless_other_device" msgid="4654849800789196737">"Enye idivayisi"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Guqula ukubuka konke"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Kushajiwe"</string>
<string name="expanded_header_battery_charging" msgid="1717522253171025549">"Iyashaja"</string>
@@ -1179,4 +1179,5 @@
<string name="qs_tile_request_dialog_text" msgid="3501359944139877694">"I-<xliff:g id="APPNAME">%1$s</xliff:g> ifuna ukwengeza ithayela elilandelayo Kumasethingi Asheshayo"</string>
<string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Engeza ithayela"</string>
<string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Ungafaki ithayela"</string>
+ <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Khetha umsebenzisi"</string>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
index 915e7f6..9010d51 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
@@ -16,7 +16,6 @@
package com.android.systemui.shared.animation
import android.graphics.Point
-import android.util.MathUtils.lerp
import android.view.Surface
import android.view.View
import android.view.WindowManager
@@ -27,7 +26,7 @@
* Creates an animation where all registered views are moved into their final location
* by moving from the center of the screen to the sides
*/
-class UnfoldMoveFromCenterAnimator(
+class UnfoldMoveFromCenterAnimator @JvmOverloads constructor(
private val windowManager: WindowManager,
/**
* Allows to set custom translation applier
@@ -36,14 +35,22 @@
* using custom methods instead of [View.setTranslationX] or
* [View.setTranslationY]
*/
- var translationApplier: TranslationApplier = object : TranslationApplier {}
+ private val translationApplier: TranslationApplier = object : TranslationApplier {},
+ /**
+ * Allows to set custom implementation for getting
+ * view location. Could be useful if logical view bounds
+ * are different than actual bounds (e.g. view container may
+ * have larger width than width of the items in the container)
+ */
+ private val viewCenterProvider: ViewCenterProvider = object : ViewCenterProvider {}
) : UnfoldTransitionProgressProvider.TransitionProgressListener {
private val screenSize = Point()
private var isVerticalFold = false
private val animatedViews: MutableList<AnimatedView> = arrayListOf()
- private val tmpArray = IntArray(2)
+
+ private var lastAnimationProgress: Float = 0f
/**
* Updates display properties in order to calculate the initial position for the views
@@ -60,6 +67,19 @@
}
/**
+ * If target view positions have changed (e.g. because of layout changes) call this method
+ * to re-query view positions and update the translations
+ */
+ fun updateViewPositions() {
+ animatedViews.forEach { animatedView ->
+ animatedView.view.get()?.let {
+ animatedView.updateAnimatedView(it)
+ }
+ }
+ onTransitionProgress(lastAnimationProgress)
+ }
+
+ /**
* Registers a view to be animated, the view should be measured and layouted
* After finishing the animation it is necessary to clear
* the views using [clearRegisteredViews]
@@ -82,43 +102,35 @@
it.view.get()?.let { view ->
translationApplier.apply(
view = view,
- x = lerp(it.startTranslationX, it.finishTranslationX, progress),
- y = lerp(it.startTranslationY, it.finishTranslationY, progress)
+ x = it.startTranslationX * (1 - progress),
+ y = it.startTranslationY * (1 - progress)
)
}
}
+ lastAnimationProgress = progress
}
- private fun createAnimatedView(view: View): AnimatedView {
- val viewLocation = tmpArray
- view.getLocationOnScreen(viewLocation)
+ private fun createAnimatedView(view: View): AnimatedView =
+ AnimatedView(view = WeakReference(view)).updateAnimatedView(view)
- val viewX = viewLocation[0].toFloat()
- val viewY = viewLocation[1].toFloat()
+ private fun AnimatedView.updateAnimatedView(view: View): AnimatedView {
+ val viewCenter = Point()
+ viewCenterProvider.getViewCenter(view, viewCenter)
- val viewCenterX = viewX + view.width / 2
- val viewCenterY = viewY + view.height / 2
-
- val translationXDiff: Float
- val translationYDiff: Float
+ val viewCenterX = viewCenter.x
+ val viewCenterY = viewCenter.y
if (isVerticalFold) {
val distanceFromScreenCenterToViewCenter = screenSize.x / 2 - viewCenterX
- translationXDiff = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE
- translationYDiff = 0f
+ startTranslationX = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE
+ startTranslationY = 0f
} else {
val distanceFromScreenCenterToViewCenter = screenSize.y / 2 - viewCenterY
- translationXDiff = 0f
- translationYDiff = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE
+ startTranslationX = 0f
+ startTranslationY = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE
}
- return AnimatedView(
- view = WeakReference(view),
- startTranslationX = view.translationX + translationXDiff,
- startTranslationY = view.translationY + translationYDiff,
- finishTranslationX = view.translationX,
- finishTranslationY = view.translationY
- )
+ return this
}
/**
@@ -134,12 +146,29 @@
}
}
+ /**
+ * Interface that allows to use custom logic to get the center of the view
+ */
+ interface ViewCenterProvider {
+ /**
+ * Called when we need to get the center of the view
+ */
+ fun getViewCenter(view: View, outPoint: Point) {
+ val viewLocation = IntArray(2)
+ view.getLocationOnScreen(viewLocation)
+
+ val viewX = viewLocation[0]
+ val viewY = viewLocation[1]
+
+ outPoint.x = viewX + view.width / 2
+ outPoint.y = viewY + view.height / 2
+ }
+ }
+
private class AnimatedView(
val view: WeakReference<View>,
- val startTranslationX: Float,
- val startTranslationY: Float,
- val finishTranslationX: Float,
- val finishTranslationY: Float
+ var startTranslationX: Float = 0f,
+ var startTranslationY: Float = 0f
)
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalSurfaceCallback.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalSurfaceCallback.aidl
index 58acce0..3d5998b 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalSurfaceCallback.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalSurfaceCallback.aidl
@@ -16,7 +16,7 @@
package com.android.systemui.shared.communal;
-import android.view.SurfaceControlViewHost;
+import android.view.SurfaceControlViewHost.SurfacePackage;
/**
* An interface for receiving the result of a surface request. ICommunalSurfaceCallback is
@@ -26,5 +26,5 @@
/**
* Invoked when the CommunalSurface has generated the SurfacePackage to be displayed.
*/
- void onSurface(in SurfaceControlViewHost.SurfacePackage surfacePackage) = 1;
+ void onSurface(in SurfacePackage surfacePackage) = 1;
}
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java
new file mode 100644
index 0000000..9ea4b57
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2016 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.shared.plugins;
+
+import android.app.Notification;
+import android.app.Notification.Action;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.util.ArraySet;
+import android.util.Log;
+import android.view.LayoutInflater;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.shared.plugins.VersionInfo.InvalidVersionException;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Coordinates all the available plugins for a given action.
+ *
+ * The available plugins are queried from the {@link PackageManager} via an an {@link Intent}
+ * action.
+ *
+ * @param <T> The type of plugin that this contains.
+ */
+public class PluginActionManager<T extends Plugin> {
+
+ private static final boolean DEBUG = false;
+
+ private static final String TAG = "PluginInstanceManager";
+ public static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN";
+
+ private final Context mContext;
+ private final PluginListener<T> mListener;
+ private final String mAction;
+ private final boolean mAllowMultiple;
+ private final NotificationManager mNotificationManager;
+ private final PluginEnabler mPluginEnabler;
+ private final PluginInstance.Factory mPluginInstanceFactory;
+ private final ArraySet<String> mPrivilegedPlugins = new ArraySet<>();
+
+ @VisibleForTesting
+ private final ArrayList<PluginInstance<T>> mPluginInstances = new ArrayList<>();
+ private final boolean mIsDebuggable;
+ private final PackageManager mPm;
+ private final Class<T> mPluginClass;
+ private final Executor mMainExecutor;
+ private final Executor mBgExecutor;
+
+ private PluginActionManager(
+ Context context,
+ PackageManager pm,
+ String action,
+ PluginListener<T> listener,
+ Class<T> pluginClass,
+ boolean allowMultiple,
+ Executor mainExecutor,
+ Executor bgExecutor,
+ boolean debuggable,
+ NotificationManager notificationManager,
+ PluginEnabler pluginEnabler,
+ List<String> privilegedPlugins,
+ PluginInstance.Factory pluginInstanceFactory) {
+ mPluginClass = pluginClass;
+ mMainExecutor = mainExecutor;
+ mBgExecutor = bgExecutor;
+ mContext = context;
+ mPm = pm;
+ mAction = action;
+ mListener = listener;
+ mAllowMultiple = allowMultiple;
+ mNotificationManager = notificationManager;
+ mPluginEnabler = pluginEnabler;
+ mPluginInstanceFactory = pluginInstanceFactory;
+ mPrivilegedPlugins.addAll(privilegedPlugins);
+ mIsDebuggable = debuggable;
+ }
+
+ /** Load all plugins matching this instance's action. */
+ public void loadAll() {
+ if (DEBUG) Log.d(TAG, "startListening");
+ mBgExecutor.execute(this::queryAll);
+ }
+
+ /** Unload all plugins managed by this instance. */
+ public void destroy() {
+ if (DEBUG) Log.d(TAG, "stopListening");
+ ArrayList<PluginInstance<T>> plugins = new ArrayList<>(mPluginInstances);
+ for (PluginInstance<T> plugInstance : plugins) {
+ mMainExecutor.execute(() -> onPluginDisconnected(plugInstance));
+ }
+ }
+
+ /** Unload all matching plugins managed by this instance. */
+ public void onPackageRemoved(String pkg) {
+ mBgExecutor.execute(() -> removePkg(pkg));
+ }
+
+ /** Unload and then reload all matching plugins managed by this instance. */
+ public void reloadPackage(String pkg) {
+ mBgExecutor.execute(() -> {
+ removePkg(pkg);
+ queryPkg(pkg);
+ });
+ }
+
+ /** Disable a specific plugin managed by this instance. */
+ public boolean checkAndDisable(String className) {
+ boolean disableAny = false;
+ ArrayList<PluginInstance<T>> plugins = new ArrayList<>(mPluginInstances);
+ for (PluginInstance<T> info : plugins) {
+ if (className.startsWith(info.getPackage())) {
+ disableAny |= disable(info, PluginEnabler.DISABLED_FROM_EXPLICIT_CRASH);
+ }
+ }
+ return disableAny;
+ }
+
+ /** Disable all plugins managed by this instance. */
+ public boolean disableAll() {
+ ArrayList<PluginInstance<T>> plugins = new ArrayList<>(mPluginInstances);
+ boolean disabledAny = false;
+ for (int i = 0; i < plugins.size(); i++) {
+ disabledAny |= disable(plugins.get(i), PluginEnabler.DISABLED_FROM_SYSTEM_CRASH);
+ }
+ return disabledAny;
+ }
+
+ boolean isPluginPrivileged(ComponentName pluginName) {
+ for (String componentNameOrPackage : mPrivilegedPlugins) {
+ ComponentName componentName = ComponentName.unflattenFromString(componentNameOrPackage);
+ if (componentName == null) {
+ if (componentNameOrPackage.equals(pluginName.getPackageName())) {
+ return true;
+ }
+ } else {
+ if (componentName.equals(pluginName)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean disable(
+ PluginInstance<T> pluginInstance, @PluginEnabler.DisableReason int reason) {
+ // Live by the sword, die by the sword.
+ // Misbehaving plugins get disabled and won't come back until uninstall/reinstall.
+
+ ComponentName pluginComponent = pluginInstance.getComponentName();
+ // If a plugin is detected in the stack of a crash then this will be called for that
+ // plugin, if the plugin causing a crash cannot be identified, they are all disabled
+ // assuming one of them must be bad.
+ if (isPluginPrivileged(pluginComponent)) {
+ // Don't disable privileged plugins as they are a part of the OS.
+ return false;
+ }
+ Log.w(TAG, "Disabling plugin " + pluginComponent.flattenToShortString());
+ mPluginEnabler.setDisabled(pluginComponent, reason);
+
+ return true;
+ }
+
+ <C> boolean dependsOn(Plugin p, Class<C> cls) {
+ ArrayList<PluginInstance<T>> instances = new ArrayList<>(mPluginInstances);
+ for (PluginInstance<T> instance : instances) {
+ if (instance.containsPluginClass(p.getClass())) {
+ return instance.getVersionInfo() != null && instance.getVersionInfo().hasClass(cls);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s@%s (action=%s)",
+ getClass().getSimpleName(), hashCode(), mAction);
+ }
+
+ private void onPluginConnected(PluginInstance<T> pluginInstance) {
+ if (DEBUG) Log.d(TAG, "onPluginConnected");
+ PluginPrefs.setHasPlugins(mContext);
+ pluginInstance.onCreate(mContext, mListener);
+ }
+
+ private void onPluginDisconnected(PluginInstance<T> pluginInstance) {
+ if (DEBUG) Log.d(TAG, "onPluginDisconnected");
+ pluginInstance.onDestroy(mListener);
+ }
+
+ private void queryAll() {
+ if (DEBUG) Log.d(TAG, "queryAll " + mAction);
+ for (int i = mPluginInstances.size() - 1; i >= 0; i--) {
+ PluginInstance<T> pluginInstance = mPluginInstances.get(i);
+ mMainExecutor.execute(() -> onPluginDisconnected(pluginInstance));
+ }
+ mPluginInstances.clear();
+ handleQueryPlugins(null);
+ }
+
+ private void removePkg(String pkg) {
+ for (int i = mPluginInstances.size() - 1; i >= 0; i--) {
+ final PluginInstance<T> pluginInstance = mPluginInstances.get(i);
+ if (pluginInstance.getPackage().equals(pkg)) {
+ mMainExecutor.execute(() -> onPluginDisconnected(pluginInstance));
+ mPluginInstances.remove(i);
+ }
+ }
+ }
+
+ private void queryPkg(String pkg) {
+ if (DEBUG) Log.d(TAG, "queryPkg " + pkg + " " + mAction);
+ if (mAllowMultiple || (mPluginInstances.size() == 0)) {
+ handleQueryPlugins(pkg);
+ } else {
+ if (DEBUG) Log.d(TAG, "Too many of " + mAction);
+ }
+ }
+
+ private void handleQueryPlugins(String pkgName) {
+ // This isn't actually a service and shouldn't ever be started, but is
+ // a convenient PM based way to manage our plugins.
+ Intent intent = new Intent(mAction);
+ if (pkgName != null) {
+ intent.setPackage(pkgName);
+ }
+ List<ResolveInfo> result = mPm.queryIntentServices(intent, 0);
+ if (DEBUG) Log.d(TAG, "Found " + result.size() + " plugins");
+ if (result.size() > 1 && !mAllowMultiple) {
+ // TODO: Show warning.
+ Log.w(TAG, "Multiple plugins found for " + mAction);
+ if (DEBUG) {
+ for (ResolveInfo info : result) {
+ ComponentName name = new ComponentName(info.serviceInfo.packageName,
+ info.serviceInfo.name);
+ Log.w(TAG, " " + name);
+ }
+ }
+ return;
+ }
+ for (ResolveInfo info : result) {
+ ComponentName name = new ComponentName(info.serviceInfo.packageName,
+ info.serviceInfo.name);
+ PluginInstance<T> pluginInstance = loadPluginComponent(name);
+ if (pluginInstance != null) {
+ // add plugin before sending PLUGIN_CONNECTED message
+ mPluginInstances.add(pluginInstance);
+ mMainExecutor.execute(() -> onPluginConnected(pluginInstance));
+ }
+ }
+ }
+
+ private PluginInstance<T> loadPluginComponent(ComponentName component) {
+ // This was already checked, but do it again here to make extra extra sure, we don't
+ // use these on production builds.
+ if (!mIsDebuggable && !isPluginPrivileged(component)) {
+ // Never ever ever allow these on production builds, they are only for prototyping.
+ Log.w(TAG, "Plugin cannot be loaded on production build: " + component);
+ return null;
+ }
+ if (!mPluginEnabler.isEnabled(component)) {
+ if (DEBUG) {
+ Log.d(TAG, "Plugin is not enabled, aborting load: " + component);
+ }
+ return null;
+ }
+ String packageName = component.getPackageName();
+ try {
+ // TODO: This probably isn't needed given that we don't have IGNORE_SECURITY on
+ if (mPm.checkPermission(PLUGIN_PERMISSION, packageName)
+ != PackageManager.PERMISSION_GRANTED) {
+ Log.d(TAG, "Plugin doesn't have permission: " + packageName);
+ return null;
+ }
+
+ ApplicationInfo appInfo = mPm.getApplicationInfo(packageName, 0);
+ // TODO: Only create the plugin before version check if we need it for
+ // legacy version check.
+ if (DEBUG) {
+ Log.d(TAG, "createPlugin");
+ }
+ try {
+ return mPluginInstanceFactory.create(
+ mContext, appInfo, component,
+ mPluginClass);
+ } catch (InvalidVersionException e) {
+ reportInvalidVersion(component, component.getClassName(), e);
+ }
+ } catch (Throwable e) {
+ Log.w(TAG, "Couldn't load plugin: " + packageName, e);
+ return null;
+ }
+
+ return null;
+ }
+
+ private void reportInvalidVersion(
+ ComponentName component, String className, InvalidVersionException e) {
+ final int icon = Resources.getSystem().getIdentifier(
+ "stat_sys_warning", "drawable", "android");
+ final int color = Resources.getSystem().getIdentifier(
+ "system_notification_accent_color", "color", "android");
+ final Notification.Builder nb = new Notification.Builder(mContext,
+ PluginManager.NOTIFICATION_CHANNEL_ID)
+ .setStyle(new Notification.BigTextStyle())
+ .setSmallIcon(icon)
+ .setWhen(0)
+ .setShowWhen(false)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setColor(mContext.getColor(color));
+ String label = className;
+ try {
+ label = mPm.getServiceInfo(component, 0).loadLabel(mPm).toString();
+ } catch (NameNotFoundException e2) {
+ // no-op
+ }
+ if (!e.isTooNew()) {
+ // Localization not required as this will never ever appear in a user build.
+ nb.setContentTitle("Plugin \"" + label + "\" is too old")
+ .setContentText("Contact plugin developer to get an updated"
+ + " version.\n" + e.getMessage());
+ } else {
+ // Localization not required as this will never ever appear in a user build.
+ nb.setContentTitle("Plugin \"" + label + "\" is too new")
+ .setContentText("Check to see if an OTA is available.\n"
+ + e.getMessage());
+ }
+ Intent i = new Intent(PluginManagerImpl.DISABLE_PLUGIN).setData(
+ Uri.parse("package://" + component.flattenToString()));
+ PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i,
+ PendingIntent.FLAG_IMMUTABLE);
+ nb.addAction(new Action.Builder(null, "Disable plugin", pi).build());
+ mNotificationManager.notify(SystemMessage.NOTE_PLUGIN, nb.build());
+ // TODO: Warn user.
+ Log.w(TAG, "Plugin has invalid interface version " + e.getActualVersion()
+ + ", expected " + e.getExpectedVersion());
+ }
+
+ /**
+ * Construct a {@link PluginActionManager}
+ */
+ public static class Factory {
+ private final Context mContext;
+ private final PackageManager mPackageManager;
+ private final Executor mMainExecutor;
+ private final Executor mBgExecutor;
+ private final NotificationManager mNotificationManager;
+ private final PluginEnabler mPluginEnabler;
+ private final List<String> mPrivilegedPlugins;
+ private final PluginInstance.Factory mPluginInstanceFactory;
+
+ public Factory(Context context, PackageManager packageManager,
+ Executor mainExecutor, Executor bgExecutor,
+ NotificationManager notificationManager, PluginEnabler pluginEnabler,
+ List<String> privilegedPlugins, PluginInstance.Factory pluginInstanceFactory) {
+ mContext = context;
+ mPackageManager = packageManager;
+ mMainExecutor = mainExecutor;
+ mBgExecutor = bgExecutor;
+ mNotificationManager = notificationManager;
+ mPluginEnabler = pluginEnabler;
+ mPrivilegedPlugins = privilegedPlugins;
+ mPluginInstanceFactory = pluginInstanceFactory;
+ }
+
+ <T extends Plugin> PluginActionManager<T> create(
+ String action, PluginListener<T> listener, Class<T> pluginClass,
+ boolean allowMultiple, boolean debuggable) {
+ return new PluginActionManager<>(mContext, mPackageManager, action, listener,
+ pluginClass, allowMultiple, mMainExecutor, mBgExecutor,
+ debuggable, mNotificationManager, mPluginEnabler,
+ mPrivilegedPlugins, mPluginInstanceFactory);
+ }
+ }
+
+ /** */
+ public static class PluginContextWrapper extends ContextWrapper {
+ private final ClassLoader mClassLoader;
+ private LayoutInflater mInflater;
+
+ public PluginContextWrapper(Context base, ClassLoader classLoader) {
+ super(base);
+ mClassLoader = classLoader;
+ }
+
+ @Override
+ public ClassLoader getClassLoader() {
+ return mClassLoader;
+ }
+
+ @Override
+ public Object getSystemService(String name) {
+ if (LAYOUT_INFLATER_SERVICE.equals(name)) {
+ if (mInflater == null) {
+ mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
+ }
+ return mInflater;
+ }
+ return getBaseContext().getSystemService(name);
+ }
+ }
+
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInitializer.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInitializer.java
deleted file mode 100644
index 895b6cd..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInitializer.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2018 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.shared.plugins;
-
-import android.content.Context;
-
-/**
- * Provides necessary components for initializing {@link PluginManagerImpl}.
- */
-public interface PluginInitializer {
-
- /**
- * Return a list of plugins that don't get disabled when an exception occurs.
- */
- String[] getPrivilegedPlugins(Context context);
-
-
- /**
- * Called from {@link PluginInstanceManager}.
- */
- void handleWtfs();
-}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java
new file mode 100644
index 0000000..2f84602
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.plugins;
+
+import android.app.LoadedApk;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginFragment;
+import com.android.systemui.plugins.PluginListener;
+
+import dalvik.system.PathClassLoader;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Contains a single instantiation of a Plugin.
+ *
+ * This class and its related Factory are in charge of actually instantiating a plugin and
+ * managing any state related to it.
+ *
+ * @param <T> The type of plugin that this contains.
+ */
+public class PluginInstance<T extends Plugin> {
+ private static final String TAG = "PluginInstance";
+ private static final Map<String, ClassLoader> sClassLoaders = new ArrayMap<>();
+
+ private final Context mPluginContext;
+ private final VersionInfo mVersionInfo;
+ private final ComponentName mComponentName;
+ private final T mPlugin;
+
+ /** */
+ public PluginInstance(ComponentName componentName, T plugin, Context pluginContext,
+ VersionInfo versionInfo) {
+ mComponentName = componentName;
+ mPlugin = plugin;
+ mPluginContext = pluginContext;
+ mVersionInfo = versionInfo;
+ }
+
+ /** Alerts listener and plugin that the plugin has been created. */
+ public void onCreate(Context appContext, PluginListener<T> listener) {
+ if (!(mPlugin instanceof PluginFragment)) {
+ // Only call onCreate for plugins that aren't fragments, as fragments
+ // will get the onCreate as part of the fragment lifecycle.
+ mPlugin.onCreate(appContext, mPluginContext);
+ }
+ listener.onPluginConnected(mPlugin, mPluginContext);
+ }
+
+ /** Alerts listener and plugin that the plugin is being shutdown. */
+ public void onDestroy(PluginListener<T> listener) {
+ listener.onPluginDisconnected(mPlugin);
+ if (!(mPlugin instanceof PluginFragment)) {
+ // Only call onDestroy for plugins that aren't fragments, as fragments
+ // will get the onDestroy as part of the fragment lifecycle.
+ mPlugin.onDestroy();
+ }
+ }
+
+ /**
+ * Returns if the contained plugin matches the passed in class name.
+ *
+ * It does this by string comparison of the class names.
+ **/
+ public boolean containsPluginClass(Class pluginClass) {
+ return mPlugin.getClass().getName().equals(pluginClass.getName());
+ }
+
+ public ComponentName getComponentName() {
+ return mComponentName;
+ }
+
+ public String getPackage() {
+ return mComponentName.getPackageName();
+ }
+
+ public VersionInfo getVersionInfo() {
+ return mVersionInfo;
+ }
+
+ @VisibleForTesting
+ Context getPluginContext() {
+ return mPluginContext;
+ }
+
+ /** Used to create new {@link PluginInstance}s. */
+ public static class Factory {
+ private final ClassLoader mBaseClassLoader;
+ private final InstanceFactory<?> mInstanceFactory;
+ private final VersionChecker mVersionChecker;
+ private final boolean mIsDebug;
+ private final List<String> mPrivilegedPlugins;
+
+ /** Factory used to construct {@link PluginInstance}s. */
+ public Factory(ClassLoader classLoader, InstanceFactory<?> instanceFactory,
+ VersionChecker versionChecker,
+ List<String> privilegedPlugins,
+ boolean isDebug) {
+ mPrivilegedPlugins = privilegedPlugins;
+ mBaseClassLoader = classLoader;
+ mInstanceFactory = instanceFactory;
+ mVersionChecker = versionChecker;
+ mIsDebug = isDebug;
+ }
+
+ /** Construct a new PluginInstance. */
+ public <T extends Plugin> PluginInstance<T> create(
+ Context context,
+ ApplicationInfo appInfo,
+ ComponentName componentName,
+ Class<T> pluginClass)
+ throws PackageManager.NameNotFoundException, ClassNotFoundException,
+ InstantiationException, IllegalAccessException {
+
+ ClassLoader classLoader = getClassLoader(appInfo, mBaseClassLoader);
+ Context pluginContext = new PluginActionManager.PluginContextWrapper(
+ context.createApplicationContext(appInfo, 0), classLoader);
+ Class<T> instanceClass = (Class<T>) Class.forName(
+ componentName.getClassName(), true, classLoader);
+ // TODO: Only create the plugin before version check if we need it for
+ // legacy version check.
+ T instance = (T) mInstanceFactory.create(instanceClass);
+ VersionInfo version = mVersionChecker.checkVersion(
+ instanceClass, pluginClass, instance);
+ return new PluginInstance<T>(componentName, instance, pluginContext, version);
+ }
+
+ private boolean isPluginPackagePrivileged(String packageName) {
+ for (String componentNameOrPackage : mPrivilegedPlugins) {
+ ComponentName componentName = ComponentName.unflattenFromString(
+ componentNameOrPackage);
+ if (componentName != null) {
+ if (componentName.getPackageName().equals(packageName)) {
+ return true;
+ }
+ } else if (componentNameOrPackage.equals(packageName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private ClassLoader getParentClassLoader(ClassLoader baseClassLoader) {
+ return new PluginManagerImpl.ClassLoaderFilter(
+ baseClassLoader, "com.android.systemui.plugin");
+ }
+
+ /** Returns class loader specific for the given plugin. */
+ private ClassLoader getClassLoader(ApplicationInfo appInfo,
+ ClassLoader baseClassLoader) {
+ if (!mIsDebug && !isPluginPackagePrivileged(appInfo.packageName)) {
+ Log.w(TAG, "Cannot get class loader for non-privileged plugin. Src:"
+ + appInfo.sourceDir + ", pkg: " + appInfo.packageName);
+ return null;
+ }
+ if (sClassLoaders.containsKey(appInfo.packageName)) {
+ return sClassLoaders.get(appInfo.packageName);
+ }
+
+ List<String> zipPaths = new ArrayList<>();
+ List<String> libPaths = new ArrayList<>();
+ LoadedApk.makePaths(null, true, appInfo, zipPaths, libPaths);
+ ClassLoader classLoader = new PathClassLoader(
+ TextUtils.join(File.pathSeparator, zipPaths),
+ TextUtils.join(File.pathSeparator, libPaths),
+ getParentClassLoader(baseClassLoader));
+ sClassLoaders.put(appInfo.packageName, classLoader);
+ return classLoader;
+ }
+ }
+
+ /** Class that compares a plugin class against an implementation for version matching. */
+ public static class VersionChecker {
+ /** Compares two plugin classes. */
+ public <T extends Plugin> VersionInfo checkVersion(
+ Class<T> instanceClass, Class<T> pluginClass, Plugin plugin) {
+ VersionInfo pluginVersion = new VersionInfo().addClass(pluginClass);
+ VersionInfo instanceVersion = new VersionInfo().addClass(instanceClass);
+ if (instanceVersion.hasVersionInfo()) {
+ pluginVersion.checkVersion(instanceVersion);
+ } else {
+ int fallbackVersion = plugin.getVersion();
+ if (fallbackVersion != pluginVersion.getDefaultVersion()) {
+ throw new VersionInfo.InvalidVersionException("Invalid legacy version", false);
+ }
+ return null;
+ }
+ return instanceVersion;
+ }
+ }
+
+ /**
+ * Simple class to create a new instance. Useful for testing.
+ *
+ * @param <T> The type of plugin this create.
+ **/
+ public static class InstanceFactory<T extends Plugin> {
+ T create(Class cls) throws IllegalAccessException, InstantiationException {
+ return (T) cls.newInstance();
+ }
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
deleted file mode 100644
index dcd3b3e..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstanceManager.java
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright (C) 2016 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.shared.plugins;
-
-import android.app.LoadedApk;
-import android.app.Notification;
-import android.app.Notification.Action;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.net.Uri;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-import android.view.LayoutInflater;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.systemui.plugins.Plugin;
-import com.android.systemui.plugins.PluginFragment;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.VersionInfo.InvalidVersionException;
-
-import dalvik.system.PathClassLoader;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-public class PluginInstanceManager<T extends Plugin> {
-
- private static final boolean DEBUG = false;
-
- private static final String TAG = "PluginInstanceManager";
- public static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN";
-
- private final Context mContext;
- private final PluginListener<T> mListener;
- private final String mAction;
- private final boolean mAllowMultiple;
- private final VersionInfo mVersion;
- private final NotificationManager mNotificationManager;
- private final PluginEnabler mPluginEnabler;
- private final InstanceFactory<T> mInstanceFactory;
- private final ArraySet<String> mPrivilegedPlugins = new ArraySet<>();
- private final Map<String, ClassLoader> mClassLoaders = new ArrayMap<>();
-
- @VisibleForTesting
- private final ArrayList<PluginInfo<T>> mPlugins = new ArrayList<>();
- private final boolean mIsDebuggable;
- private final PackageManager mPm;
- private final PluginInitializer mInitializer;
- private final Executor mMainExecutor;
- private final Executor mBgExecutor;
-
- private PluginManagerImpl.ClassLoaderFilter mParentClassLoader;
-
- private PluginInstanceManager(Context context, PackageManager pm, String action,
- PluginListener<T> listener, boolean allowMultiple, Executor mainExecutor,
- Executor bgExecutor, VersionInfo version, boolean debuggable,
- PluginInitializer initializer, NotificationManager notificationManager,
- PluginEnabler pluginEnabler, List<String> privilegedPlugins,
- InstanceFactory<T> instanceFactory) {
- mInitializer = initializer;
- mMainExecutor = mainExecutor;
- mBgExecutor = bgExecutor;
- mContext = context;
- mPm = pm;
- mAction = action;
- mListener = listener;
- mAllowMultiple = allowMultiple;
- mVersion = version;
- mNotificationManager = notificationManager;
- mPluginEnabler = pluginEnabler;
- mInstanceFactory = instanceFactory;
- mPrivilegedPlugins.addAll(privilegedPlugins);
- mIsDebuggable = debuggable;
- }
-
- public void loadAll() {
- if (DEBUG) Log.d(TAG, "startListening");
- mBgExecutor.execute(this::queryAll);
- }
-
- public void destroy() {
- if (DEBUG) Log.d(TAG, "stopListening");
- ArrayList<PluginInfo<T>> plugins = new ArrayList<>(mPlugins);
- for (PluginInfo<T> pluginInfo : plugins) {
- mMainExecutor.execute(() -> onPluginDisconnected(pluginInfo.mPlugin));
- }
- }
-
- public void onPackageRemoved(String pkg) {
- mBgExecutor.execute(() -> removePkg(pkg));
- }
-
- public void onPackageChange(String pkg) {
- mBgExecutor.execute(() -> removePkg(pkg));
- mBgExecutor.execute(() -> queryPkg(pkg));
- }
-
- public boolean checkAndDisable(String className) {
- boolean disableAny = false;
- ArrayList<PluginInfo<T>> plugins = new ArrayList<>(mPlugins);
- for (PluginInfo<T> info : plugins) {
- if (className.startsWith(info.mPackage)) {
- disableAny |= disable(info, PluginEnabler.DISABLED_FROM_EXPLICIT_CRASH);
- }
- }
- return disableAny;
- }
-
- public boolean disableAll() {
- ArrayList<PluginInfo<T>> plugins = new ArrayList<>(mPlugins);
- boolean disabledAny = false;
- for (int i = 0; i < plugins.size(); i++) {
- disabledAny |= disable(plugins.get(i), PluginEnabler.DISABLED_FROM_SYSTEM_CRASH);
- }
- return disabledAny;
- }
-
- private boolean isPluginPackagePrivileged(String packageName) {
- for (String componentNameOrPackage : mPrivilegedPlugins) {
- ComponentName componentName = ComponentName.unflattenFromString(componentNameOrPackage);
- if (componentName != null) {
- if (componentName.getPackageName().equals(packageName)) {
- return true;
- }
- } else if (componentNameOrPackage.equals(packageName)) {
- return true;
- }
- }
- return false;
- }
-
- private boolean isPluginPrivileged(ComponentName pluginName) {
- for (String componentNameOrPackage : mPrivilegedPlugins) {
- ComponentName componentName = ComponentName.unflattenFromString(componentNameOrPackage);
- if (componentName == null) {
- if (componentNameOrPackage.equals(pluginName.getPackageName())) {
- return true;
- }
- } else {
- if (componentName.equals(pluginName)) {
- return true;
- }
- }
- }
- return false;
- }
-
- private boolean disable(PluginInfo<T> info, @PluginEnabler.DisableReason int reason) {
- // Live by the sword, die by the sword.
- // Misbehaving plugins get disabled and won't come back until uninstall/reinstall.
-
- ComponentName pluginComponent = new ComponentName(info.mPackage, info.mClass);
- // If a plugin is detected in the stack of a crash then this will be called for that
- // plugin, if the plugin causing a crash cannot be identified, they are all disabled
- // assuming one of them must be bad.
- if (isPluginPrivileged(pluginComponent)) {
- // Don't disable whitelisted plugins as they are a part of the OS.
- return false;
- }
- Log.w(TAG, "Disabling plugin " + pluginComponent.flattenToShortString());
- mPluginEnabler.setDisabled(pluginComponent, reason);
-
- return true;
- }
-
- <C> boolean dependsOn(Plugin p, Class<C> cls) {
- ArrayList<PluginInfo<T>> plugins = new ArrayList<>(mPlugins);
- for (PluginInfo<T> info : plugins) {
- if (info.mPlugin.getClass().getName().equals(p.getClass().getName())) {
- return info.mVersion != null && info.mVersion.hasClass(cls);
- }
- }
- return false;
- }
-
- @Override
- public String toString() {
- return String.format("%s@%s (action=%s)",
- getClass().getSimpleName(), hashCode(), mAction);
- }
-
- private void onPluginConnected(PluginInfo<T> pluginInfo) {
- if (DEBUG) Log.d(TAG, "onPluginConnected");
- PluginPrefs.setHasPlugins(mContext);
- mInitializer.handleWtfs();
- if (!(pluginInfo.mPlugin instanceof PluginFragment)) {
- // Only call onCreate for plugins that aren't fragments, as fragments
- // will get the onCreate as part of the fragment lifecycle.
- pluginInfo.mPlugin.onCreate(mContext, pluginInfo.mPluginContext);
- }
- mListener.onPluginConnected(pluginInfo.mPlugin, pluginInfo.mPluginContext);
- }
-
- private void onPluginDisconnected(T plugin) {
- if (DEBUG) Log.d(TAG, "onPluginDisconnected");
- mListener.onPluginDisconnected(plugin);
- if (!(plugin instanceof PluginFragment)) {
- // Only call onDestroy for plugins that aren't fragments, as fragments
- // will get the onDestroy as part of the fragment lifecycle.
- plugin.onDestroy();
- }
- }
-
- private void queryAll() {
- if (DEBUG) Log.d(TAG, "queryAll " + mAction);
- for (int i = mPlugins.size() - 1; i >= 0; i--) {
- PluginInfo<T> pluginInfo = mPlugins.get(i);
- mMainExecutor.execute(() -> onPluginDisconnected(pluginInfo.mPlugin));
- }
- mPlugins.clear();
- handleQueryPlugins(null);
- }
-
- private void removePkg(String pkg) {
- for (int i = mPlugins.size() - 1; i >= 0; i--) {
- final PluginInfo<T> pluginInfo = mPlugins.get(i);
- if (pluginInfo.mPackage.equals(pkg)) {
- mMainExecutor.execute(() -> onPluginDisconnected(pluginInfo.mPlugin));
- mPlugins.remove(i);
- }
- }
- }
-
- private void queryPkg(String pkg) {
- if (DEBUG) Log.d(TAG, "queryPkg " + pkg + " " + mAction);
- if (mAllowMultiple || (mPlugins.size() == 0)) {
- handleQueryPlugins(pkg);
- } else {
- if (DEBUG) Log.d(TAG, "Too many of " + mAction);
- }
- }
-
- private void handleQueryPlugins(String pkgName) {
- // This isn't actually a service and shouldn't ever be started, but is
- // a convenient PM based way to manage our plugins.
- Intent intent = new Intent(mAction);
- if (pkgName != null) {
- intent.setPackage(pkgName);
- }
- List<ResolveInfo> result = mPm.queryIntentServices(intent, 0);
- if (DEBUG) Log.d(TAG, "Found " + result.size() + " plugins");
- if (result.size() > 1 && !mAllowMultiple) {
- // TODO: Show warning.
- Log.w(TAG, "Multiple plugins found for " + mAction);
- if (DEBUG) {
- for (ResolveInfo info : result) {
- ComponentName name = new ComponentName(info.serviceInfo.packageName,
- info.serviceInfo.name);
- Log.w(TAG, " " + name);
- }
- }
- return;
- }
- for (ResolveInfo info : result) {
- ComponentName name = new ComponentName(info.serviceInfo.packageName,
- info.serviceInfo.name);
- PluginInfo<T> pluginInfo = handleLoadPlugin(name);
- if (pluginInfo == null) continue;
-
- // add plugin before sending PLUGIN_CONNECTED message
- mPlugins.add(pluginInfo);
- mMainExecutor.execute(() -> onPluginConnected(pluginInfo));
- }
- }
-
- protected PluginInfo<T> handleLoadPlugin(ComponentName component) {
- // This was already checked, but do it again here to make extra extra sure, we don't
- // use these on production builds.
- if (!mIsDebuggable && !isPluginPrivileged(component)) {
- // Never ever ever allow these on production builds, they are only for prototyping.
- Log.w(TAG, "Plugin cannot be loaded on production build: " + component);
- return null;
- }
- if (!mPluginEnabler.isEnabled(component)) {
- if (DEBUG) Log.d(TAG, "Plugin is not enabled, aborting load: " + component);
- return null;
- }
- String pkg = component.getPackageName();
- String cls = component.getClassName();
- try {
- ApplicationInfo info = mPm.getApplicationInfo(pkg, 0);
- // TODO: This probably isn't needed given that we don't have IGNORE_SECURITY on
- if (mPm.checkPermission(PLUGIN_PERMISSION, pkg)
- != PackageManager.PERMISSION_GRANTED) {
- Log.d(TAG, "Plugin doesn't have permission: " + pkg);
- return null;
- }
- // Create our own ClassLoader so we can use our own code as the parent.
- ClassLoader classLoader = getClassLoader(info);
- Context pluginContext = new PluginContextWrapper(
- mContext.createApplicationContext(info, 0), classLoader);
- Class<?> pluginClass = Class.forName(cls, true, classLoader);
- // TODO: Only create the plugin before version check if we need it for
- // legacy version check.
- T plugin = mInstanceFactory.create(pluginClass);
- try {
- VersionInfo version = checkVersion(pluginClass, plugin, mVersion);
- if (DEBUG) Log.d(TAG, "createPlugin");
- return new PluginInfo<>(pkg, cls, plugin, pluginContext, version);
- } catch (InvalidVersionException e) {
- final int icon = Resources.getSystem().getIdentifier(
- "stat_sys_warning", "drawable", "android");
- final int color = Resources.getSystem().getIdentifier(
- "system_notification_accent_color", "color", "android");
- final Notification.Builder nb = new Notification.Builder(mContext,
- PluginManager.NOTIFICATION_CHANNEL_ID)
- .setStyle(new Notification.BigTextStyle())
- .setSmallIcon(icon)
- .setWhen(0)
- .setShowWhen(false)
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setColor(mContext.getColor(color));
- String label = cls;
- try {
- label = mPm.getServiceInfo(component, 0).loadLabel(mPm).toString();
- } catch (NameNotFoundException e2) {
- }
- if (!e.isTooNew()) {
- // Localization not required as this will never ever appear in a user build.
- nb.setContentTitle("Plugin \"" + label + "\" is too old")
- .setContentText("Contact plugin developer to get an updated"
- + " version.\n" + e.getMessage());
- } else {
- // Localization not required as this will never ever appear in a user build.
- nb.setContentTitle("Plugin \"" + label + "\" is too new")
- .setContentText("Check to see if an OTA is available.\n"
- + e.getMessage());
- }
- Intent i = new Intent(PluginManagerImpl.DISABLE_PLUGIN).setData(
- Uri.parse("package://" + component.flattenToString()));
- PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i,
- PendingIntent.FLAG_IMMUTABLE);
- nb.addAction(new Action.Builder(null, "Disable plugin", pi).build());
- mNotificationManager.notify(SystemMessage.NOTE_PLUGIN, nb.build());
- // TODO: Warn user.
- Log.w(TAG, "Plugin has invalid interface version " + plugin.getVersion()
- + ", expected " + mVersion);
- return null;
- }
- } catch (Throwable e) {
- Log.w(TAG, "Couldn't load plugin: " + pkg, e);
- return null;
- }
- }
-
- private VersionInfo checkVersion(Class<?> pluginClass, T plugin, VersionInfo version)
- throws InvalidVersionException {
- VersionInfo pv = new VersionInfo().addClass(pluginClass);
- if (pv.hasVersionInfo()) {
- version.checkVersion(pv);
- } else {
- int fallbackVersion = plugin.getVersion();
- if (fallbackVersion != version.getDefaultVersion()) {
- throw new InvalidVersionException("Invalid legacy version", false);
- }
- return null;
- }
- return pv;
- }
-
- /** Returns class loader specific for the given plugin. */
- public ClassLoader getClassLoader(ApplicationInfo appInfo) {
- if (!mIsDebuggable && !isPluginPackagePrivileged(appInfo.packageName)) {
- Log.w(TAG, "Cannot get class loader for non-privileged plugin. Src:"
- + appInfo.sourceDir + ", pkg: " + appInfo.packageName);
- return null;
- }
- if (mClassLoaders.containsKey(appInfo.packageName)) {
- return mClassLoaders.get(appInfo.packageName);
- }
-
- List<String> zipPaths = new ArrayList<>();
- List<String> libPaths = new ArrayList<>();
- LoadedApk.makePaths(null, true, appInfo, zipPaths, libPaths);
- ClassLoader classLoader = new PathClassLoader(
- TextUtils.join(File.pathSeparator, zipPaths),
- TextUtils.join(File.pathSeparator, libPaths),
- getParentClassLoader());
- mClassLoaders.put(appInfo.packageName, classLoader);
- return classLoader;
- }
-
- private ClassLoader getParentClassLoader() {
- if (mParentClassLoader == null) {
- // Lazily load this so it doesn't have any effect on devices without plugins.
- mParentClassLoader = new PluginManagerImpl.ClassLoaderFilter(
- getClass().getClassLoader(), "com.android.systemui.plugin");
- }
- return mParentClassLoader;
- }
-
- /**
- * Construct a {@link PluginInstanceManager}
- */
- public static class Factory {
- private final Context mContext;
- private final PackageManager mPackageManager;
- private final Executor mMainExecutor;
- private final Executor mBgExecutor;
- private final PluginInitializer mInitializer;
- private final NotificationManager mNotificationManager;
- private final PluginEnabler mPluginEnabler;
- private final List<String> mPrivilegedPlugins;
- private InstanceFactory<?> mInstanceFactory;
-
- public Factory(Context context, PackageManager packageManager,
- Executor mainExecutor, Executor bgExecutor, PluginInitializer initializer,
- NotificationManager notificationManager, PluginEnabler pluginEnabler,
- List<String> privilegedPlugins) {
- mContext = context;
- mPackageManager = packageManager;
- mMainExecutor = mainExecutor;
- mBgExecutor = bgExecutor;
- mInitializer = initializer;
- mNotificationManager = notificationManager;
- mPluginEnabler = pluginEnabler;
- mPrivilegedPlugins = privilegedPlugins;
-
- mInstanceFactory = new InstanceFactory<>();
- }
-
- @VisibleForTesting
- <T extends Plugin> Factory setInstanceFactory(InstanceFactory<T> instanceFactory) {
- mInstanceFactory = instanceFactory;
- return this;
- }
-
- <T extends Plugin> PluginInstanceManager<T> create(
- String action, PluginListener<T> listener, boolean allowMultiple,
- VersionInfo version, boolean debuggable) {
- return new PluginInstanceManager<T>(mContext, mPackageManager, action, listener,
- allowMultiple, mMainExecutor, mBgExecutor, version, debuggable,
- mInitializer, mNotificationManager, mPluginEnabler,
- mPrivilegedPlugins, (InstanceFactory<T>) mInstanceFactory);
- }
- }
-
- public static class PluginContextWrapper extends ContextWrapper {
- private final ClassLoader mClassLoader;
- private LayoutInflater mInflater;
-
- public PluginContextWrapper(Context base, ClassLoader classLoader) {
- super(base);
- mClassLoader = classLoader;
- }
-
- @Override
- public ClassLoader getClassLoader() {
- return mClassLoader;
- }
-
- @Override
- public Object getSystemService(String name) {
- if (LAYOUT_INFLATER_SERVICE.equals(name)) {
- if (mInflater == null) {
- mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
- }
- return mInflater;
- }
- return getBaseContext().getSystemService(name);
- }
- }
-
- static class PluginInfo<T extends Plugin> {
- private final Context mPluginContext;
- private final VersionInfo mVersion;
- private final String mClass;
- T mPlugin;
- String mPackage;
-
- public PluginInfo(String pkg, String cls, T plugin, Context pluginContext,
- VersionInfo info) {
- mPlugin = plugin;
- mClass = cls;
- mPackage = pkg;
- mPluginContext = pluginContext;
- mVersion = info;
- }
- }
-
- static class InstanceFactory<T extends Plugin> {
- T create(Class cls) throws IllegalAccessException, InstantiationException {
- return (T) cls.newInstance();
- }
- }
-}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManager.java
index d264bf2..c89be86 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManager.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManager.java
@@ -30,13 +30,15 @@
/** Returns plugins that don't get disabled when an exceptoin occurs. */
String[] getPrivilegedPlugins();
- <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls);
- <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls,
+ /** */
+ <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<T> cls);
+ /** */
+ <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<T> cls,
boolean allowMultiple);
<T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
- Class<?> cls);
+ Class<T> cls);
<T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
- Class<?> cls, boolean allowMultiple);
+ Class<T> cls, boolean allowMultiple);
void removePluginListener(PluginListener<?> listener);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
index ea7b0c3..7539f99 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
@@ -47,26 +47,26 @@
private static final String TAG = PluginManagerImpl.class.getSimpleName();
static final String DISABLE_PLUGIN = "com.android.systemui.action.DISABLE_PLUGIN";
- private final ArrayMap<PluginListener<?>, PluginInstanceManager<?>> mPluginMap
+ private final ArrayMap<PluginListener<?>, PluginActionManager<?>> mPluginMap
= new ArrayMap<>();
private final Map<String, ClassLoader> mClassLoaders = new ArrayMap<>();
private final ArraySet<String> mPrivilegedPlugins = new ArraySet<>();
private final Context mContext;
- private final PluginInstanceManager.Factory mInstanceManagerFactory;
+ private final PluginActionManager.Factory mActionManagerFactory;
private final boolean mIsDebuggable;
private final PluginPrefs mPluginPrefs;
private final PluginEnabler mPluginEnabler;
private boolean mListening;
public PluginManagerImpl(Context context,
- PluginInstanceManager.Factory instanceManagerFactory,
+ PluginActionManager.Factory actionManagerFactory,
boolean debuggable,
Optional<UncaughtExceptionHandler> defaultHandlerOptional,
PluginEnabler pluginEnabler,
PluginPrefs pluginPrefs,
List<String> privilegedPlugins) {
mContext = context;
- mInstanceManagerFactory = instanceManagerFactory;
+ mActionManagerFactory = actionManagerFactory;
mIsDebuggable = debuggable;
mPrivilegedPlugins.addAll(privilegedPlugins);
mPluginPrefs = pluginPrefs;
@@ -85,25 +85,27 @@
return mPrivilegedPlugins.toArray(new String[0]);
}
- public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls) {
+ /** */
+ public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<T> cls) {
addPluginListener(listener, cls, false);
}
- public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls,
+ /** */
+ public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<T> cls,
boolean allowMultiple) {
addPluginListener(PluginManager.Helper.getAction(cls), listener, cls, allowMultiple);
}
public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
- Class<?> cls) {
+ Class<T> cls) {
addPluginListener(action, listener, cls, false);
}
public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
- Class<?> cls, boolean allowMultiple) {
+ Class<T> cls, boolean allowMultiple) {
mPluginPrefs.addAction(action);
- PluginInstanceManager<T> p = mInstanceManagerFactory.create(action, listener, allowMultiple,
- new VersionInfo().addClass(cls), isDebuggable());
+ PluginActionManager<T> p = mActionManagerFactory.create(action, listener, cls,
+ allowMultiple, isDebuggable());
p.loadAll();
synchronized (this) {
mPluginMap.put(listener, p);
@@ -135,7 +137,7 @@
filter.addAction(PLUGIN_CHANGED);
filter.addAction(DISABLE_PLUGIN);
filter.addDataScheme("package");
- mContext.registerReceiver(this, filter, PluginInstanceManager.PLUGIN_PERMISSION, null);
+ mContext.registerReceiver(this, filter, PluginActionManager.PLUGIN_PERMISSION, null);
filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
mContext.registerReceiver(this, filter);
}
@@ -150,7 +152,7 @@
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
synchronized (this) {
- for (PluginInstanceManager<?> manager : mPluginMap.values()) {
+ for (PluginActionManager<?> manager : mPluginMap.values()) {
manager.loadAll();
}
}
@@ -189,12 +191,14 @@
}
}
synchronized (this) {
- if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
- for (PluginInstanceManager<?> manager : mPluginMap.values()) {
- manager.onPackageChange(pkg);
+ if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
+ || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
+ || Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction())) {
+ for (PluginActionManager<?> actionManager : mPluginMap.values()) {
+ actionManager.reloadPackage(pkg);
}
} else {
- for (PluginInstanceManager<?> manager : mPluginMap.values()) {
+ for (PluginActionManager<?> manager : mPluginMap.values()) {
manager.onPackageRemoved(pkg);
}
}
@@ -284,7 +288,7 @@
// disable all the plugins, so we can be sure that SysUI is running as
// best as possible.
synchronized (this) {
- for (PluginInstanceManager<?> manager : mPluginMap.values()) {
+ for (PluginActionManager<?> manager : mPluginMap.values()) {
disabledAny |= manager.disableAll();
}
}
@@ -304,7 +308,7 @@
boolean disabledAny = false;
synchronized (this) {
for (StackTraceElement element : throwable.getStackTrace()) {
- for (PluginInstanceManager<?> manager : mPluginMap.values()) {
+ for (PluginActionManager<?> manager : mPluginMap.values()) {
disabledAny |= manager.checkAndDisable(element.getClassName());
}
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/VersionInfo.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/VersionInfo.java
index bb845cd..6be3243 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/VersionInfo.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/VersionInfo.java
@@ -119,6 +119,8 @@
public static class InvalidVersionException extends RuntimeException {
private final boolean mTooNew;
+ private int mExpected;
+ private int mActual;
public InvalidVersionException(String str, boolean tooNew) {
super(str);
@@ -128,11 +130,21 @@
public InvalidVersionException(Class<?> cls, boolean tooNew, int expected, int actual) {
super(cls.getSimpleName() + " expected version " + expected + " but had " + actual);
mTooNew = tooNew;
+ mExpected = expected;
+ mActual = actual;
}
public boolean isTooNew() {
return mTooNew;
}
+
+ public int getExpectedVersion() {
+ return mExpected;
+ }
+
+ public int getActualVersion() {
+ return mActual;
+ }
}
private static class Version {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
index 49cd279..b6be6ed 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
@@ -22,7 +22,6 @@
import android.hardware.devicestate.DeviceStateManager
import android.os.Handler
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
-import com.android.systemui.unfold.config.ANIMATION_MODE_HINGE_ANGLE
import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig
import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.progress.FixedTimingTransitionProgressProvider
@@ -30,7 +29,6 @@
import com.android.systemui.unfold.updates.DeviceFoldStateProvider
import com.android.systemui.unfold.updates.hinge.EmptyHingeAngleProvider
import com.android.systemui.unfold.updates.hinge.HingeSensorAngleProvider
-import com.android.systemui.unfold.updates.hinge.RotationSensorHingeAngleProvider
import java.lang.IllegalStateException
import java.util.concurrent.Executor
@@ -50,14 +48,8 @@
}
val hingeAngleProvider =
- if (config.mode == ANIMATION_MODE_HINGE_ANGLE) {
- // TODO: after removing temporary "config.mode" we should just
- // switch between fixed timing and hinge sensor based on this flag
- if (config.isHingeAngleEnabled) {
- HingeSensorAngleProvider(sensorManager)
- } else {
- RotationSensorHingeAngleProvider(sensorManager)
- }
+ if (config.isHingeAngleEnabled) {
+ HingeSensorAngleProvider(sensorManager)
} else {
EmptyHingeAngleProvider()
}
@@ -70,7 +62,7 @@
mainExecutor
)
- return if (config.mode == ANIMATION_MODE_HINGE_ANGLE) {
+ return if (config.isHingeAngleEnabled) {
PhysicsBasedUnfoldTransitionProgressProvider(
mainHandler,
foldStateProvider
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
index e7c6998a..3f027e3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
@@ -23,17 +23,16 @@
) : UnfoldTransitionConfig {
override val isEnabled: Boolean
- get() = readIsEnabled() && mode != ANIMATION_MODE_DISABLED
+ get() = readIsEnabledResource() && isPropertyEnabled
override val isHingeAngleEnabled: Boolean
get() = readIsHingeAngleEnabled()
- @AnimationMode
- override val mode: Int
+ private val isPropertyEnabled: Boolean
get() = SystemProperties.getInt(UNFOLD_TRANSITION_MODE_PROPERTY_NAME,
- ANIMATION_MODE_FIXED_TIMING)
+ UNFOLD_TRANSITION_PROPERTY_ENABLED) == UNFOLD_TRANSITION_PROPERTY_ENABLED
- private fun readIsEnabled(): Boolean = context.resources
+ private fun readIsEnabledResource(): Boolean = context.resources
.getBoolean(com.android.internal.R.bool.config_unfoldTransitionEnabled)
private fun readIsHingeAngleEnabled(): Boolean = context.resources
@@ -44,4 +43,5 @@
* Temporary persistent property to control unfold transition mode
* See [com.android.unfold.config.AnimationMode]
*/
-private const val UNFOLD_TRANSITION_MODE_PROPERTY_NAME = "persist.unfold.transition_mode"
+private const val UNFOLD_TRANSITION_MODE_PROPERTY_NAME = "persist.unfold.transition_enabled"
+private const val UNFOLD_TRANSITION_PROPERTY_ENABLED = 1
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
index a569757..5b187b3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
@@ -15,25 +15,7 @@
*/
package com.android.systemui.unfold.config
-import android.annotation.IntDef
-
interface UnfoldTransitionConfig {
val isEnabled: Boolean
val isHingeAngleEnabled: Boolean
-
- @AnimationMode
- val mode: Int
}
-
-@IntDef(prefix = ["ANIMATION_MODE_"], value = [
- ANIMATION_MODE_DISABLED,
- ANIMATION_MODE_FIXED_TIMING,
- ANIMATION_MODE_HINGE_ANGLE
-])
-
-@Retention(AnnotationRetention.SOURCE)
-annotation class AnimationMode
-
-const val ANIMATION_MODE_DISABLED = 0
-const val ANIMATION_MODE_FIXED_TIMING = 1
-const val ANIMATION_MODE_HINGE_ANGLE = 2
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/RotationSensorHingeAngleProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/RotationSensorHingeAngleProvider.kt
deleted file mode 100644
index 8b6eecf..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/RotationSensorHingeAngleProvider.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.android.systemui.unfold.updates.hinge
-
-import android.hardware.Sensor
-import android.hardware.SensorEvent
-import android.hardware.SensorEventListener
-import android.hardware.SensorManager
-import androidx.core.util.Consumer
-import com.android.systemui.shared.recents.utilities.Utilities
-
-/**
- * Temporary hinge angle provider that uses rotation sensor instead.
- * It requires to have the device in a certain position to work correctly
- * (flat to the ground)
- */
-internal class RotationSensorHingeAngleProvider(
- private val sensorManager: SensorManager
-) : HingeAngleProvider {
-
- private val sensorListener = HingeAngleSensorListener()
- private val listeners: MutableList<Consumer<Float>> = arrayListOf()
-
- override fun start() {
- val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR)
- sensorManager.registerListener(sensorListener, sensor, SensorManager.SENSOR_DELAY_FASTEST)
- }
-
- override fun stop() {
- sensorManager.unregisterListener(sensorListener)
- }
-
- override fun removeCallback(listener: Consumer<Float>) {
- listeners.remove(listener)
- }
-
- override fun addCallback(listener: Consumer<Float>) {
- listeners.add(listener)
- }
-
- private fun onHingeAngle(angle: Float) {
- listeners.forEach { it.accept(angle) }
- }
-
- private inner class HingeAngleSensorListener : SensorEventListener {
-
- override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
- }
-
- override fun onSensorChanged(event: SensorEvent) {
- // Jumbojack sends incorrect sensor reading 1.0f event in the beginning, let's ignore it
- if (event.values[3] == 1.0f) return
-
- val angleRadians = event.values.convertToAngle()
- val hingeAngleDegrees = Math.toDegrees(angleRadians).toFloat()
- val angle = Utilities.clamp(hingeAngleDegrees, FULLY_CLOSED_DEGREES, FULLY_OPEN_DEGREES)
- onHingeAngle(angle)
- }
-
- private val rotationMatrix = FloatArray(9)
- private val resultOrientation = FloatArray(9)
-
- private fun FloatArray.convertToAngle(): Double {
- SensorManager.getRotationMatrixFromVector(rotationMatrix, this)
- SensorManager.getOrientation(rotationMatrix, resultOrientation)
- return resultOrientation[2] + Math.PI
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index c8f8404..cffc048 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -120,6 +120,7 @@
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
+ Trace.beginSection("ImageWallpaper.Engine#onCreate");
mEglHelper = getEglHelperInstance();
// Deferred init renderer because we need to get wallpaper by display context.
mRenderer = getRendererInstance();
@@ -129,6 +130,7 @@
mRenderer.setOnBitmapChanged(this::updateMiniBitmap);
getDisplayContext().getSystemService(DisplayManager.class)
.registerDisplayListener(this, mWorker.getThreadHandler());
+ Trace.endSection();
}
@Override
@@ -185,11 +187,13 @@
}
private void updateSurfaceSize() {
+ Trace.beginSection("ImageWallpaper#updateSurfaceSize");
SurfaceHolder holder = getSurfaceHolder();
Size frameSize = mRenderer.reportSurfaceSize();
int width = Math.max(MIN_SURFACE_WIDTH, frameSize.getWidth());
int height = Math.max(MIN_SURFACE_HEIGHT, frameSize.getHeight());
holder.setFixedSize(width, height);
+ Trace.endSection();
}
@Override
@@ -198,6 +202,11 @@
}
@Override
+ public boolean shouldWaitForEngineShown() {
+ return true;
+ }
+
+ @Override
public void onDestroy() {
getDisplayContext().getSystemService(DisplayManager.class)
.unregisterDisplayListener(this);
@@ -340,8 +349,10 @@
public void onSurfaceCreated(SurfaceHolder holder) {
if (mWorker == null) return;
mWorker.getThreadHandler().post(() -> {
+ Trace.beginSection("ImageWallpaper#onSurfaceCreated");
mEglHelper.init(holder, needSupportWideColorGamut());
mRenderer.onSurfaceCreated();
+ Trace.endSection();
});
}
@@ -358,9 +369,11 @@
}
private void drawFrame() {
+ Trace.beginSection("ImageWallpaper#drawFrame");
preRender();
requestRender();
postRender();
+ Trace.endSection();
}
public void preRender() {
@@ -425,9 +438,8 @@
public void postRender() {
// This method should only be invoked from worker thread.
- Trace.beginSection("ImageWallpaper#postRender");
scheduleFinishRendering();
- Trace.endSection();
+ reportEngineShown(false /* waitForEngineShown */);
}
private void cancelFinishRenderingTask() {
diff --git a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
index f9617ca..c7f1006 100644
--- a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
@@ -53,7 +53,7 @@
private static final String TAG = "PluginInflateContainer";
- private Class<?> mClass;
+ private Class<ViewProvider> mClass;
private View mPluginView;
public PluginInflateContainer(Context context, @Nullable AttributeSet attrs) {
@@ -61,7 +61,7 @@
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PluginInflateContainer);
String viewType = a.getString(R.styleable.PluginInflateContainer_viewType);
try {
- mClass = Class.forName(viewType);
+ mClass = (Class<ViewProvider>) Class.forName(viewType);
} catch (Exception e) {
Log.d(TAG, "Problem getting class info " + viewType, e);
mClass = null;
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index 66085ac0..39088c3 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -25,6 +25,7 @@
import android.animation.ObjectAnimator;
import android.annotation.IntDef;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Rect;
@@ -164,6 +165,12 @@
updateShowPercent();
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updatePercentView();
+ }
+
public void setColorsFromContext(Context context) {
if (context == null) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index 45ca708..9c818ff 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -20,6 +20,7 @@
import android.content.res.Configuration
import android.graphics.PointF
import android.hardware.biometrics.BiometricSourceType
+import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
@@ -38,6 +39,7 @@
import com.android.systemui.util.ViewController
import java.io.PrintWriter
import javax.inject.Inject
+import javax.inject.Provider
/***
* Controls the ripple effect that shows when authentication is successful.
@@ -54,12 +56,18 @@
private val notificationShadeWindowController: NotificationShadeWindowController,
private val bypassController: KeyguardBypassController,
private val biometricUnlockController: BiometricUnlockController,
+ private val udfpsControllerProvider: Provider<UdfpsController>,
rippleView: AuthRippleView?
) : ViewController<AuthRippleView>(rippleView) {
var fingerprintSensorLocation: PointF? = null
private var faceSensorLocation: PointF? = null
private var circleReveal: LightRevealEffect? = null
+ private var udfpsController: UdfpsController? = null
+ private var dwellScale = 2f
+ private var expandedDwellScale = 2.5f
+ private var udfpsRadius: Float = -1f
+
override fun onInit() {
mView.setAlphaInDuration(sysuiContext.resources.getInteger(
R.integer.auth_ripple_alpha_in_duration).toLong())
@@ -67,9 +75,11 @@
@VisibleForTesting
public override fun onViewAttached() {
+ authController.addCallback(authControllerCallback)
updateRippleColor()
updateSensorLocation()
- authController.addCallback(authControllerCallback)
+ updateUdfpsDependentParams()
+ udfpsController?.addCallback(udfpsControllerCallback)
configurationController.addCallback(configurationChangedListener)
keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
commandRegistry.registerCommand("auth-ripple") { AuthRippleCommand() }
@@ -77,6 +87,7 @@
@VisibleForTesting
public override fun onViewDetached() {
+ udfpsController?.removeCallback(udfpsControllerCallback)
authController.removeCallback(authControllerCallback)
keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
configurationController.removeCallback(configurationChangedListener)
@@ -94,18 +105,18 @@
if (biometricSourceType == BiometricSourceType.FINGERPRINT &&
fingerprintSensorLocation != null) {
mView.setSensorLocation(fingerprintSensorLocation!!)
- showRipple()
+ showUnlockedRipple()
} else if (biometricSourceType == BiometricSourceType.FACE &&
faceSensorLocation != null) {
if (!bypassController.canBypass()) {
return
}
mView.setSensorLocation(faceSensorLocation!!)
- showRipple()
+ showUnlockedRipple()
}
}
- private fun showRipple() {
+ private fun showUnlockedRipple() {
notificationShadeWindowController.setForcePluginOpen(true, this)
val biometricUnlockMode = biometricUnlockController.mode
val useCircleReveal = circleReveal != null &&
@@ -117,7 +128,7 @@
lightRevealScrim?.revealEffect = circleReveal!!
}
- mView.startRipple(
+ mView.startUnlockedRipple(
/* end runnable */
Runnable {
notificationShadeWindowController.setForcePluginOpen(false, this)
@@ -152,7 +163,7 @@
Utils.getColorAttr(sysuiContext, android.R.attr.colorAccent).defaultColor)
}
- val keyguardUpdateMonitorCallback =
+ private val keyguardUpdateMonitorCallback =
object : KeyguardUpdateMonitorCallback() {
override fun onBiometricAuthenticated(
userId: Int,
@@ -161,9 +172,13 @@
) {
showRipple(biometricSourceType)
}
+
+ override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType?) {
+ mView.retractRipple()
+ }
}
- val configurationChangedListener =
+ private val configurationChangedListener =
object : ConfigurationController.ConfigurationListener {
override fun onConfigChanged(newConfig: Configuration?) {
updateSensorLocation()
@@ -179,14 +194,97 @@
}
}
- private val authControllerCallback = AuthController.Callback { updateSensorLocation() }
+ private val udfpsControllerCallback =
+ object : UdfpsController.Callback {
+ override fun onFingerDown() {
+ if (fingerprintSensorLocation == null) {
+ Log.e("AuthRipple", "fingerprintSensorLocation=null onFingerDown. " +
+ "Skip showing dwell ripple")
+ return
+ }
+
+ mView.setSensorLocation(fingerprintSensorLocation!!)
+ mView.startDwellRipple(
+ /* startRadius */ udfpsRadius,
+ /* endRadius */ udfpsRadius * dwellScale,
+ /* expandedRadius */ udfpsRadius * expandedDwellScale)
+ }
+
+ override fun onFingerUp() {
+ mView.retractRipple()
+ }
+ }
+
+ private val authControllerCallback = AuthController.Callback {
+ updateSensorLocation()
+ updateUdfpsDependentParams()
+ }
+
+ private fun updateUdfpsDependentParams() {
+ authController.udfpsProps?.let {
+ if (it.size > 0) {
+ udfpsRadius = it[0].sensorRadius.toFloat()
+ udfpsController = udfpsControllerProvider.get()
+
+ if (mView.isAttachedToWindow) {
+ udfpsController?.addCallback(udfpsControllerCallback)
+ }
+ }
+ }
+ }
inner class AuthRippleCommand : Command {
+ fun printDwellInfo(pw: PrintWriter) {
+ pw.println("dwell ripple: " +
+ "\n\tsensorLocation=$fingerprintSensorLocation" +
+ "\n\tdwellScale=$dwellScale" +
+ "\n\tdwellAlpha=${mView.dwellAlpha}, " +
+ "duration=${mView.dwellAlphaDuration}" +
+ "\n\tdwellExpand=$expandedDwellScale" +
+ "\n\t(crash systemui to reset to default)")
+ }
+
override fun execute(pw: PrintWriter, args: List<String>) {
if (args.isEmpty()) {
invalidCommand(pw)
} else {
when (args[0]) {
+ "dwellScale" -> {
+ if (args.size > 1 && args[1].toFloatOrNull() != null) {
+ dwellScale = args[1].toFloat()
+ printDwellInfo(pw)
+ } else {
+ pw.println("expected float argument <dwellScale>")
+ }
+ }
+ "dwellAlpha" -> {
+ if (args.size > 2 && args[1].toFloatOrNull() != null &&
+ args[2].toLongOrNull() != null) {
+ mView.dwellAlpha = args[1].toFloat()
+ if (args[2].toFloat() > 200L) {
+ pw.println("alpha animation duration must be less than 200ms.")
+ }
+ mView.dwellAlphaDuration = kotlin.math.min(args[2].toLong(), 200L)
+ printDwellInfo(pw)
+ } else {
+ pw.println("expected two float arguments:" +
+ " <dwellAlpha> <dwellAlphaDuration>")
+ }
+ }
+ "dwellExpand" -> {
+ if (args.size > 1 && args[1].toFloatOrNull() != null) {
+ val expandedScale = args[1].toFloat()
+ if (expandedScale <= dwellScale) {
+ pw.println("invalid expandedScale. must be greater than " +
+ "dwellScale=$dwellScale, but given $expandedScale")
+ } else {
+ expandedDwellScale = expandedScale
+ }
+ printDwellInfo(pw)
+ } else {
+ pw.println("expected float argument <expandedScale>")
+ }
+ }
"fingerprint" -> {
pw.println("fingerprint ripple sensorLocation=$fingerprintSensorLocation")
showRipple(BiometricSourceType.FINGERPRINT)
@@ -205,7 +303,7 @@
pw.println("custom ripple sensorLocation=" + args[1].toFloat() + ", " +
args[2].toFloat())
mView.setSensorLocation(PointF(args[1].toFloat(), args[2].toFloat()))
- showRipple()
+ showUnlockedRipple()
}
else -> invalidCommand(pw)
}
@@ -215,6 +313,9 @@
override fun help(pw: PrintWriter) {
pw.println("Usage: adb shell cmd statusbar auth-ripple <command>")
pw.println("Available commands:")
+ pw.println(" dwellScale <200ms_scale: float>")
+ pw.println(" dwellAlpha <alpha: float> <duration : long>")
+ pw.println(" dwellExpand <expanded_scale: float>")
pw.println(" fingerprint")
pw.println(" face")
pw.println(" custom <x-location: int> <y-location: int>")
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index 95d0afa..8e13037 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -26,7 +26,9 @@
import android.util.AttributeSet
import android.view.View
import android.view.animation.PathInterpolator
+import com.android.internal.R.attr.interpolator
import com.android.internal.graphics.ColorUtils
+import com.android.systemui.animation.Interpolators
import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.charging.RippleShader
@@ -34,15 +36,28 @@
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
/**
- * Expanding ripple effect on the transition from biometric authentication success to showing
+ * Expanding ripple effect
+ * - startUnlockedRipple for the transition from biometric authentication success to showing
* launcher.
+ * - startDwellRipple for the ripple expansion out when the user has their finger down on the UDFPS
+ * sensor area
+ * - retractRipple for the ripple animation inwards to signal a failure
*/
class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
+ private val retractInterpolator = PathInterpolator(.05f, .93f, .1f, 1f)
+ private val dwellPulseDuration = 200L
+ var dwellAlphaDuration = dwellPulseDuration
+ private val dwellExpandDuration = 1200L - dwellPulseDuration
+ private val retractDuration = 400L
+
+ var dwellAlpha: Float = .5f
private var alphaInDuration: Long = 0
- private var rippleInProgress: Boolean = false
+ private var unlockedRippleInProgress: Boolean = false
private val rippleShader = RippleShader()
private val ripplePaint = Paint()
- private var radius: Float = 0.0f
+ private var retractAnimator: Animator? = null
+ private var dwellPulseOutAnimator: Animator? = null
+ private var radius: Float = 0f
set(value) {
rippleShader.radius = value
field = value
@@ -63,21 +78,182 @@
fun setSensorLocation(location: PointF) {
origin = location
- radius = maxOf(location.x, location.y, width - location.x, height - location.y)
- .toFloat()
+ radius = maxOf(location.x, location.y, width - location.x, height - location.y).toFloat()
}
fun setAlphaInDuration(duration: Long) {
alphaInDuration = duration
}
- fun startRipple(onAnimationEnd: Runnable?, lightReveal: LightRevealScrim?) {
- if (rippleInProgress) {
+ /**
+ * Animate ripple inwards back to radius 0
+ */
+ fun retractRipple() {
+ if (retractAnimator?.isRunning == true) {
+ return // let the animation finish
+ }
+
+ if (dwellPulseOutAnimator?.isRunning == true) {
+ val retractRippleAnimator = ValueAnimator.ofFloat(rippleShader.progress, 0f)
+ .apply {
+ interpolator = retractInterpolator
+ duration = retractDuration
+ addUpdateListener { animator ->
+ val now = animator.currentPlayTime
+ rippleShader.progress = animator.animatedValue as Float
+ rippleShader.time = now.toFloat()
+
+ invalidate()
+ }
+ }
+
+ val retractAlphaAnimator = ValueAnimator.ofInt(255, 0).apply {
+ interpolator = Interpolators.LINEAR
+ duration = retractDuration
+ addUpdateListener { animator ->
+ rippleShader.color = ColorUtils.setAlphaComponent(
+ rippleShader.color,
+ animator.animatedValue as Int
+ )
+ invalidate()
+ }
+ }
+
+ retractAnimator = AnimatorSet().apply {
+ playTogether(retractRippleAnimator, retractAlphaAnimator)
+ addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationStart(animation: Animator?) {
+ dwellPulseOutAnimator?.cancel()
+ rippleShader.shouldFadeOutRipple = false
+ visibility = VISIBLE
+ }
+
+ override fun onAnimationEnd(animation: Animator?) {
+ visibility = GONE
+ resetRippleAlpha()
+ }
+ })
+ start()
+ }
+ }
+ }
+
+ /**
+ * Ripple that moves animates from an outer ripple ring of
+ * startRadius => endRadius => expandedRadius
+ */
+ fun startDwellRipple(startRadius: Float, endRadius: Float, expandedRadius: Float) {
+ if (unlockedRippleInProgress || dwellPulseOutAnimator?.isRunning == true) {
+ return
+ }
+
+ // we divide by 4 because the desired startRadius and endRadius is for the ripple's outer
+ // ring see RippleShader
+ val startDwellProgress = startRadius / radius / 4f
+ val endInitialDwellProgress = endRadius / radius / 4f
+ val endExpandDwellProgress = expandedRadius / radius / 4f
+
+ val pulseOutEndAlpha = (255 * dwellAlpha).toInt()
+ val expandDwellEndAlpha = kotlin.math.min((255 * (dwellAlpha + .25f)).toInt(), 255)
+ val dwellPulseOutRippleAnimator = ValueAnimator.ofFloat(startDwellProgress,
+ endInitialDwellProgress).apply {
+ interpolator = Interpolators.LINEAR_OUT_SLOW_IN
+ duration = dwellPulseDuration
+ addUpdateListener { animator ->
+ val now = animator.currentPlayTime
+ rippleShader.progress = animator.animatedValue as Float
+ rippleShader.time = now.toFloat()
+
+ invalidate()
+ }
+ }
+
+ val dwellPulseOutAlphaAnimator = ValueAnimator.ofInt(0, pulseOutEndAlpha).apply {
+ interpolator = Interpolators.LINEAR
+ duration = dwellAlphaDuration
+ addUpdateListener { animator ->
+ rippleShader.color = ColorUtils.setAlphaComponent(
+ rippleShader.color,
+ animator.animatedValue as Int
+ )
+ invalidate()
+ }
+ }
+
+ // slowly animate outwards until we receive a call to retractRipple or startUnlockedRipple
+ val expandDwellRippleAnimator = ValueAnimator.ofFloat(endInitialDwellProgress,
+ endExpandDwellProgress).apply {
+ interpolator = Interpolators.LINEAR_OUT_SLOW_IN
+ duration = dwellExpandDuration
+ addUpdateListener { animator ->
+ val now = animator.currentPlayTime
+ rippleShader.progress = animator.animatedValue as Float
+ rippleShader.time = now.toFloat()
+
+ invalidate()
+ }
+ }
+
+ val expandDwellAlphaAnimator = ValueAnimator.ofInt(pulseOutEndAlpha, expandDwellEndAlpha)
+ .apply {
+ interpolator = Interpolators.LINEAR
+ duration = dwellExpandDuration
+ addUpdateListener { animator ->
+ rippleShader.color = ColorUtils.setAlphaComponent(
+ rippleShader.color,
+ animator.animatedValue as Int
+ )
+ invalidate()
+ }
+ }
+
+ val initialDwellPulseOutAnimator = AnimatorSet().apply {
+ playTogether(dwellPulseOutRippleAnimator, dwellPulseOutAlphaAnimator)
+ }
+ val expandDwellAnimator = AnimatorSet().apply {
+ playTogether(expandDwellRippleAnimator, expandDwellAlphaAnimator)
+ }
+
+ dwellPulseOutAnimator = AnimatorSet().apply {
+ playSequentially(
+ initialDwellPulseOutAnimator,
+ expandDwellAnimator
+ )
+ addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationStart(animation: Animator?) {
+ retractAnimator?.cancel()
+ rippleShader.shouldFadeOutRipple = false
+ visibility = VISIBLE
+ }
+
+ override fun onAnimationEnd(animation: Animator?) {
+ visibility = GONE
+ resetRippleAlpha()
+ }
+ })
+ start()
+ }
+ }
+
+ /**
+ * Ripple that bursts outwards from the position of the sensor to the edges of the screen
+ */
+ fun startUnlockedRipple(onAnimationEnd: Runnable?, lightReveal: LightRevealScrim?) {
+ if (unlockedRippleInProgress) {
return // Ignore if ripple effect is already playing
}
- val rippleAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
- interpolator = PathInterpolator(0f, 0f, .2f, 1f)
+ var rippleStart = 0f
+ var alphaDuration = alphaInDuration
+ if (dwellPulseOutAnimator?.isRunning == true || retractAnimator?.isRunning == true) {
+ rippleStart = rippleShader.progress
+ alphaDuration = 0
+ dwellPulseOutAnimator?.cancel()
+ retractAnimator?.cancel()
+ }
+
+ val rippleAnimator = ValueAnimator.ofFloat(rippleStart, 1f).apply {
+ interpolator = Interpolators.LINEAR_OUT_SLOW_IN
duration = RIPPLE_ANIMATION_DURATION
addUpdateListener { animator ->
val now = animator.currentPlayTime
@@ -97,7 +273,7 @@
}
val alphaInAnimator = ValueAnimator.ofInt(0, 255).apply {
- duration = alphaInDuration
+ duration = alphaDuration
addUpdateListener { animator ->
rippleShader.color = ColorUtils.setAlphaComponent(
rippleShader.color,
@@ -115,13 +291,14 @@
)
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?) {
- rippleInProgress = true
+ unlockedRippleInProgress = true
+ rippleShader.shouldFadeOutRipple = true
visibility = VISIBLE
}
override fun onAnimationEnd(animation: Animator?) {
onAnimationEnd?.run()
- rippleInProgress = false
+ unlockedRippleInProgress = false
visibility = GONE
}
})
@@ -129,8 +306,16 @@
animatorSet.start()
}
+ fun resetRippleAlpha() {
+ rippleShader.color = ColorUtils.setAlphaComponent(
+ rippleShader.color,
+ 255
+ )
+ }
+
fun setColor(color: Int) {
rippleShader.color = color
+ resetRippleAlpha()
}
override fun onDraw(canvas: Canvas?) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index ae426b6..62b9fd4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -77,7 +77,9 @@
import com.android.systemui.util.concurrency.Execution;
import com.android.systemui.util.time.SystemClock;
+import java.util.HashSet;
import java.util.Optional;
+import java.util.Set;
import javax.inject.Inject;
@@ -158,6 +160,7 @@
private Runnable mAodInterruptRunnable;
private boolean mOnFingerDown;
private boolean mAttemptedToDismissKeyguard;
+ private Set<Callback> mCallbacks = new HashSet<>();
@VisibleForTesting
public static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
@@ -877,6 +880,20 @@
}
/**
+ * Add a callback for fingerUp and fingerDown events
+ */
+ public void addCallback(Callback cb) {
+ mCallbacks.add(cb);
+ }
+
+ /**
+ * Remove callback
+ */
+ public void removeCallback(Callback cb) {
+ mCallbacks.remove(cb);
+ }
+
+ /**
* Cancel updfs scan affordances - ability to hide the HbmSurfaceView (white circle) before
* user explicitly lifts their finger. Generally, this should be called whenever udfps fails
* or errors.
@@ -930,6 +947,10 @@
mFingerprintManager.onUiReady(mSensorProps.sensorId);
Trace.endAsyncSection("UdfpsController.e2e.startIllumination", 0);
});
+
+ for (Callback cb : mCallbacks) {
+ cb.onFingerDown();
+ }
}
private void onFingerUp() {
@@ -942,6 +963,9 @@
}
if (mOnFingerDown) {
mFingerprintManager.onPointerUp(mSensorProps.sensorId);
+ for (Callback cb : mCallbacks) {
+ cb.onFingerUp();
+ }
}
mOnFingerDown = false;
if (mView.isIlluminationRequested()) {
@@ -962,4 +986,19 @@
mView.setOnTouchListener(mOnTouchListener);
}
}
+
+ /**
+ * Callback for fingerUp and fingerDown events.
+ */
+ public interface Callback {
+ /**
+ * Called onFingerUp events. Will only be called if the finger was previously down.
+ */
+ void onFingerUp();
+
+ /**
+ * Called onFingerDown events.
+ */
+ void onFingerDown();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 44ab69f..8ce4c3b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -292,7 +292,9 @@
: (int) MathUtils.constrain(
MathUtils.map(.5f, .9f, 0f, 255f, expansion),
0f, 255f);
- alpha *= (1.0f - mTransitionToFullShadeProgress);
+ if (!mShowingUdfpsBouncer) {
+ alpha *= (1.0f - mTransitionToFullShadeProgress);
+ }
mView.setUnpausedAlpha(alpha);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java b/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java
index 406981d..67ad3db 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/PluginModule.java
@@ -24,6 +24,7 @@
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.GlobalActions;
+import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
@@ -32,6 +33,7 @@
import dagger.Binds;
import dagger.Module;
+import dagger.Provides;
/**
* Module for binding Plugin implementations.
@@ -39,36 +41,40 @@
* TODO(b/166258224): Many of these should be moved closer to their implementations.
*/
@Module
-public interface PluginModule {
+public abstract class PluginModule {
+
+ /** */
+ @Provides
+ static ActivityStarter provideActivityStarter(ActivityStarterDelegate delegate,
+ PluginDependencyProvider dependencyProvider) {
+ dependencyProvider.allowPluginDependency(ActivityStarter.class, delegate);
+ return delegate;
+ }
/** */
@Binds
- ActivityStarter provideActivityStarter(ActivityStarterDelegate delegate);
+ abstract DarkIconDispatcher provideDarkIconDispatcher(DarkIconDispatcherImpl controllerImpl);
/** */
@Binds
- DarkIconDispatcher provideDarkIconDispatcher(DarkIconDispatcherImpl controllerImpl);
+ abstract FalsingManager provideFalsingManager(FalsingManagerProxy falsingManagerImpl);
/** */
@Binds
- FalsingManager provideFalsingManager(FalsingManagerProxy falsingManagerImpl);
+ abstract GlobalActions provideGlobalActions(GlobalActionsImpl controllerImpl);
/** */
@Binds
- GlobalActions provideGlobalActions(GlobalActionsImpl controllerImpl);
-
- /** */
- @Binds
- GlobalActions.GlobalActionsManager provideGlobalActionsManager(
+ abstract GlobalActions.GlobalActionsManager provideGlobalActionsManager(
GlobalActionsComponent controllerImpl);
/** */
@Binds
- StatusBarStateController provideStatusBarStateController(
+ abstract StatusBarStateController provideStatusBarStateController(
StatusBarStateControllerImpl controllerImpl);
/** */
@Binds
- VolumeDialogController provideVolumeDialogController(VolumeDialogControllerImpl controllerImpl);
-
+ abstract VolumeDialogController provideVolumeDialogController(
+ VolumeDialogControllerImpl controllerImpl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index d30783c..a51ec54 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -102,7 +102,6 @@
@Override
public Size reportSurfaceSize() {
- mTexture.use(null /* consumer */);
mSurfaceSize.set(mTexture.getTextureDimensions());
return new Size(mSurfaceSize.width(), mSurfaceSize.height());
}
@@ -124,6 +123,7 @@
private final WallpaperManager mWallpaperManager;
private Bitmap mBitmap;
private boolean mWcgContent;
+ private boolean mTextureUsed;
private WallpaperTexture(WallpaperManager wallpaperManager) {
mWallpaperManager = wallpaperManager;
@@ -141,6 +141,7 @@
mWallpaperManager.forgetLoadedWallpaper();
if (mBitmap != null) {
mDimensions.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+ mTextureUsed = true;
} else {
Log.w(TAG, "Can't get bitmap");
}
@@ -171,6 +172,9 @@
}
private Rect getTextureDimensions() {
+ if (!mTextureUsed) {
+ mDimensions.set(mWallpaperManager.peekBitmapDimensions());
+ }
return mDimensions;
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index 3167070..ecc3245 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -30,6 +30,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import android.app.StatusBarManager;
import android.app.StatusBarManager.WindowVisibleState;
@@ -46,6 +47,7 @@
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.CommandQueue;
import javax.inject.Inject;
@@ -126,6 +128,8 @@
.setFlag(SYSUI_STATE_NAV_BAR_HIDDEN, !isWindowVisible())
.setFlag(SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY,
allowSystemGestureIgnoringBarVisibility())
+ .setFlag(SYSUI_STATE_SCREEN_PINNING,
+ ActivityManagerWrapper.getInstance().isScreenPinningActive())
.commitUpdate(mDisplayId);
}
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginInitializerImpl.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginInitializerImpl.java
deleted file mode 100644
index 654d000..0000000
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginInitializerImpl.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2018 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.plugins;
-
-import android.content.Context;
-import android.util.Log;
-
-import com.android.systemui.R;
-import com.android.systemui.shared.plugins.PluginInitializer;
-import com.android.systemui.shared.plugins.PluginManagerImpl;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/** */
-@Singleton
-public class PluginInitializerImpl implements PluginInitializer {
-
- /**
- * True if WTFs should lead to crashes
- */
- private static final boolean WTFS_SHOULD_CRASH = false;
- private boolean mWtfsSet;
-
- @Inject
- public PluginInitializerImpl(PluginDependencyProvider dependencyProvider) {
- dependencyProvider.allowPluginDependency(ActivityStarter.class);
- }
-
- @Override
- public String[] getPrivilegedPlugins(Context context) {
- return context.getResources().getStringArray(R.array.config_pluginWhitelist);
- }
-
-
- @Override
- public void handleWtfs() {
- if (WTFS_SHOULD_CRASH && !mWtfsSet) {
- mWtfsSet = true;
- Log.setWtfHandler((tag, what, system) -> {
- throw new PluginManagerImpl.CrashWhilePluginActiveException(what);
- });
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java
index 1ea9b3c..a0cf44c 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java
@@ -23,10 +23,12 @@
import android.content.pm.PackageManager;
import android.os.Build;
+import com.android.systemui.R;
+import com.android.systemui.dagger.PluginModule;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.shared.plugins.PluginActionManager;
import com.android.systemui.shared.plugins.PluginEnabler;
-import com.android.systemui.shared.plugins.PluginInitializer;
-import com.android.systemui.shared.plugins.PluginInstanceManager;
+import com.android.systemui.shared.plugins.PluginInstance;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
import com.android.systemui.shared.plugins.PluginPrefs;
@@ -66,19 +68,30 @@
@Binds
abstract PluginEnabler bindsPluginEnablerImpl(PluginEnablerImpl impl);
- @Binds
- abstract PluginInitializer bindsPluginInitializerImpl(PluginInitializerImpl impl);
+ @Provides
+ @Singleton
+ static PluginInstance.Factory providesPluginInstanceFactory(
+ @Named(PLUGIN_PRIVILEGED) List<String> privilegedPlugins,
+ @Named(PLUGIN_DEBUG) boolean isDebug) {
+ return new PluginInstance.Factory(
+ PluginModule.class.getClassLoader(),
+ new PluginInstance.InstanceFactory<>(),
+ new PluginInstance.VersionChecker(),
+ privilegedPlugins,
+ isDebug);
+ }
@Provides
@Singleton
- static PluginInstanceManager.Factory providePluginInstanceManagerFactory(Context context,
+ static PluginActionManager.Factory providePluginInstanceManagerFactory(Context context,
PackageManager packageManager, @Main Executor mainExecutor,
- @Named(PLUGIN_THREAD) Executor pluginExecutor, PluginInitializer initializer,
+ @Named(PLUGIN_THREAD) Executor pluginExecutor,
NotificationManager notificationManager, PluginEnabler pluginEnabler,
- @Named(PLUGIN_PRIVILEGED) List<String> privilegedPlugins) {
- return new PluginInstanceManager.Factory(
- context, packageManager, mainExecutor, pluginExecutor, initializer,
- notificationManager, pluginEnabler, privilegedPlugins);
+ @Named(PLUGIN_PRIVILEGED) List<String> privilegedPlugins,
+ PluginInstance.Factory pluginInstanceFactory) {
+ return new PluginActionManager.Factory(
+ context, packageManager, mainExecutor, pluginExecutor,
+ notificationManager, pluginEnabler, privilegedPlugins, pluginInstanceFactory);
}
@Provides
@@ -91,7 +104,7 @@
@Provides
static PluginManager providesPluginManager(
Context context,
- PluginInstanceManager.Factory instanceManagerFactory,
+ PluginActionManager.Factory instanceManagerFactory,
@Named(PLUGIN_DEBUG) boolean debug,
@Named(PRE_HANDLER)
Optional<Thread.UncaughtExceptionHandler> uncaughtExceptionHandlerOptional,
@@ -110,7 +123,7 @@
@Provides
@Named(PLUGIN_PRIVILEGED)
- static List<String> providesPrivilegedPlugins(PluginInitializer initializer, Context context) {
- return Arrays.asList(initializer.getPrivilegedPlugins(context));
+ static List<String> providesPrivilegedPlugins(Context context) {
+ return Arrays.asList(context.getResources().getStringArray(R.array.config_pluginWhitelist));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index eff34d8..0196769 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -39,6 +39,7 @@
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
@@ -96,6 +97,7 @@
private final UiEventLogger mUiEventLogger;
private final InstanceIdSequence mInstanceIdSequence;
private final CustomTileStatePersister mCustomTileStatePersister;
+ private final FeatureFlags mFeatureFlags;
private final List<Callback> mCallbacks = new ArrayList<>();
private AutoTileManager mAutoTiles;
@@ -126,7 +128,8 @@
UserTracker userTracker,
SecureSettings secureSettings,
CustomTileStatePersister customTileStatePersister,
- TileServiceRequestController.Builder tileServiceRequestControllerBuilder
+ TileServiceRequestController.Builder tileServiceRequestControllerBuilder,
+ FeatureFlags featureFlags
) {
mIconController = iconController;
mContext = context;
@@ -149,6 +152,7 @@
mUserTracker = userTracker;
mSecureSettings = secureSettings;
mCustomTileStatePersister = customTileStatePersister;
+ mFeatureFlags = featureFlags;
mainHandler.post(() -> {
// This is technically a hack to avoid circular dependency of
@@ -272,7 +276,7 @@
if (newValue == null && UserManager.isDeviceInDemoMode(mContext)) {
newValue = mContext.getResources().getString(R.string.quick_settings_tiles_retail_mode);
}
- final List<String> tileSpecs = loadTileSpecs(mContext, newValue);
+ final List<String> tileSpecs = loadTileSpecs(mContext, newValue, mFeatureFlags);
int currentUser = mUserTracker.getUserId();
if (currentUser != mCurrentUser) {
mUserContext = mUserTracker.getUserContext();
@@ -341,7 +345,7 @@
if (newTiles.isEmpty() && !tileSpecs.isEmpty()) {
// If we didn't manage to create any tiles, set it to empty (default)
Log.d(TAG, "No valid tiles on tuning changed. Setting to default.");
- changeTiles(currentSpecs, loadTileSpecs(mContext, ""));
+ changeTiles(currentSpecs, loadTileSpecs(mContext, "", mFeatureFlags));
} else {
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).onTilesChanged();
@@ -409,7 +413,7 @@
private void changeTileSpecs(Predicate<List<String>> changeFunction) {
final String setting = mSecureSettings.getStringForUser(TILES_SETTING, mCurrentUser);
- final List<String> tileSpecs = loadTileSpecs(mContext, setting);
+ final List<String> tileSpecs = loadTileSpecs(mContext, setting, mFeatureFlags);
if (changeFunction.test(tileSpecs)) {
saveTilesToSettings(tileSpecs);
}
@@ -498,7 +502,8 @@
throw new RuntimeException("Default factory didn't create view for " + tile.getTileSpec());
}
- protected static List<String> loadTileSpecs(Context context, String tileList) {
+ protected static List<String> loadTileSpecs(
+ Context context, String tileList, FeatureFlags featureFlags) {
final Resources res = context.getResources();
if (TextUtils.isEmpty(tileList)) {
@@ -531,6 +536,21 @@
}
}
}
+ if (featureFlags.isProviderModelSettingEnabled()) {
+ if (!tiles.contains("internet")) {
+ if (tiles.contains("wifi")) {
+ // Replace the WiFi with Internet, and remove the Cell
+ tiles.set(tiles.indexOf("wifi"), "internet");
+ tiles.remove("cell");
+ } else if (tiles.contains("cell")) {
+ // Replace the Cell with Internet
+ tiles.set(tiles.indexOf("cell"), "internet");
+ }
+ } else {
+ tiles.remove("wifi");
+ tiles.remove("cell");
+ }
+ }
return tiles;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index d33982c..e6ab436 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -116,6 +116,7 @@
*/
void show(int x, int y, TileAdapter tileAdapter) {
if (!isShown) {
+ mRecyclerView.getLayoutManager().scrollToPosition(0);
int[] containerLocation = findViewById(R.id.customize_container).getLocationOnScreen();
mX = x - containerLocation[0];
mY = y - containerLocation[1];
@@ -131,6 +132,7 @@
void showImmediately() {
if (!isShown) {
+ mRecyclerView.getLayoutManager().scrollToPosition(0);
setVisibility(VISIBLE);
mClipper.cancelAnimator();
mClipper.showBackground();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 3c2f35b..993bbd0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -34,6 +34,7 @@
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
import com.android.systemui.qs.QSTileHost;
@@ -62,6 +63,7 @@
private final Executor mBgExecutor;
private final Context mContext;
private final UserTracker mUserTracker;
+ private final FeatureFlags mFeatureFlags;
private TileStateListener mListener;
private boolean mFinished;
@@ -71,12 +73,14 @@
Context context,
UserTracker userTracker,
@Main Executor mainExecutor,
- @Background Executor bgExecutor
+ @Background Executor bgExecutor,
+ FeatureFlags featureFlags
) {
mContext = context;
mMainExecutor = mainExecutor;
mBgExecutor = bgExecutor;
mUserTracker = userTracker;
+ mFeatureFlags = featureFlags;
}
public void setListener(TileStateListener listener) {
@@ -117,6 +121,10 @@
}
final ArrayList<QSTile> tilesToAdd = new ArrayList<>();
+ if (mFeatureFlags.isProviderModelSettingEnabled()) {
+ possibleTiles.remove("cell");
+ possibleTiles.remove("wifi");
+ }
for (String spec : possibleTiles) {
// Only add current and stock tiles that can be created from QSFactoryImpl.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index d262412..e6612fe 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -329,7 +329,8 @@
filter.addDataScheme("package");
try {
mPackageReceiverRegistered.set(true);
- mContext.registerReceiverAsUser(this, mUser, filter, null, mHandler);
+ mContext.registerReceiverAsUser(
+ this, mUser, filter, null, mHandler, Context.RECEIVER_EXPORTED);
} catch (Exception ex) {
mPackageReceiverRegistered.set(false);
Log.e(TAG, "Could not register package receiver", ex);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 7e76e57..fda755b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -92,7 +92,7 @@
filter.addDataScheme("package");
Context context = mServices.getContext();
context.registerReceiverAsUser(mUninstallReceiver, userTracker.getUserHandle(), filter,
- null, mHandler);
+ null, mHandler, Context.RECEIVER_EXPORTED);
}
boolean isLifecycleStarted() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DisableFlagsLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/DisableFlagsLogger.kt
new file mode 100644
index 0000000..cf34db2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DisableFlagsLogger.kt
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar
+
+import android.app.StatusBarManager.DISABLE_BACK
+import android.app.StatusBarManager.DISABLE_CLOCK
+import android.app.StatusBarManager.DISABLE_EXPAND
+import android.app.StatusBarManager.DISABLE_HOME
+import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS
+import android.app.StatusBarManager.DISABLE_NOTIFICATION_ALERTS
+import android.app.StatusBarManager.DISABLE_ONGOING_CALL_CHIP
+import android.app.StatusBarManager.DISABLE_RECENT
+import android.app.StatusBarManager.DISABLE_SEARCH
+import android.app.StatusBarManager.DISABLE_SYSTEM_INFO
+import android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS
+import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE
+import android.app.StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS
+import android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS
+import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+
+/**
+ * A singleton that creates concise but readable strings representing the values of the disable
+ * flags for debugging.
+ *
+ * See [CommandQueue.disable] for information about disable flags.
+ *
+ * Note that, for both lists passed in, each flag must have a distinct [DisableFlag.flagIsSetSymbol]
+ * and distinct [DisableFlag.flagNotSetSymbol] within the list. If this isn't true, the logs could
+ * be ambiguous so an [IllegalArgumentException] is thrown.
+ */
+@SysUISingleton
+class DisableFlagsLogger constructor(
+ private val disable1FlagsList: List<DisableFlag>,
+ private val disable2FlagsList: List<DisableFlag>
+) {
+
+ @Inject
+ constructor() : this(defaultDisable1FlagsList, defaultDisable2FlagsList)
+
+ init {
+ if (flagsListHasDuplicateSymbols(disable1FlagsList)) {
+ throw IllegalArgumentException("disable1 flags must have unique symbols")
+ }
+ if (flagsListHasDuplicateSymbols(disable2FlagsList)) {
+ throw IllegalArgumentException("disable2 flags must have unique symbols")
+ }
+ }
+
+ private fun flagsListHasDuplicateSymbols(list: List<DisableFlag>): Boolean {
+ val numDistinctFlagOffStatus = list.map { it.getFlagStatus(0) }.distinct().count()
+ val numDistinctFlagOnStatus = list
+ .map { it.getFlagStatus(Int.MAX_VALUE) }
+ .distinct()
+ .count()
+ return numDistinctFlagOffStatus < list.count() || numDistinctFlagOnStatus < list.count()
+ }
+
+ /**
+ * Returns a string representing the, old, new, and new-after-modification disable flag states,
+ * as well as the differences between each of the states.
+ *
+ * Example:
+ * Old: EnaiHbcRso.qINgr | New: EnaihBcRso.qiNGR (hB.iGR) | New after local modification:
+ * EnaihBcRso.qInGR (.n)
+ *
+ * A capital character signifies the flag is set and a lowercase character signifies that the
+ * flag isn't set. The flag states will be logged in the same order as the passed-in lists.
+ *
+ * The difference between states is written between parentheses, and won't be included if there
+ * is no difference. the new-after-modification state also won't be included if there's no
+ * difference from the new state.
+ *
+ * @param old the disable state that had been previously sent.
+ * @param new the new disable state that has just been sent.
+ * @param newAfterLocalModification the new disable states after a class has locally modified
+ * them. Null if the class does not locally modify.
+ */
+ fun getDisableFlagsString(
+ old: DisableState,
+ new: DisableState,
+ newAfterLocalModification: DisableState? = null
+ ): String {
+ val builder = StringBuilder("Received new disable state. ")
+ builder.append("Old: ")
+ builder.append(getFlagsString(old))
+ builder.append(" | New: ")
+ if (old != new) {
+ builder.append(getFlagsStringWithDiff(old, new))
+ } else {
+ builder.append(getFlagsString(old))
+ }
+
+ if (newAfterLocalModification != null && new != newAfterLocalModification) {
+ builder.append(" | New after local modification: ")
+ builder.append(getFlagsStringWithDiff(new, newAfterLocalModification))
+ }
+
+ return builder.toString()
+ }
+
+ /**
+ * Returns a string representing [new] state, as well as the difference from [old] to [new]
+ * (if there is one).
+ */
+ private fun getFlagsStringWithDiff(old: DisableState, new: DisableState): String {
+ val builder = StringBuilder()
+ builder.append(getFlagsString(new))
+ builder.append(" ")
+ builder.append(getDiffString(old, new))
+ return builder.toString()
+ }
+
+ /**
+ * Returns a string representing the difference between [old] and [new], or an empty string if
+ * there is no difference.
+ *
+ * For example, if old was "abc.DE" and new was "aBC.De", the difference returned would be
+ * "(BC.e)".
+ */
+ private fun getDiffString(old: DisableState, new: DisableState): String {
+ if (old == new) {
+ return ""
+ }
+
+ val builder = StringBuilder("(")
+ disable1FlagsList.forEach {
+ val newSymbol = it.getFlagStatus(new.disable1)
+ if (it.getFlagStatus(old.disable1) != newSymbol) {
+ builder.append(newSymbol)
+ }
+ }
+ builder.append(".")
+ disable2FlagsList.forEach {
+ val newSymbol = it.getFlagStatus(new.disable2)
+ if (it.getFlagStatus(old.disable2) != newSymbol) {
+ builder.append(newSymbol)
+ }
+ }
+ builder.append(")")
+ return builder.toString()
+ }
+
+ /** Returns a string representing the disable flag states, e.g. "EnaihBcRso.qiNGR". */
+ private fun getFlagsString(state: DisableState): String {
+ val builder = StringBuilder("")
+ disable1FlagsList.forEach { builder.append(it.getFlagStatus(state.disable1)) }
+ builder.append(".")
+ disable2FlagsList.forEach { builder.append(it.getFlagStatus(state.disable2)) }
+ return builder.toString()
+ }
+
+ /** A POJO representing each disable flag. */
+ class DisableFlag(
+ private val bitMask: Int,
+ private val flagIsSetSymbol: Char,
+ private val flagNotSetSymbol: Char
+ ) {
+
+ /**
+ * Returns a character representing whether or not this flag is set in [state].
+ *
+ * A capital character signifies the flag is set and a lowercase character signifies that
+ * the flag isn't set.
+ */
+ internal fun getFlagStatus(state: Int): Char =
+ if (0 != state and this.bitMask) this.flagIsSetSymbol
+ else this.flagNotSetSymbol
+ }
+
+ /** POJO to hold [disable1] and [disable2]. */
+ data class DisableState(val disable1: Int, val disable2: Int)
+}
+
+// LINT.IfChange
+private val defaultDisable1FlagsList: List<DisableFlagsLogger.DisableFlag> = listOf(
+ DisableFlagsLogger.DisableFlag(DISABLE_EXPAND, 'E', 'e'),
+ DisableFlagsLogger.DisableFlag(DISABLE_NOTIFICATION_ICONS, 'N', 'n'),
+ DisableFlagsLogger.DisableFlag(DISABLE_NOTIFICATION_ALERTS, 'A', 'a'),
+ DisableFlagsLogger.DisableFlag(DISABLE_SYSTEM_INFO, 'I', 'i'),
+ DisableFlagsLogger.DisableFlag(DISABLE_HOME, 'H', 'h'),
+ DisableFlagsLogger.DisableFlag(DISABLE_BACK, 'B', 'b'),
+ DisableFlagsLogger.DisableFlag(DISABLE_CLOCK, 'C', 'c'),
+ DisableFlagsLogger.DisableFlag(DISABLE_RECENT, 'R', 'r'),
+ DisableFlagsLogger.DisableFlag(DISABLE_SEARCH, 'S', 's'),
+ DisableFlagsLogger.DisableFlag(DISABLE_ONGOING_CALL_CHIP, 'O', 'o')
+)
+
+private val defaultDisable2FlagsList: List<DisableFlagsLogger.DisableFlag> = listOf(
+ DisableFlagsLogger.DisableFlag(DISABLE2_QUICK_SETTINGS, 'Q', 'q'),
+ DisableFlagsLogger.DisableFlag(DISABLE2_SYSTEM_ICONS, 'I', 'i'),
+ DisableFlagsLogger.DisableFlag(DISABLE2_NOTIFICATION_SHADE, 'N', 'n'),
+ DisableFlagsLogger.DisableFlag(DISABLE2_GLOBAL_ACTIONS, 'G', 'g'),
+ DisableFlagsLogger.DisableFlag(DISABLE2_ROTATE_SUGGESTIONS, 'R', 'r')
+)
+// LINT.ThenChange(frameworks/base/core/java/android/app/StatusBarManager.java)
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index e845804..2a8771e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -78,7 +78,8 @@
private var keyguardAnimator: Animator? = null
private var notificationAnimator: Animator? = null
private var updateScheduled: Boolean = false
- private var shadeExpansion = 0f
+ @VisibleForTesting
+ var shadeExpansion = 0f
private var isClosed: Boolean = true
private var isOpen: Boolean = false
private var isBlurred: Boolean = false
@@ -92,6 +93,9 @@
// Only for dumpsys
private var lastAppliedBlur = 0
+ // Shade expansion offset that happens when pulling down on a HUN.
+ var panelPullDownMinFraction = 0f
+
var shadeAnimation = DepthAnimation()
@VisibleForTesting
@@ -312,8 +316,10 @@
/**
* Update blurs when pulling down the shade
*/
- override fun onPanelExpansionChanged(expansion: Float, tracking: Boolean) {
+ override fun onPanelExpansionChanged(rawExpansion: Float, tracking: Boolean) {
val timestamp = SystemClock.elapsedRealtimeNanos()
+ val expansion = MathUtils.saturate(
+ (rawExpansion - panelPullDownMinFraction) / (1f - panelPullDownMinFraction))
if (shadeExpansion == expansion && prevTracking == tracking) {
prevTimestamp = timestamp
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt b/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt
index 146046b..5175977 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt
@@ -147,8 +147,12 @@
val fadeIn = subProgress(0f, 0.1f, value)
val fadeOutNoise = subProgress(0.4f, 1f, value)
- val fadeOutRipple = subProgress(0.3f, 1f, value)
- val fadeCircle = subProgress(0f, 0.2f, value)
+ var fadeOutRipple = 0f
+ var fadeCircle = 0f
+ if (shouldFadeOutRipple) {
+ fadeCircle = subProgress(0f, 0.2f, value)
+ fadeOutRipple = subProgress(0.3f, 1f, value)
+ }
setUniform("in_fadeSparkle", Math.min(fadeIn, 1 - fadeOutNoise))
setUniform("in_fadeCircle", 1 - fadeCircle)
setUniform("in_fadeRing", Math.min(fadeIn, 1 - fadeOutRipple))
@@ -200,4 +204,6 @@
field = value
setUniform("in_pixelDensity", value)
}
+
+ var shouldFadeOutRipple: Boolean = true
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
index f0eb084..efec94f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
@@ -48,7 +48,9 @@
val sectioner = object : NotifSectioner("People") {
override fun isInSection(entry: ListEntry): Boolean =
isConversation(entry.representativeEntry!!)
- override fun getHeaderNodeController() = peopleHeaderController
+ override fun getHeaderNodeController() =
+ // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and peopleHeaderController
+ if (RankingCoordinator.SHOW_ALL_SECTIONS) peopleHeaderController else null
}
override fun attach(pipeline: NotifPipeline) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
index 6e98c27..1bde312 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
@@ -205,7 +205,11 @@
@Nullable
@Override
public NodeController getHeaderNodeController() {
- return mIncomingHeaderController;
+ // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and mIncomingHeaderController
+ if (RankingCoordinator.SHOW_ALL_SECTIONS) {
+ return mIncomingHeaderController;
+ }
+ return null;
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
index 6da4d8b..d556e97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
@@ -41,6 +41,7 @@
*/
@SysUISingleton
public class RankingCoordinator implements Coordinator {
+ public static final boolean SHOW_ALL_SECTIONS = false;
private final StatusBarStateController mStatusBarStateController;
private final HighPriorityProvider mHighPriorityProvider;
private final NodeController mSilentHeaderController;
@@ -83,7 +84,11 @@
@Nullable
@Override
public NodeController getHeaderNodeController() {
- return mAlertingHeaderController;
+ // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and mAlertingHeaderController
+ if (SHOW_ALL_SECTIONS) {
+ return mAlertingHeaderController;
+ }
+ return null;
}
};
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 0d8e850..e956046 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
@@ -3201,13 +3201,6 @@
}
}
- /** Sets whether dismiss gestures are right-to-left (instead of left-to-right). */
- public void setDismissRtl(boolean dismissRtl) {
- if (mMenuRow != null) {
- mMenuRow.setDismissRtl(dismissRtl);
- }
- }
-
private static class NotificationViewState extends ExpandableViewState {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index c3dc700..b7d721e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -82,7 +82,6 @@
private ArrayList<MenuItem> mRightMenuItems;
private final Map<View, MenuItem> mMenuItemsByView = new ArrayMap<>();
private OnMenuEventListener mMenuListener;
- private boolean mDismissRtl;
private ValueAnimator mFadeAnimator;
private boolean mAnimating;
@@ -787,14 +786,6 @@
return getParent().canViewBeDismissed();
}
- @Override
- public void setDismissRtl(boolean dismissRtl) {
- mDismissRtl = dismissRtl;
- if (mMenuContainer != null) {
- createMenuViews(true);
- }
- }
-
public static class NotificationMenuItem implements MenuItem {
View mMenuView;
GutsContent mGutsContent;
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 3d72ae7..2ecf8e9 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
@@ -163,7 +163,6 @@
private final Paint mBackgroundPaint = new Paint();
private final boolean mShouldDrawNotificationBackground;
private boolean mHighPriorityBeforeSpeedBump;
- private boolean mDismissRtl;
private float mExpandedHeight;
private int mOwnScrollY;
@@ -620,16 +619,6 @@
addView(mFgsSectionView, -1);
}
- void updateDismissRtlSetting(boolean dismissRtl) {
- mDismissRtl = dismissRtl;
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child instanceof ExpandableNotificationRow) {
- ((ExpandableNotificationRow) child).setDismissRtl(dismissRtl);
- }
- }
- }
-
/**
* Set the overexpansion of the panel to be applied to the view.
*/
@@ -2918,7 +2907,6 @@
updateChronometerForChild(child);
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- row.setDismissRtl(mDismissRtl);
row.setDismissUsingRowTranslationX(mDismissUsingRowTranslationX);
}
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 f1ae3da..830d3b9 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
@@ -762,9 +762,6 @@
mTunerService.addTunable(
(key, newValue) -> {
switch (key) {
- case Settings.Secure.NOTIFICATION_DISMISS_RTL:
- mView.updateDismissRtlSetting("1".equals(newValue));
- break;
case Settings.Secure.NOTIFICATION_HISTORY_ENABLED:
updateFooter();
break;
@@ -774,7 +771,6 @@
}
},
HIGH_PRIORITY,
- Settings.Secure.NOTIFICATION_DISMISS_RTL,
Settings.Secure.NOTIFICATION_HISTORY_ENABLED);
mKeyguardMediaController.setVisibilityChangedListener(visible -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index df4bbcf..5f44a7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -73,7 +73,8 @@
private final UserManager mUserManager;
private int mSystemIconsSwitcherHiddenExpandedMargin;
- private int mSystemIconsBaseMargin;
+ private int mStatusBarPaddingEnd;
+ private int mMinDotWidth;
private View mSystemIconsContainer;
private View mCutoutSpace;
@@ -118,6 +119,7 @@
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
+ loadDimens();
MarginLayoutParams lp = (MarginLayoutParams) mMultiUserAvatar.getLayoutParams();
lp.width = lp.height = getResources().getDimensionPixelSize(
@@ -125,14 +127,23 @@
mMultiUserAvatar.setLayoutParams(lp);
// System icons
- lp = (MarginLayoutParams) mSystemIconsContainer.getLayoutParams();
- lp.setMarginStart(getResources().getDimensionPixelSize(
- R.dimen.system_icons_super_container_margin_start));
- mSystemIconsContainer.setLayoutParams(lp);
- mSystemIconsContainer.setPaddingRelative(mSystemIconsContainer.getPaddingStart(),
- mSystemIconsContainer.getPaddingTop(),
- getResources().getDimensionPixelSize(R.dimen.system_icons_keyguard_padding_end),
- mSystemIconsContainer.getPaddingBottom());
+ updateSystemIconsLayoutParams();
+
+ // mStatusIconArea
+ mStatusIconArea.setPaddingRelative(
+ mStatusIconArea.getPaddingStart(),
+ getResources().getDimensionPixelSize(R.dimen.status_bar_padding_top),
+ mStatusIconArea.getPaddingEnd(),
+ mStatusIconArea.getPaddingBottom()
+ );
+
+ // mStatusIconContainer
+ mStatusIconContainer.setPaddingRelative(
+ mStatusIconContainer.getPaddingStart(),
+ mStatusIconContainer.getPaddingTop(),
+ getResources().getDimensionPixelSize(R.dimen.signal_cluster_battery_padding),
+ mStatusIconContainer.getPaddingBottom()
+ );
// Respect font size setting.
mCarrierLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX,
@@ -162,8 +173,10 @@
Resources res = getResources();
mSystemIconsSwitcherHiddenExpandedMargin = res.getDimensionPixelSize(
R.dimen.system_icons_switcher_hidden_expanded_margin);
- mSystemIconsBaseMargin = res.getDimensionPixelSize(
- R.dimen.system_icons_super_container_avatarless_margin_end);
+ mStatusBarPaddingEnd = res.getDimensionPixelSize(
+ R.dimen.status_bar_padding_end);
+ mMinDotWidth = res.getDimensionPixelSize(
+ R.dimen.ongoing_appops_dot_min_padding);
mCutoutSideNudge = getResources().getDimensionPixelSize(
R.dimen.display_cutout_margin_consumption);
mShowPercentAvailable = getContext().getResources().getBoolean(
@@ -203,16 +216,24 @@
private void updateSystemIconsLayoutParams() {
LinearLayout.LayoutParams lp =
(LinearLayout.LayoutParams) mSystemIconsContainer.getLayoutParams();
- // If the avatar icon is gone, we need to have some end margin to display the system icons
- // correctly.
- int baseMarginEnd = mMultiUserAvatar.getVisibility() == View.GONE
- ? mSystemIconsBaseMargin
- : 0;
+
+ int marginStart = getResources().getDimensionPixelSize(
+ R.dimen.system_icons_super_container_margin_start);
+
+ // Use status_bar_padding_end to replace original
+ // system_icons_super_container_avatarless_margin_end to prevent different end alignment
+ // between PhoneStatusBarView and KeyguardStatusBarView
+ int baseMarginEnd = mStatusBarPaddingEnd;
int marginEnd =
mKeyguardUserSwitcherEnabled ? mSystemIconsSwitcherHiddenExpandedMargin
: baseMarginEnd;
- marginEnd = calculateMargin(marginEnd, mPadding.second);
- if (marginEnd != lp.getMarginEnd()) {
+
+ // Align PhoneStatusBar right margin/padding, only use
+ // 1. status bar layout: mPadding(consider round_corner + privacy dot)
+ // 2. icon container: R.dimen.status_bar_padding_end
+
+ if (marginEnd != lp.getMarginEnd() || marginStart != lp.getMarginStart()) {
+ lp.setMarginStart(marginStart);
lp.setMarginEnd(marginEnd);
mSystemIconsContainer.setLayoutParams(lp);
}
@@ -247,7 +268,13 @@
mPadding =
StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner(
mDisplayCutout, cornerCutoutMargins, mRoundedCornerPadding);
- setPadding(mPadding.first, waterfallTop, mPadding.second, 0);
+
+ // consider privacy dot space
+ final int minLeft = isLayoutRtl() ? Math.max(mMinDotWidth, mPadding.first) : mPadding.first;
+ final int minRight = isLayoutRtl() ? mPadding.second :
+ Math.max(mMinDotWidth, mPadding.second);
+
+ setPadding(minLeft, waterfallTop, minRight, 0);
}
private boolean updateLayoutParamsNoCutout() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 51eb496..abee7a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -225,19 +225,19 @@
}
}
+ // If no one is light, all icons become white.
+ if (numLightStacks == 0) {
+ mStatusBarIconController.getTransitionsController().setIconsDark(
+ false, animateChange());
+ }
+
// If all stacks are light, all icons get dark.
- if (numLightStacks == numStacks) {
+ else if (numLightStacks == numStacks) {
mStatusBarIconController.setIconsDarkArea(null);
mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
}
- // If no one is light, all icons become white.
- else if (numLightStacks == 0) {
- mStatusBarIconController.getTransitionsController().setIconsDark(
- false, animateChange());
- }
-
// Not the same for every stack, magic!
else {
mStatusBarIconController.setIconsDarkArea(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 2c95ae4..3aca18e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -630,6 +630,7 @@
private int mQsClipBottom;
private boolean mQsVisible;
private final ContentResolver mContentResolver;
+ private float mMinFraction;
private final Executor mUiExecutor;
private final SecureSettings mSecureSettings;
@@ -1920,6 +1921,15 @@
return !mQsTouchAboveFalsingThreshold;
}
+ /**
+ * Percentage of panel expansion offset, caused by pulling down on a heads-up.
+ */
+ @Override
+ public void setMinFraction(float minFraction) {
+ mMinFraction = minFraction;
+ mDepthController.setPanelPullDownMinFraction(mMinFraction);
+ }
+
private float computeQsExpansionFraction() {
if (mQSAnimatingHiddenFromCollapsed) {
// When hiding QS from collapsed state, the expansion can sometimes temporarily
@@ -2393,6 +2403,12 @@
}
}
top += mOverStretchAmount;
+ // Correction for instant expansion caused by HUN pull down/
+ if (mMinFraction > 0f && mMinFraction < 1f) {
+ float realFraction =
+ (getExpandedFraction() - mMinFraction) / (1f - mMinFraction);
+ top *= MathUtils.saturate(realFraction / mMinFraction);
+ }
bottom = getView().getBottom();
// notification bounds should take full screen width regardless of insets
left = 0;
@@ -3465,7 +3481,7 @@
}
public void setPanelScrimMinFraction(float minFraction) {
- mBar.panelScrimMinFractionChanged(minFraction);
+ mBar.onPanelMinFractionChanged(minFraction);
}
public void clearNotificationEffects() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index f1b6c7c..eca91a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -18,6 +18,7 @@
import static java.lang.Float.isNaN;
+import android.annotation.CallSuper;
import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
@@ -162,7 +163,13 @@
return mPanel == null || mPanel.getView().dispatchTouchEvent(event);
}
- public abstract void panelScrimMinFractionChanged(float minFraction);
+ /**
+ * Percentage of panel expansion offset, caused by pulling down on a heads-up.
+ */
+ @CallSuper
+ public void onPanelMinFractionChanged(float minFraction) {
+ mPanel.setMinFraction(minFraction);
+ }
/**
* @param frac the fraction from the expansion in [0, 1]
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index a3877b0..51cae8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -340,6 +340,13 @@
protected abstract float getOpeningHeight();
/**
+ * Minimum fraction from where expansion should start. This is set when pulling down on a
+ * heads-up notification.
+ * @param minFraction Fraction from 0 to 1.
+ */
+ public abstract void setMinFraction(float minFraction);
+
+ /**
* @return whether the swiping direction is upwards and above a 45 degree angle compared to the
* horizontal direction
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 88a823c..a09b30f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -273,10 +273,11 @@
}
@Override
- public void panelScrimMinFractionChanged(float minFraction) {
+ public void onPanelMinFractionChanged(float minFraction) {
if (isNaN(minFraction)) {
throw new IllegalArgumentException("minFraction cannot be NaN");
}
+ super.onPanelMinFractionChanged(minFraction);
if (mMinFraction != minFraction) {
mMinFraction = minFraction;
updateScrimFraction();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.java
deleted file mode 100644
index b36b67d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.util.ViewController;
-
-/** Controller for {@link PhoneStatusBarView}. */
-public class PhoneStatusBarViewController extends ViewController<PhoneStatusBarView> {
-
- protected PhoneStatusBarViewController(
- PhoneStatusBarView view,
- CommandQueue commandQueue) {
- super(view);
- mView.setPanelEnabledProvider(commandQueue::panelsEnabled);
- }
-
- @Override
- protected void onViewAttached() {
- }
-
- @Override
- protected void onViewDetached() {
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
new file mode 100644
index 0000000..9799533
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.phone
+
+import android.graphics.Point
+import android.view.View
+import android.view.ViewGroup
+import com.android.systemui.R
+import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
+import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.util.ViewController
+
+/** Controller for [PhoneStatusBarView]. */
+class PhoneStatusBarViewController(
+ view: PhoneStatusBarView,
+ commandQueue: CommandQueue,
+ statusBarMoveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?
+) : ViewController<PhoneStatusBarView>(view) {
+
+ override fun onViewAttached() {}
+ override fun onViewDetached() {}
+
+ init {
+ mView.setPanelEnabledProvider {
+ commandQueue.panelsEnabled()
+ }
+
+ statusBarMoveFromCenterAnimationController?.let { animationController ->
+ val statusBarLeftSide: View = mView.findViewById(R.id.status_bar_left_side)
+ val systemIconArea: ViewGroup = mView.findViewById(R.id.system_icon_area)
+
+ val viewCenterProvider = StatusBarViewsCenterProvider()
+ val viewsToAnimate = arrayOf(
+ statusBarLeftSide,
+ systemIconArea
+ )
+
+ animationController.init(viewsToAnimate, viewCenterProvider)
+
+ mView.addOnLayoutChangeListener { _, left, _, right, _, oldLeft, _, oldRight, _ ->
+ val widthChanged = right - left != oldRight - oldLeft
+ if (widthChanged) {
+ statusBarMoveFromCenterAnimationController.onStatusBarWidthChanged()
+ }
+ }
+ }
+ }
+
+ private class StatusBarViewsCenterProvider : UnfoldMoveFromCenterAnimator.ViewCenterProvider {
+ override fun getViewCenter(view: View, outPoint: Point) =
+ when (view.id) {
+ R.id.status_bar_left_side -> {
+ // items aligned to the start, return start center point
+ getViewEdgeCenter(view, outPoint, isStart = true)
+ }
+ R.id.system_icon_area -> {
+ // items aligned to the end, return end center point
+ getViewEdgeCenter(view, outPoint, isStart = false)
+ }
+ else -> super.getViewCenter(view, outPoint)
+ }
+
+ /**
+ * Returns start or end (based on [isStart]) center point of the view
+ */
+ private fun getViewEdgeCenter(view: View, outPoint: Point, isStart: Boolean) {
+ val isRtl = view.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL
+ val isLeftEdge = isRtl xor isStart
+
+ val viewLocation = IntArray(2)
+ view.getLocationOnScreen(viewLocation)
+
+ val viewX = viewLocation[0]
+ val viewY = viewLocation[1]
+
+ outPoint.x = viewX + if (isLeftEdge) view.height / 2 else view.width - view.height / 2
+ outPoint.y = viewY + view.height / 2
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 575a3c4..304b2a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -536,6 +536,7 @@
private final FeatureFlags mFeatureFlags;
private final UnfoldTransitionConfig mUnfoldTransitionConfig;
private final Lazy<UnfoldLightRevealOverlayAnimation> mUnfoldLightRevealOverlayAnimation;
+ private final Lazy<StatusBarMoveFromCenterAnimationController> mMoveFromCenterAnimation;
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private final MessageRouter mMessageRouter;
private final WallpaperManager mWallpaperManager;
@@ -768,6 +769,7 @@
BrightnessSlider.Factory brightnessSliderFactory,
UnfoldTransitionConfig unfoldTransitionConfig,
Lazy<UnfoldLightRevealOverlayAnimation> unfoldLightRevealOverlayAnimation,
+ Lazy<StatusBarMoveFromCenterAnimationController> statusBarUnfoldAnimationController,
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher,
@@ -860,6 +862,7 @@
mBrightnessSliderFactory = brightnessSliderFactory;
mUnfoldTransitionConfig = unfoldTransitionConfig;
mUnfoldLightRevealOverlayAnimation = unfoldLightRevealOverlayAnimation;
+ mMoveFromCenterAnimation = statusBarUnfoldAnimationController;
mOngoingCallController = ongoingCallController;
mAnimationScheduler = animationScheduler;
mStatusBarLocationPublisher = locationPublisher;
@@ -1141,8 +1144,13 @@
sendInitialExpansionAmount(listener);
}
+ StatusBarMoveFromCenterAnimationController moveFromCenterAnimation = null;
+ if (mUnfoldTransitionConfig.isEnabled()) {
+ moveFromCenterAnimation = mMoveFromCenterAnimation.get();
+ }
mPhoneStatusBarViewController =
- new PhoneStatusBarViewController(mStatusBarView, mCommandQueue);
+ new PhoneStatusBarViewController(mStatusBarView, mCommandQueue,
+ moveFromCenterAnimation);
mPhoneStatusBarViewController.init();
mBatteryMeterViewController = new BatteryMeterViewController(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
index 6a510c9..5301b25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
@@ -57,6 +57,7 @@
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.qs.QSPanelController;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.DisableFlagsLogger;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
@@ -98,6 +99,7 @@
private final VibratorHelper mVibratorHelper;
private final Optional<Vibrator> mVibratorOptional;
private final LightBarController mLightBarController;
+ private final DisableFlagsLogger mDisableFlagsLogger;
private final int mDisplayId;
private final boolean mVibrateOnOpening;
private final VibrationEffect mCameraLaunchGestureVibrationEffect;
@@ -134,6 +136,7 @@
VibratorHelper vibratorHelper,
Optional<Vibrator> vibratorOptional,
LightBarController lightBarController,
+ DisableFlagsLogger disableFlagsLogger,
@DisplayId int displayId) {
mStatusBar = statusBar;
@@ -159,6 +162,7 @@
mVibratorHelper = vibratorHelper;
mVibratorOptional = vibratorOptional;
mLightBarController = lightBarController;
+ mDisableFlagsLogger = disableFlagsLogger;
mDisplayId = displayId;
mVibrateOnOpening = resources.getBoolean(R.bool.config_vibrateOnIconAnimation);
@@ -267,7 +271,17 @@
if (displayId != mDisplayId) {
return;
}
+
+ int state2BeforeAdjustment = state2;
state2 = mRemoteInputQuickSettingsDisabler.adjustDisableFlags(state2);
+ Log.d(StatusBar.TAG,
+ mDisableFlagsLogger.getDisableFlagsString(
+ /* old= */ new DisableFlagsLogger.DisableState(
+ mStatusBar.getDisabled1(), mStatusBar.getDisabled2()),
+ /* new= */ new DisableFlagsLogger.DisableState(
+ state1, state2BeforeAdjustment),
+ /* newStateAfterLocalModification= */ new DisableFlagsLogger.DisableState(
+ state1, state2)));
final int old1 = mStatusBar.getDisabled1();
final int diff1 = state1 ^ old1;
@@ -277,43 +291,6 @@
final int diff2 = state2 ^ old2;
mStatusBar.setDisabled2(state2);
- if (StatusBar.DEBUG) {
- Log.d(StatusBar.TAG, String.format("disable1: 0x%08x -> 0x%08x (diff1: 0x%08x)",
- old1, state1, diff1));
- Log.d(StatusBar.TAG, String.format("disable2: 0x%08x -> 0x%08x (diff2: 0x%08x)",
- old2, state2, diff2));
- }
-
- StringBuilder flagdbg = new StringBuilder();
- flagdbg.append("disable<");
- flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_EXPAND)) ? 'E' : 'e');
- flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_EXPAND)) ? '!' : ' ');
- flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) ? 'I' : 'i');
- flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) ? '!' : ' ');
- flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS)) ? 'A' : 'a');
- flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS)) ? '!' : ' ');
- flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO)) ? 'S' : 's');
- flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO)) ? '!' : ' ');
- flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_BACK)) ? 'B' : 'b');
- flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_BACK)) ? '!' : ' ');
- flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_HOME)) ? 'H' : 'h');
- flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_HOME)) ? '!' : ' ');
- flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_RECENT)) ? 'R' : 'r');
- flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_RECENT)) ? '!' : ' ');
- flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_CLOCK)) ? 'C' : 'c');
- flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_CLOCK)) ? '!' : ' ');
- flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SEARCH)) ? 'S' : 's');
- flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_SEARCH)) ? '!' : ' ');
- flagdbg.append("> disable2<");
- flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? 'Q' : 'q');
- flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? '!' : ' ');
- flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? 'I' : 'i');
- flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? '!' : ' ');
- flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE)) ? 'N' : 'n');
- flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE)) ? '!' : ' ');
- flagdbg.append('>');
- Log.d(StatusBar.TAG, flagdbg.toString());
-
if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) {
if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) {
mShadeController.animateCollapsePanels();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 6a63156..88a7dc7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -114,6 +114,14 @@
}
}
+ private void refreshIconGroups() {
+ for (int i = mIconGroups.size() - 1; i >= 0; --i) {
+ IconManager group = mIconGroups.get(i);
+ removeIconGroup(group);
+ addIconGroup(group);
+ }
+ }
+
/** */
@Override
public void removeIconGroup(IconManager group) {
@@ -468,5 +476,6 @@
@Override
public void onDensityOrFontScaleChanged() {
loadDimens();
+ refreshIconGroups();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
new file mode 100644
index 0000000..8af03aa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.phone
+
+import android.view.View
+import android.view.WindowManager
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
+import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator.ViewCenterProvider
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import javax.inject.Inject
+
+@SysUISingleton
+class StatusBarMoveFromCenterAnimationController @Inject constructor(
+ private val unfoldTransitionProgressProvider: UnfoldTransitionProgressProvider,
+ private val windowManager: WindowManager
+) {
+
+ private lateinit var moveFromCenterAnimator: UnfoldMoveFromCenterAnimator
+
+ fun init(viewsToAnimate: Array<View>, viewCenterProvider: ViewCenterProvider) {
+ moveFromCenterAnimator = UnfoldMoveFromCenterAnimator(windowManager,
+ viewCenterProvider = viewCenterProvider)
+
+ unfoldTransitionProgressProvider.addCallback(object : TransitionProgressListener {
+ override fun onTransitionStarted() {
+ moveFromCenterAnimator.updateDisplayProperties()
+
+ viewsToAnimate.forEach {
+ moveFromCenterAnimator.registerViewForAnimation(it)
+ }
+ }
+
+ override fun onTransitionFinished() {
+ moveFromCenterAnimator.onTransitionFinished()
+ moveFromCenterAnimator.clearRegisteredViews()
+ }
+
+ override fun onTransitionProgress(progress: Float) {
+ moveFromCenterAnimator.onTransitionProgress(progress)
+ }
+ })
+ }
+
+ fun onStatusBarWidthChanged() {
+ moveFromCenterAnimator.updateViewPositions()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 63ee701..befea41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -90,6 +90,7 @@
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
+import com.android.systemui.statusbar.phone.StatusBarMoveFromCenterAnimationController;
import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
import com.android.systemui.statusbar.phone.StatusBarWindowView;
@@ -213,6 +214,7 @@
BrightnessSlider.Factory brightnessSliderFactory,
UnfoldTransitionConfig unfoldTransitionConfig,
Lazy<UnfoldLightRevealOverlayAnimation> unfoldLightRevealOverlayAnimation,
+ Lazy<StatusBarMoveFromCenterAnimationController> statusBarMoveFromCenterAnimation,
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher,
@@ -307,6 +309,7 @@
brightnessSliderFactory,
unfoldTransitionConfig,
unfoldLightRevealOverlayAnimation,
+ statusBarMoveFromCenterAnimation,
ongoingCallController,
animationScheduler,
locationPublisher,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 3490e15..675bbc4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -108,8 +108,6 @@
private Config mConfig;
@VisibleForTesting
boolean mInflateSignalStrengths = false;
- private MobileStatusTracker.Callback mCallback;
- private RegistrationCallback mRegistrationCallback;
private int mLastWwanLevel;
private int mLastWlanLevel;
private int mLastWlanCrossSimLevel;
@@ -121,6 +119,82 @@
// Where to copy the next state into.
private int mMobileStatusHistoryIndex;
+ private final MobileStatusTracker.Callback mMobileCallback =
+ new MobileStatusTracker.Callback() {
+ private String mLastStatus;
+
+ @Override
+ public void onMobileStatusChanged(boolean updateTelephony,
+ MobileStatus mobileStatus) {
+ if (Log.isLoggable(mTag, Log.DEBUG)) {
+ Log.d(mTag, "onMobileStatusChanged="
+ + " updateTelephony=" + updateTelephony
+ + " mobileStatus=" + mobileStatus.toString());
+ }
+ String currentStatus = mobileStatus.toString();
+ if (!currentStatus.equals(mLastStatus)) {
+ mLastStatus = currentStatus;
+ String status = new StringBuilder()
+ .append(SSDF.format(System.currentTimeMillis())).append(",")
+ .append(currentStatus)
+ .toString();
+ recordLastMobileStatus(status);
+ }
+ updateMobileStatus(mobileStatus);
+ if (updateTelephony) {
+ updateTelephony();
+ } else {
+ notifyListenersIfNecessary();
+ }
+ }
+ };
+
+ private final RegistrationCallback mRegistrationCallback = new RegistrationCallback() {
+ @Override
+ public void onRegistered(ImsRegistrationAttributes attributes) {
+ Log.d(mTag, "onRegistered: " + "attributes=" + attributes);
+ int imsTransportType = attributes.getTransportType();
+ int registrationAttributes = attributes.getAttributeFlags();
+ if (imsTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
+ mImsType = IMS_TYPE_WWAN;
+ IconState statusIcon = new IconState(
+ true,
+ getCallStrengthIcon(mLastWwanLevel, /* isWifi= */false),
+ getCallStrengthDescription(mLastWwanLevel, /* isWifi= */false));
+ notifyCallStateChange(statusIcon, mSubscriptionInfo.getSubscriptionId());
+ } else if (imsTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
+ if (registrationAttributes == 0) {
+ mImsType = IMS_TYPE_WLAN;
+ IconState statusIcon = new IconState(
+ true,
+ getCallStrengthIcon(mLastWlanLevel, /* isWifi= */true),
+ getCallStrengthDescription(mLastWlanLevel, /* isWifi= */true));
+ notifyCallStateChange(statusIcon, mSubscriptionInfo.getSubscriptionId());
+ } else if (registrationAttributes
+ == ImsRegistrationAttributes.ATTR_EPDG_OVER_CELL_INTERNET) {
+ mImsType = IMS_TYPE_WLAN_CROSS_SIM;
+ IconState statusIcon = new IconState(
+ true,
+ getCallStrengthIcon(mLastWlanCrossSimLevel, /* isWifi= */false),
+ getCallStrengthDescription(
+ mLastWlanCrossSimLevel, /* isWifi= */false));
+ notifyCallStateChange(statusIcon, mSubscriptionInfo.getSubscriptionId());
+ }
+ }
+ }
+
+ @Override
+ public void onUnregistered(ImsReasonInfo info) {
+ Log.d(mTag, "onDeregistered: " + "info=" + info);
+ mImsType = IMS_TYPE_WWAN;
+ IconState statusIcon = new IconState(
+ true,
+ getCallStrengthIcon(mLastWwanLevel, /* isWifi= */false),
+ getCallStrengthDescription(mLastWwanLevel, /* isWifi= */false));
+ notifyCallStateChange(statusIcon, mSubscriptionInfo.getSubscriptionId());
+ }
+ };
+
// TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
// need listener lists anymore.
public MobileSignalController(
@@ -144,8 +218,8 @@
mPhone = phone;
mDefaults = defaults;
mSubscriptionInfo = info;
- mNetworkNameSeparator = getTextIfExists(R.string.status_bar_network_name_separator)
- .toString();
+ mNetworkNameSeparator = getTextIfExists(
+ R.string.status_bar_network_name_separator).toString();
mNetworkNameDefault = getTextIfExists(
com.android.internal.R.string.lockscreen_carrier_default).toString();
mReceiverHandler = new Handler(receiverLooper);
@@ -165,83 +239,9 @@
updateTelephony();
}
};
- mCallback = new MobileStatusTracker.Callback() {
- private String mLastStatus;
-
- @Override
- public void onMobileStatusChanged(boolean updateTelephony,
- MobileStatus mobileStatus) {
- if (Log.isLoggable(mTag, Log.DEBUG)) {
- Log.d(mTag, "onMobileStatusChanged="
- + " updateTelephony=" + updateTelephony
- + " mobileStatus=" + mobileStatus.toString());
- }
- String currentStatus = mobileStatus.toString();
- if (!currentStatus.equals(mLastStatus)) {
- mLastStatus = currentStatus;
- String status = new StringBuilder()
- .append(SSDF.format(System.currentTimeMillis())).append(",")
- .append(currentStatus)
- .toString();
- recordLastMobileStatus(status);
- }
- updateMobileStatus(mobileStatus);
- if (updateTelephony) {
- updateTelephony();
- } else {
- notifyListenersIfNecessary();
- }
- }
- };
-
- mRegistrationCallback = new RegistrationCallback() {
- @Override
- public void onRegistered(ImsRegistrationAttributes attributes) {
- Log.d(mTag, "onRegistered: " + "attributes=" + attributes);
- int imsTransportType = attributes.getTransportType();
- int registrationAttributes = attributes.getAttributeFlags();
- if (imsTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
- mImsType = IMS_TYPE_WWAN;
- IconState statusIcon = new IconState(
- true,
- getCallStrengthIcon(mLastWwanLevel, /* isWifi= */false),
- getCallStrengthDescription(mLastWwanLevel, /* isWifi= */false));
- notifyCallStateChange(statusIcon, mSubscriptionInfo.getSubscriptionId());
- } else if (imsTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
- if (registrationAttributes == 0) {
- mImsType = IMS_TYPE_WLAN;
- IconState statusIcon = new IconState(
- true,
- getCallStrengthIcon(mLastWlanLevel, /* isWifi= */true),
- getCallStrengthDescription(mLastWlanLevel, /* isWifi= */true));
- notifyCallStateChange(statusIcon, mSubscriptionInfo.getSubscriptionId());
- } else if (registrationAttributes
- == ImsRegistrationAttributes.ATTR_EPDG_OVER_CELL_INTERNET) {
- mImsType = IMS_TYPE_WLAN_CROSS_SIM;
- IconState statusIcon = new IconState(
- true,
- getCallStrengthIcon(mLastWlanCrossSimLevel, /* isWifi= */false),
- getCallStrengthDescription(
- mLastWlanCrossSimLevel, /* isWifi= */false));
- notifyCallStateChange(statusIcon, mSubscriptionInfo.getSubscriptionId());
- }
- }
- }
-
- @Override
- public void onUnregistered(ImsReasonInfo info) {
- Log.d(mTag, "onDeregistered: " + "info=" + info);
- mImsType = IMS_TYPE_WWAN;
- IconState statusIcon = new IconState(
- true,
- getCallStrengthIcon(mLastWwanLevel, /* isWifi= */false),
- getCallStrengthDescription(mLastWwanLevel, /* isWifi= */false));
- notifyCallStateChange(statusIcon, mSubscriptionInfo.getSubscriptionId());
- }
- };
mImsMmTelManager = ImsMmTelManager.createForSubscriptionId(info.getSubscriptionId());
mMobileStatusTracker = new MobileStatusTracker(mPhone, receiverLooper,
- info, mDefaults, mCallback);
+ info, mDefaults, mMobileCallback);
mProviderModelBehavior = featureFlags.isCombinedStatusBarSignalIconsEnabled();
mProviderModelSetting = featureFlags.isProviderModelSettingEnabled();
}
@@ -419,7 +419,7 @@
MobileDataIndicators mobileDataIndicators = new MobileDataIndicators(
statusIcon, qsIcon, typeIcon, qsTypeIcon,
activityIn, activityOut, dataContentDescription, dataContentDescriptionHtml,
- description, icons.isWide, mSubscriptionInfo.getSubscriptionId(),
+ description, mSubscriptionInfo.getSubscriptionId(),
mCurrentState.roaming, showTriangle);
callback.setMobileDataIndicators(mobileDataIndicators);
} else {
@@ -464,7 +464,7 @@
MobileDataIndicators mobileDataIndicators = new MobileDataIndicators(
statusIcon, qsIcon, typeIcon, qsTypeIcon,
activityIn, activityOut, dataContentDescription, dataContentDescriptionHtml,
- description, icons.isWide, mSubscriptionInfo.getSubscriptionId(),
+ description, mSubscriptionInfo.getSubscriptionId(),
mCurrentState.roaming, showTriangle);
callback.setMobileDataIndicators(mobileDataIndicators);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index eeea699..caf8f31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -101,7 +101,6 @@
public CharSequence typeContentDescription;
public CharSequence typeContentDescriptionHtml;
public CharSequence description;
- public boolean isWide;
public int subId;
public boolean roaming;
public boolean showTriangle;
@@ -109,7 +108,7 @@
public MobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int qsType, boolean activityIn, boolean activityOut,
CharSequence typeContentDescription, CharSequence typeContentDescriptionHtml,
- CharSequence description, boolean isWide, int subId, boolean roaming,
+ CharSequence description, int subId, boolean roaming,
boolean showTriangle) {
this.statusIcon = statusIcon;
this.qsIcon = qsIcon;
@@ -120,7 +119,6 @@
this.typeContentDescription = typeContentDescription;
this.typeContentDescriptionHtml = typeContentDescriptionHtml;
this.description = description;
- this.isWide = isWide;
this.subId = subId;
this.roaming = roaming;
this.showTriangle = showTriangle;
@@ -138,7 +136,6 @@
.append(",typeContentDescription=").append(typeContentDescription)
.append(",typeContentDescriptionHtml=").append(typeContentDescriptionHtml)
.append(",description=").append(description)
- .append(",isWide=").append(isWide)
.append(",subId=").append(subId)
.append(",roaming=").append(roaming)
.append(",showTriangle=").append(showTriangle)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index fc19564..22dff7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -172,7 +172,7 @@
MobileDataIndicators mobileDataIndicators = new MobileDataIndicators(
statusIcon, qsIcon, typeIcon, qsTypeIcon,
mCurrentState.activityIn, mCurrentState.activityOut, dataContentDescription,
- dataContentDescriptionHtml, description, icons.isWide,
+ dataContentDescriptionHtml, description,
mCurrentState.subId, /* roaming= */ false, /* showTriangle= */ true
);
callback.setMobileDataIndicators(mobileDataIndicators);
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
index 20857ea..fe183fc 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
@@ -38,8 +38,8 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.PluginEnablerImpl;
+import com.android.systemui.shared.plugins.PluginActionManager;
import com.android.systemui.shared.plugins.PluginEnabler;
-import com.android.systemui.shared.plugins.PluginInstanceManager;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginPrefs;
@@ -102,7 +102,7 @@
}
List<PackageInfo> apps = pm.getPackagesHoldingPermissions(new String[]{
- PluginInstanceManager.PLUGIN_PERMISSION},
+ PluginActionManager.PLUGIN_PERMISSION},
PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.GET_SERVICES);
apps.forEach(app -> {
if (!plugins.containsKey(app.packageName)) return;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index 06b0bb2..8d615f0 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -226,7 +226,7 @@
}
@Test
- public void testDetachRemovesSmartspaceView() {
+ public void testDetachDisconnectsSmartspace() {
when(mSmartspaceController.isEnabled()).thenReturn(true);
when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mFakeSmartspaceView);
mController.init();
@@ -237,7 +237,7 @@
verify(mView).addOnAttachStateChangeListener(listenerArgumentCaptor.capture());
listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView);
- verify(mView).removeView(mFakeSmartspaceView);
+ verify(mSmartspaceController).disconnect();
}
@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 d87a26b..8f5eefc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
@@ -42,6 +42,8 @@
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+import javax.inject.Provider
+
@SmallTest
@RunWith(AndroidTestingRunner::class)
class AuthRippleControllerTest : SysuiTestCase() {
@@ -55,10 +57,14 @@
@Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
@Mock private lateinit var bypassController: KeyguardBypassController
@Mock private lateinit var biometricUnlockController: BiometricUnlockController
+ @Mock private lateinit var udfpsControllerProvider: Provider<UdfpsController>
+ @Mock private lateinit var udfpsController: UdfpsController
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
+ `when`(udfpsControllerProvider.get()).thenReturn(udfpsController)
+
controller = AuthRippleController(
statusBar,
context,
@@ -69,6 +75,7 @@
notificationShadeWindowController,
bypassController,
biometricUnlockController,
+ udfpsControllerProvider,
rippleView
)
controller.init()
@@ -93,7 +100,7 @@
// THEN update sensor location and show ripple
verify(rippleView).setSensorLocation(fpsLocation)
- verify(rippleView).startRipple(any(), any())
+ verify(rippleView).startUnlockedRipple(any(), any())
}
@Test
@@ -114,7 +121,7 @@
false /* isStrongBiometric */)
// THEN no ripple
- verify(rippleView, never()).startRipple(any(), any())
+ verify(rippleView, never()).startUnlockedRipple(any(), any())
}
@Test
@@ -135,7 +142,7 @@
false /* isStrongBiometric */)
// THEN no ripple
- verify(rippleView, never()).startRipple(any(), any())
+ verify(rippleView, never()).startUnlockedRipple(any(), any())
}
@Test
@@ -159,7 +166,7 @@
// THEN show ripple
verify(rippleView).setSensorLocation(faceLocation)
- verify(rippleView).startRipple(any(), any())
+ verify(rippleView).startUnlockedRipple(any(), any())
}
@Test
@@ -179,7 +186,7 @@
false /* isStrongBiometric */)
// THEN no ripple
- verify(rippleView, never()).startRipple(any(), any())
+ verify(rippleView, never()).startUnlockedRipple(any(), any())
}
@Test
@@ -194,7 +201,7 @@
0 /* userId */,
BiometricSourceType.FACE /* type */,
false /* isStrongBiometric */)
- verify(rippleView, never()).startRipple(any(), any())
+ verify(rippleView, never()).startUnlockedRipple(any(), any())
}
@Test
@@ -209,7 +216,7 @@
0 /* userId */,
BiometricSourceType.FINGERPRINT /* type */,
false /* isStrongBiometric */)
- verify(rippleView, never()).startRipple(any(), any())
+ verify(rippleView, never()).startUnlockedRipple(any(), any())
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
index 2c08fe6..be3e535 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
@@ -384,7 +384,41 @@
// WHEN status bar expansion is 0 but udfps bouncer is requested
mAltAuthInterceptor.showAlternateAuthBouncer();
- // THEN alpha is 0
+ // THEN alpha is 255
+ verify(mView).setUnpausedAlpha(255);
+ }
+
+ @Test
+ public void testTransitionToFullShadeProgress() {
+ // GIVEN view is attached and status bar expansion is 1f
+ mController.onViewAttached();
+ captureExpansionListeners();
+ updateStatusBarExpansion(1f, true);
+ reset(mView);
+
+ // WHEN we're transitioning to the full shade
+ float transitionProgress = .6f;
+ mController.setTransitionToFullShadeProgress(transitionProgress);
+
+ // THEN alpha is between 0 and 255
+ verify(mView).setUnpausedAlpha((int) ((1f - transitionProgress) * 255));
+ }
+
+ @Test
+ public void testShowUdfpsBouncer_transitionToFullShadeProgress() {
+ // GIVEN view is attached and status bar expansion is 1f
+ mController.onViewAttached();
+ captureExpansionListeners();
+ captureKeyguardStateControllerCallback();
+ captureAltAuthInterceptor();
+ updateStatusBarExpansion(1f, true);
+ mAltAuthInterceptor.showAlternateAuthBouncer();
+ reset(mView);
+
+ // WHEN we're transitioning to the full shade
+ mController.setTransitionToFullShadeProgress(1.0f);
+
+ // THEN alpha is 255 (b/c udfps bouncer is requested)
verify(mView).setUnpausedAlpha(255);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 1ed34d9..c3d60d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -43,6 +43,7 @@
import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -100,6 +101,8 @@
private TileServiceRequestController.Builder mTileServiceRequestControllerBuilder;
@Mock
private TileServiceRequestController mTileServiceRequestController;
+ @Mock
+ private FeatureFlags mFeatureFlags;
public QSFragmentTest() {
super(QSFragment.class);
@@ -145,7 +148,7 @@
mock(BroadcastDispatcher.class), Optional.of(mock(StatusBar.class)),
mock(QSLogger.class), mock(UiEventLogger.class), mock(UserTracker.class),
mock(SecureSettings.class), mock(CustomTileStatePersister.class),
- mTileServiceRequestControllerBuilder);
+ mTileServiceRequestControllerBuilder, mFeatureFlags);
qs.setHost(host);
qs.setListening(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index c746bca..aba043b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -50,6 +50,7 @@
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
@@ -126,6 +127,8 @@
private TileServiceRequestController.Builder mTileServiceRequestControllerBuilder;
@Mock
private TileServiceRequestController mTileServiceRequestController;
+ @Mock
+ private FeatureFlags mFeatureFlags;
private Handler mHandler;
private TestableLooper mLooper;
@@ -145,8 +148,10 @@
mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mHandler,
mLooper.getLooper(), mPluginManager, mTunerService, mAutoTiles, mDumpManager,
mBroadcastDispatcher, mStatusBar, mQSLogger, mUiEventLogger, mUserTracker,
- mSecureSettings, mCustomTileStatePersister, mTileServiceRequestControllerBuilder);
+ mSecureSettings, mCustomTileStatePersister, mTileServiceRequestControllerBuilder,
+ mFeatureFlags);
setUpTileFactory();
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(false);
}
private void setUpTileFactory() {
@@ -174,13 +179,13 @@
@Test
public void testLoadTileSpecs_emptySetting() {
- List<String> tiles = QSTileHost.loadTileSpecs(mContext, "");
+ List<String> tiles = QSTileHost.loadTileSpecs(mContext, "", mFeatureFlags);
assertFalse(tiles.isEmpty());
}
@Test
public void testLoadTileSpecs_nullSetting() {
- List<String> tiles = QSTileHost.loadTileSpecs(mContext, null);
+ List<String> tiles = QSTileHost.loadTileSpecs(mContext, null, mFeatureFlags);
assertFalse(tiles.isEmpty());
}
@@ -194,6 +199,55 @@
}
@Test
+ public void testRemoveWifiAndCellularWithoutInternet() {
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "wifi, spec1, cell, spec2");
+
+ assertEquals("internet", mQSTileHost.mTileSpecs.get(0));
+ assertEquals("spec1", mQSTileHost.mTileSpecs.get(1));
+ assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+ }
+
+ @Test
+ public void testRemoveWifiAndCellularWithInternet() {
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "wifi, spec1, cell, spec2, internet");
+
+ assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
+ assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
+ assertEquals("internet", mQSTileHost.mTileSpecs.get(2));
+ }
+
+ @Test
+ public void testRemoveWifiWithoutInternet() {
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1, wifi, spec2");
+
+ assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
+ assertEquals("internet", mQSTileHost.mTileSpecs.get(1));
+ assertEquals("spec2", mQSTileHost.mTileSpecs.get(2));
+ }
+
+ @Test
+ public void testRemoveCellWithInternet() {
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1, spec2, cell, internet");
+
+ assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
+ assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
+ assertEquals("internet", mQSTileHost.mTileSpecs.get(2));
+ }
+
+ @Test
+ public void testNoWifiNoCellularNoInternet() {
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1,spec2");
+
+ assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
+ assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
+ }
+
+ @Test
public void testSpecWithInvalidDoesNotUseDefault() {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles, "spec1,spec2");
@@ -326,7 +380,7 @@
@Test
public void testLoadTileSpec_repeated() {
- List<String> specs = QSTileHost.loadTileSpecs(mContext, "spec1,spec1,spec2");
+ List<String> specs = QSTileHost.loadTileSpecs(mContext, "spec1,spec1,spec2", mFeatureFlags);
assertEquals(2, specs.size());
assertEquals("spec1", specs.get(0));
@@ -337,7 +391,7 @@
public void testLoadTileSpec_repeatedInDefault() {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles_default, "spec1,spec1");
- List<String> specs = QSTileHost.loadTileSpecs(mContext, "default");
+ List<String> specs = QSTileHost.loadTileSpecs(mContext, "default", mFeatureFlags);
// Remove spurious tiles, like dbg:mem
specs.removeIf(spec -> !"spec1".equals(spec));
@@ -348,7 +402,7 @@
public void testLoadTileSpec_repeatedDefaultAndSetting() {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles_default, "spec1");
- List<String> specs = QSTileHost.loadTileSpecs(mContext, "default,spec1");
+ List<String> specs = QSTileHost.loadTileSpecs(mContext, "default,spec1", mFeatureFlags);
// Remove spurious tiles, like dbg:mem
specs.removeIf(spec -> !"spec1".equals(spec));
@@ -387,11 +441,12 @@
BroadcastDispatcher broadcastDispatcher, StatusBar statusBar, QSLogger qsLogger,
UiEventLogger uiEventLogger, UserTracker userTracker,
SecureSettings secureSettings, CustomTileStatePersister customTileStatePersister,
- TileServiceRequestController.Builder tileServiceRequestControllerBuilder) {
+ TileServiceRequestController.Builder tileServiceRequestControllerBuilder,
+ FeatureFlags featureFlags) {
super(context, iconController, defaultFactory, mainHandler, bgLooper, pluginManager,
tunerService, autoTiles, dumpManager, broadcastDispatcher,
Optional.of(statusBar), qsLogger, uiEventLogger, userTracker, secureSettings,
- customTileStatePersister, tileServiceRequestControllerBuilder);
+ customTileStatePersister, tileServiceRequestControllerBuilder, featureFlags);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
index 126b332..a1b7210 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
@@ -232,7 +232,7 @@
MobileDataIndicators indicators = new MobileDataIndicators(
mock(NetworkController.IconState.class),
mock(NetworkController.IconState.class),
- 0, 0, true, true, "", "", "", true, 0, true, true);
+ 0, 0, true, true, "", "", "", 0, true, true);
mSignalCallback.setMobileDataIndicators(indicators);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index 4efcc5c..018806e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -53,6 +53,7 @@
import com.android.internal.logging.InstanceId;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
@@ -108,6 +109,8 @@
private PackageManager mPackageManager;
@Mock
private UserTracker mUserTracker;
+ @Mock
+ private FeatureFlags mFeatureFlags;
@Captor
private ArgumentCaptor<List<TileQueryHelper.TileInfo>> mCaptor;
@@ -133,12 +136,12 @@
}
}
).when(mQSTileHost).createTile(anyString());
-
+ when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(false);
FakeSystemClock clock = new FakeSystemClock();
mMainExecutor = new FakeExecutor(clock);
mBgExecutor = new FakeExecutor(clock);
mTileQueryHelper = new TileQueryHelper(
- mContext, mUserTracker, mMainExecutor, mBgExecutor);
+ mContext, mUserTracker, mMainExecutor, mBgExecutor, mFeatureFlags);
mTileQueryHelper.setListener(mListener);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
index 0a42865..f2303c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
@@ -19,6 +19,7 @@
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
@@ -27,8 +28,12 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.Context;
+import android.content.ContextWrapper;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.ServiceInfo;
import android.net.Uri;
@@ -42,6 +47,7 @@
import android.service.quicksettings.TileService;
import android.test.suitebuilder.annotation.SmallTest;
+import androidx.annotation.Nullable;
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
@@ -69,6 +75,7 @@
private HandlerThread mThread;
private Handler mHandler;
private TileLifecycleManager mStateManager;
+ private TestContextWrapper mWrappedContext;
@Before
public void setUp() throws Exception {
@@ -81,12 +88,14 @@
mContext.addMockService(mTileServiceComponentName, mMockTileService);
+ mWrappedContext = new TestContextWrapper(mContext);
+
mTileServiceIntent = new Intent().setComponent(mTileServiceComponentName);
mUser = new UserHandle(UserHandle.myUserId());
mThread = new HandlerThread("TestThread");
mThread.start();
mHandler = Handler.createAsync(mThread.getLooper());
- mStateManager = new TileLifecycleManager(mHandler, mContext,
+ mStateManager = new TileLifecycleManager(mHandler, mWrappedContext,
Mockito.mock(IQSService.class), new Tile(),
mTileServiceIntent,
mUser,
@@ -97,6 +106,7 @@
@After
public void tearDown() throws Exception {
mThread.quit();
+ mStateManager.handleDestroy();
}
private void setPackageEnabled(boolean enabled) throws Exception {
@@ -127,6 +137,18 @@
}
@Test
+ public void testPackageReceiverExported() throws Exception {
+ // Make sure that we register a receiver
+ setPackageEnabled(false);
+ mStateManager.setBindService(true);
+ IntentFilter filter = mWrappedContext.mLastIntentFilter;
+ assertTrue(filter.hasAction(Intent.ACTION_PACKAGE_ADDED));
+ assertTrue(filter.hasAction(Intent.ACTION_PACKAGE_CHANGED));
+ assertTrue(filter.hasDataScheme("package"));
+ assertNotEquals(0, mWrappedContext.mLastFlag & Context.RECEIVER_EXPORTED);
+ }
+
+ @Test
public void testUnbind() {
mStateManager.setBindService(true);
mStateManager.setBindService(false);
@@ -247,4 +269,23 @@
public void testToggleableTile() throws Exception {
assertTrue(mStateManager.isToggleableTile());
}
+
+ private static class TestContextWrapper extends ContextWrapper {
+ private IntentFilter mLastIntentFilter;
+ private int mLastFlag;
+
+ TestContextWrapper(Context base) {
+ super(base);
+ }
+
+ @Override
+ public Intent registerReceiverAsUser(@Nullable BroadcastReceiver receiver, UserHandle user,
+ IntentFilter filter, @Nullable String broadcastPermission,
+ @Nullable Handler scheduler, int flags) {
+ mLastIntentFilter = filter;
+ mLastFlag = flags;
+ return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
+ scheduler, flags);
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
index 6a9d9fa..573980d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceManagerTest.java
@@ -20,6 +20,9 @@
import static junit.framework.Assert.assertTrue;
import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.UserHandle;
@@ -47,6 +50,7 @@
private Handler mHandler;
private TileServiceManager mTileServiceManager;
private UserTracker mUserTracker;
+ private Context mMockContext;
@Before
public void setUp() throws Exception {
@@ -58,7 +62,8 @@
Mockito.when(mUserTracker.getUserId()).thenReturn(UserHandle.USER_SYSTEM);
Mockito.when(mUserTracker.getUserHandle()).thenReturn(UserHandle.SYSTEM);
- Mockito.when(mTileServices.getContext()).thenReturn(mContext);
+ mMockContext = Mockito.mock(Context.class);
+ Mockito.when(mTileServices.getContext()).thenReturn(mMockContext);
mTileLifecycle = Mockito.mock(TileLifecycleManager.class);
Mockito.when(mTileLifecycle.isActiveTile()).thenReturn(false);
ComponentName componentName = new ComponentName(mContext,
@@ -71,6 +76,25 @@
@After
public void tearDown() throws Exception {
mThread.quit();
+ mTileServiceManager.handleDestroy();
+ }
+
+ @Test
+ public void testUninstallReceiverExported() {
+ ArgumentCaptor<IntentFilter> intentFilterCaptor =
+ ArgumentCaptor.forClass(IntentFilter.class);
+
+ Mockito.verify(mMockContext).registerReceiverAsUser(
+ Mockito.any(),
+ Mockito.any(),
+ intentFilterCaptor.capture(),
+ Mockito.any(),
+ Mockito.any(),
+ Mockito.eq(Context.RECEIVER_EXPORTED)
+ );
+ IntentFilter filter = intentFilterCaptor.getValue();
+ assertTrue(filter.hasAction(Intent.ACTION_PACKAGE_REMOVED));
+ assertTrue(filter.hasDataScheme("package"));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index e027ab7..a803653 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -43,6 +43,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
@@ -102,6 +103,8 @@
private TileServiceRequestController.Builder mTileServiceRequestControllerBuilder;
@Mock
private TileServiceRequestController mTileServiceRequestController;
+ @Mock
+ private FeatureFlags mFeatureFlags;
@Before
public void setUp() throws Exception {
@@ -128,7 +131,8 @@
mUserTracker,
mSecureSettings,
mock(CustomTileStatePersister.class),
- mTileServiceRequestControllerBuilder);
+ mTileServiceRequestControllerBuilder,
+ mFeatureFlags);
mTileService = new TestTileServices(host, Looper.getMainLooper(), mBroadcastDispatcher,
mUserTracker);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
index a9c6a53..6a68b71 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
@@ -56,45 +56,71 @@
@Test
fun testRegisterViewOnTheLeftOfVerticalFold_halfProgress_viewTranslatedToTheRight() {
givenScreen(width = 100, height = 100, rotation = ROTATION_0)
- val view = createView(x = 20)
+ val view = createView(x = 20, width = 10, height = 10)
animator.registerViewForAnimation(view)
animator.onTransitionStarted()
animator.onTransitionProgress(0.5f)
// Positive translationX -> translated to the right
- assertThat(view.translationX).isWithin(0.1f).of(3.75f)
+ // 10x10 view center is 25px from the center,
+ // When progress is 0.5 it should be translated at:
+ // 25 * 0.3 * (1 - 0.5) = 3.75px
+ assertThat(view.translationX).isWithin(0.01f).of(3.75f)
}
@Test
fun testRegisterViewOnTheLeftOfVerticalFold_zeroProgress_viewTranslatedToTheRight() {
givenScreen(width = 100, height = 100, rotation = ROTATION_0)
- val view = createView(x = 20)
+ val view = createView(x = 20, width = 10, height = 10)
animator.registerViewForAnimation(view)
animator.onTransitionStarted()
animator.onTransitionProgress(0f)
// Positive translationX -> translated to the right
- assertThat(view.translationX).isWithin(0.1f).of(7.5f)
+ // 10x10 view center is 25px from the center,
+ // When progress is 0 it should be translated at:
+ // 25 * 0.3 * (1 - 0) = 7.5px
+ assertThat(view.translationX).isWithin(0.01f).of(7.5f)
}
@Test
fun testRegisterViewOnTheLeftOfVerticalFold_fullProgress_viewTranslatedToTheOriginalPosition() {
givenScreen(width = 100, height = 100, rotation = ROTATION_0)
- val view = createView(x = 20)
+ val view = createView(x = 20, width = 10, height = 10)
animator.registerViewForAnimation(view)
animator.onTransitionStarted()
animator.onTransitionProgress(1f)
+ // Positive translationX -> translated to the right
+ // 10x10 view center is 25px from the center,
+ // When progress is 1 it should be translated at:
+ // 25 * 0.3 * 0 = 0px
assertThat(view.translationX).isEqualTo(0f)
}
@Test
+ fun testViewOnTheLeftOfVerticalFoldWithTranslation_halfProgress_viewTranslatedToTheRight() {
+ givenScreen(width = 100, height = 100, rotation = ROTATION_0)
+ val view = createView(x = 20, width = 10, height = 10, translationX = 100f)
+ animator.registerViewForAnimation(view)
+ animator.onTransitionStarted()
+
+ animator.onTransitionProgress(0.5f)
+
+ // Positive translationX -> translated to the right, original translation is ignored
+ // 10x10 view center is 25px from the center,
+ // When progress is 0.5 it should be translated at:
+ // 25 * 0.3 * (1 - 0.5) = 3.75px
+ assertThat(view.translationX).isWithin(0.01f).of(3.75f)
+ }
+
+ @Test
fun testRegisterViewAndUnregister_halfProgress_viewIsNotUpdated() {
givenScreen(width = 100, height = 100, rotation = ROTATION_0)
- val view = createView(x = 20)
+ val view = createView(x = 20, width = 10, height = 10)
animator.registerViewForAnimation(view)
animator.onTransitionStarted()
animator.clearRegisteredViews()
@@ -107,7 +133,7 @@
@Test
fun testRegisterViewUpdateProgressAndUnregister_halfProgress_viewIsNotUpdated() {
givenScreen(width = 100, height = 100, rotation = ROTATION_0)
- val view = createView(x = 20)
+ val view = createView(x = 20, width = 10, height = 10)
animator.registerViewForAnimation(view)
animator.onTransitionStarted()
animator.onTransitionProgress(0.2f)
@@ -121,14 +147,29 @@
@Test
fun testRegisterViewOnTheTopOfHorizontalFold_halfProgress_viewTranslatedToTheBottom() {
givenScreen(width = 100, height = 100, rotation = ROTATION_90)
- val view = createView(y = 20)
+ val view = createView(y = 20, width = 10, height = 10)
animator.registerViewForAnimation(view)
animator.onTransitionStarted()
animator.onTransitionProgress(0.5f)
// Positive translationY -> translated to the bottom
- assertThat(view.translationY).isWithin(0.1f).of(3.75f)
+ assertThat(view.translationY).isWithin(0.01f).of(3.75f)
+ }
+
+ @Test
+ fun testUpdateViewPositions_viewOnTheLeftAndMovedToTheRight_viewTranslatedToTheLeft() {
+ givenScreen(width = 100, height = 100, rotation = ROTATION_0)
+ val view = createView(x = 20)
+ animator.registerViewForAnimation(view)
+ animator.onTransitionStarted()
+ animator.onTransitionProgress(0.5f)
+ view.updateMock(x = 80) // view moved from the left side to the right
+
+ animator.updateViewPositions()
+
+ // Negative translationX -> translated to the left
+ assertThat(view.translationX).isWithin(0.1f).of(-5.25f)
}
private fun createView(
@@ -150,15 +191,40 @@
whenever(view.width).thenReturn(width)
whenever(view.height).thenReturn(height)
- return view.apply {
+ view.updateMock(x, y, width, height, translationX, translationY)
+
+ return view
+ }
+
+ private fun View.updateMock(
+ x: Int = 0,
+ y: Int = 0,
+ width: Int = 10,
+ height: Int = 10,
+ translationX: Float = 0f,
+ translationY: Float = 0f
+ ) {
+ doAnswer {
+ val location = (it.arguments[0] as IntArray)
+ location[0] = x
+ location[1] = y
+ Unit
+ }.`when`(this).getLocationOnScreen(any())
+
+ whenever(this.width).thenReturn(width)
+ whenever(this.height).thenReturn(height)
+
+ this.apply {
setTranslationX(translationX)
setTranslationY(translationY)
}
}
- private fun givenScreen(width: Int = 100,
- height: Int = 100,
- rotation: Int = ROTATION_0) {
+ private fun givenScreen(
+ width: Int = 100,
+ height: Int = 100,
+ rotation: Int = ROTATION_0
+ ) {
val display = mock(Display::class.java)
whenever(display.getSize(any())).thenAnswer {
val size = (it.arguments[0] as Point)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
similarity index 62%
rename from packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceManagerTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
index 790b4dd..05280fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
@@ -1,15 +1,17 @@
/*
* Copyright (C) 2016 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
+ * 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.
+ * 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.shared.plugins;
@@ -19,8 +21,6 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -41,13 +41,11 @@
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.SysuiTestableContext;
import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.annotations.Requires;
-import com.android.systemui.shared.plugins.VersionInfo.InvalidVersionException;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -64,30 +62,34 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
-public class PluginInstanceManagerTest extends SysuiTestCase {
+public class PluginActionManagerTest extends SysuiTestCase {
private static final String PRIVILEGED_PACKAGE = "com.android.systemui.shared.plugins";
private TestPlugin mMockPlugin;
private PackageManager mMockPm;
- private PluginListener<Plugin> mMockListener;
- private PluginInstanceManager<Plugin> mPluginInstanceManager;
+ private PluginListener<TestPlugin> mMockListener;
+ private PluginActionManager<TestPlugin> mPluginActionManager;
private VersionInfo mMockVersionInfo;
private PluginEnabler mMockEnabler;
ComponentName mTestPluginComponentName =
new ComponentName(PRIVILEGED_PACKAGE, TestPlugin.class.getName());
- private PluginInitializer mInitializer;
private final FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
NotificationManager mNotificationManager;
- private PluginInstanceManager.Factory mInstanceManagerFactory;
- private final PluginInstanceManager.InstanceFactory<Plugin> mPluginInstanceFactory =
- new PluginInstanceManager.InstanceFactory<Plugin>() {
+ private PluginInstance<TestPlugin> mPluginInstance;
+ private PluginInstance.Factory mPluginInstanceFactory = new PluginInstance.Factory(
+ this.getClass().getClassLoader(),
+ new PluginInstance.InstanceFactory<>(), new PluginInstance.VersionChecker(),
+ Collections.emptyList(), false) {
@Override
- Plugin create(Class cls) {
- return mMockPlugin;
+ public <T extends Plugin> PluginInstance<T> create(Context context, ApplicationInfo appInfo,
+ ComponentName componentName, Class<T> pluginClass) {
+ return (PluginInstance<T>) mPluginInstance;
}
};
+ private PluginActionManager.Factory mActionManagerFactory;
+
@Before
public void setup() throws Exception {
mContext = new MyContextWrapper(mContext);
@@ -95,16 +97,17 @@
mMockListener = mock(PluginListener.class);
mMockEnabler = mock(PluginEnabler.class);
mMockVersionInfo = mock(VersionInfo.class);
- mInitializer = mock(PluginInitializer.class);
mNotificationManager = mock(NotificationManager.class);
mMockPlugin = mock(TestPlugin.class);
- mInstanceManagerFactory = new PluginInstanceManager.Factory(getContext(), mMockPm,
- mFakeExecutor, mFakeExecutor, mInitializer, mNotificationManager, mMockEnabler,
- new ArrayList<>())
- .setInstanceFactory(mPluginInstanceFactory);
+ mPluginInstance = mock(PluginInstance.class);
+ when(mPluginInstance.getComponentName()).thenReturn(mTestPluginComponentName);
+ when(mPluginInstance.getPackage()).thenReturn(mTestPluginComponentName.getPackageName());
+ mActionManagerFactory = new PluginActionManager.Factory(getContext(), mMockPm,
+ mFakeExecutor, mFakeExecutor, mNotificationManager, mMockEnabler,
+ new ArrayList<>(), mPluginInstanceFactory);
- mPluginInstanceManager = mInstanceManagerFactory.create("myAction", mMockListener,
- true, mMockVersionInfo, true);
+ mPluginActionManager = mActionManagerFactory.create("myAction", mMockListener,
+ TestPlugin.class, true, true);
when(mMockPlugin.getVersion()).thenReturn(1);
}
@@ -112,7 +115,7 @@
public void testNoPlugins() {
when(mMockPm.queryIntentServices(any(), anyInt())).thenReturn(
Collections.emptyList());
- mPluginInstanceManager.loadAll();
+ mPluginActionManager.loadAll();
mFakeExecutor.runAllReady();
@@ -121,68 +124,47 @@
@Test
public void testPluginCreate() throws Exception {
+ //Debug.waitForDebugger();
createPlugin();
// Verify startup lifecycle
- verify(mMockPlugin).onCreate(ArgumentCaptor.forClass(Context.class).capture(),
- ArgumentCaptor.forClass(Context.class).capture());
- verify(mMockListener).onPluginConnected(any(), any());
+ verify(mPluginInstance).onCreate(mContext, mMockListener);
}
@Test
public void testPluginDestroy() throws Exception {
createPlugin(); // Get into valid created state.
- mPluginInstanceManager.destroy();
+ mPluginActionManager.destroy();
mFakeExecutor.runAllReady();
-
// Verify shutdown lifecycle
- verify(mMockListener).onPluginDisconnected(ArgumentCaptor.forClass(Plugin.class).capture());
- verify(mMockPlugin).onDestroy();
- }
-
- @Test
- public void testIncorrectVersion() throws Exception {
- setupFakePmQuery();
- doThrow(new InvalidVersionException("", false)).when(mMockVersionInfo).checkVersion(any());
-
- mPluginInstanceManager.loadAll();
-
- mFakeExecutor.runAllReady();
-
- // Plugin shouldn't be connected because it is the wrong version.
- verify(mMockListener, never()).onPluginConnected(any(), any());
- verify(mNotificationManager).notify(eq(SystemMessage.NOTE_PLUGIN), any());
+ verify(mPluginInstance).onDestroy(mMockListener);
}
@Test
public void testReloadOnChange() throws Exception {
createPlugin(); // Get into valid created state.
- mPluginInstanceManager.onPackageChange(PRIVILEGED_PACKAGE);
+ mPluginActionManager.reloadPackage(PRIVILEGED_PACKAGE);
mFakeExecutor.runAllReady();
// Verify the old one was destroyed.
- verify(mMockListener).onPluginDisconnected(ArgumentCaptor.forClass(Plugin.class).capture());
- verify(mMockPlugin).onDestroy();
- // Also verify we got a second onCreate.
- verify(mMockPlugin, Mockito.times(2)).onCreate(
- ArgumentCaptor.forClass(Context.class).capture(),
- ArgumentCaptor.forClass(Context.class).capture());
- verify(mMockListener, Mockito.times(2)).onPluginConnected(any(), any());
+ verify(mPluginInstance).onDestroy(mMockListener);
+ verify(mPluginInstance, Mockito.times(2))
+ .onCreate(mContext, mMockListener);
}
@Test
public void testNonDebuggable() throws Exception {
// Create a version that thinks the build is not debuggable.
- mPluginInstanceManager = mInstanceManagerFactory.create("myAction", mMockListener,
- true, mMockVersionInfo, false);
+ mPluginActionManager = mActionManagerFactory.create("myAction", mMockListener,
+ TestPlugin.class, true, false);
setupFakePmQuery();
- mPluginInstanceManager.loadAll();
+ mPluginActionManager.loadAll();
mFakeExecutor.runAllReady();
@@ -193,22 +175,20 @@
@Test
public void testNonDebuggable_privileged() throws Exception {
// Create a version that thinks the build is not debuggable.
- PluginInstanceManager.Factory factory = new PluginInstanceManager.Factory(getContext(),
- mMockPm, mFakeExecutor, mFakeExecutor, mInitializer, mNotificationManager,
- mMockEnabler, Collections.singletonList(PRIVILEGED_PACKAGE));
- factory.setInstanceFactory(mPluginInstanceFactory);
- mPluginInstanceManager = factory.create("myAction", mMockListener,
- true, mMockVersionInfo, false);
+ PluginActionManager.Factory factory = new PluginActionManager.Factory(getContext(),
+ mMockPm, mFakeExecutor, mFakeExecutor, mNotificationManager,
+ mMockEnabler, Collections.singletonList(PRIVILEGED_PACKAGE),
+ mPluginInstanceFactory);
+ mPluginActionManager = factory.create("myAction", mMockListener,
+ TestPlugin.class, true, false);
setupFakePmQuery();
- mPluginInstanceManager.loadAll();
+ mPluginActionManager.loadAll();
mFakeExecutor.runAllReady();
// Verify startup lifecycle
- verify(mMockPlugin).onCreate(ArgumentCaptor.forClass(Context.class).capture(),
- ArgumentCaptor.forClass(Context.class).capture());
- verify(mMockListener).onPluginConnected(any(), any());
+ verify(mPluginInstance).onCreate(mContext, mMockListener);
}
@Test
@@ -216,12 +196,12 @@
createPlugin(); // Get into valid created state.
// Start with an unrelated class.
- boolean result = mPluginInstanceManager.checkAndDisable(Activity.class.getName());
+ boolean result = mPluginActionManager.checkAndDisable(Activity.class.getName());
assertFalse(result);
verify(mMockEnabler, never()).setDisabled(any(ComponentName.class), anyInt());
// Now hand it a real class and make sure it disables the plugin.
- result = mPluginInstanceManager.checkAndDisable(TestPlugin.class.getName());
+ result = mPluginActionManager.checkAndDisable(TestPlugin.class.getName());
assertTrue(result);
verify(mMockEnabler).setDisabled(
mTestPluginComponentName, PluginEnabler.DISABLED_FROM_EXPLICIT_CRASH);
@@ -231,24 +211,24 @@
public void testDisableAll() throws Exception {
createPlugin(); // Get into valid created state.
- mPluginInstanceManager.disableAll();
+ mPluginActionManager.disableAll();
verify(mMockEnabler).setDisabled(
mTestPluginComponentName, PluginEnabler.DISABLED_FROM_SYSTEM_CRASH);
}
@Test
- public void testDisableWhitelisted() throws Exception {
- PluginInstanceManager.Factory factory = new PluginInstanceManager.Factory(getContext(),
- mMockPm, mFakeExecutor, mFakeExecutor, mInitializer, mNotificationManager,
- mMockEnabler, Collections.singletonList(PRIVILEGED_PACKAGE));
- factory.setInstanceFactory(mPluginInstanceFactory);
- mPluginInstanceManager = factory.create("myAction", mMockListener,
- true, mMockVersionInfo, false);
+ public void testDisablePrivileged() throws Exception {
+ PluginActionManager.Factory factory = new PluginActionManager.Factory(getContext(),
+ mMockPm, mFakeExecutor, mFakeExecutor, mNotificationManager,
+ mMockEnabler, Collections.singletonList(PRIVILEGED_PACKAGE),
+ mPluginInstanceFactory);
+ mPluginActionManager = factory.create("myAction", mMockListener,
+ TestPlugin.class, true, false);
createPlugin(); // Get into valid created state.
- mPluginInstanceManager.disableAll();
+ mPluginActionManager.disableAll();
verify(mMockPm, never()).setComponentEnabledSetting(
ArgumentCaptor.forClass(ComponentName.class).capture(),
@@ -282,14 +262,14 @@
private void createPlugin() throws Exception {
setupFakePmQuery();
- mPluginInstanceManager.loadAll();
+ mPluginActionManager.loadAll();
mFakeExecutor.runAllReady();
}
// Real context with no registering/unregistering of receivers.
private static class MyContextWrapper extends SysuiTestableContext {
- public MyContextWrapper(Context base) {
+ MyContextWrapper(Context base) {
super(base);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
new file mode 100644
index 0000000..bb9a1e9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginInstanceTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.plugins;
+
+import static junit.framework.Assert.assertNotNull;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.Plugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+import com.android.systemui.plugins.annotations.Requires;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PluginInstanceTest extends SysuiTestCase {
+
+ private static final String PRIVILEGED_PACKAGE = "com.android.systemui.plugins";
+
+ @Mock
+ private TestPluginImpl mMockPlugin;
+ @Mock
+ private PluginListener<TestPlugin> mMockListener;
+ @Mock
+ private VersionInfo mVersionInfo;
+ ComponentName mTestPluginComponentName =
+ new ComponentName(PRIVILEGED_PACKAGE, TestPluginImpl.class.getName());
+ private PluginInstance<TestPlugin> mPluginInstance;
+ private PluginInstance.Factory mPluginInstanceFactory;
+
+ private ApplicationInfo mAppInfo;
+ private Context mPluginContext;
+ @Mock
+ private PluginInstance.VersionChecker mVersionChecker;
+
+ @Before
+ public void setup() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mAppInfo = mContext.getApplicationInfo();
+ mAppInfo.packageName = mTestPluginComponentName.getPackageName();
+ when(mVersionChecker.checkVersion(any(), any(), any())).thenReturn(mVersionInfo);
+
+ mPluginInstanceFactory = new PluginInstance.Factory(
+ this.getClass().getClassLoader(),
+ new PluginInstance.InstanceFactory<TestPlugin>() {
+ @Override
+ TestPlugin create(Class cls) {
+ return mMockPlugin;
+ }
+ },
+ mVersionChecker,
+ Collections.singletonList(PRIVILEGED_PACKAGE),
+ false);
+
+ mPluginInstance = mPluginInstanceFactory.create(
+ mContext, mAppInfo, mTestPluginComponentName, TestPlugin.class);
+ mPluginContext = mPluginInstance.getPluginContext();
+ }
+
+ @Test
+ public void testCorrectVersion() {
+ assertNotNull(mPluginInstance);
+ }
+
+ @Test(expected = VersionInfo.InvalidVersionException.class)
+ public void testIncorrectVersion() throws Exception {
+
+ ComponentName wrongVersionTestPluginComponentName =
+ new ComponentName(PRIVILEGED_PACKAGE, TestPlugin.class.getName());
+
+ when(mVersionChecker.checkVersion(any(), any(), any())).thenThrow(
+ new VersionInfo.InvalidVersionException("test", true));
+
+ mPluginInstanceFactory.create(
+ mContext, mAppInfo, wrongVersionTestPluginComponentName, TestPlugin.class);
+ }
+
+ @Test
+ public void testOnCreate() {
+ mPluginInstance.onCreate(mContext, mMockListener);
+ verify(mMockPlugin).onCreate(mContext, mPluginContext);
+ verify(mMockListener).onPluginConnected(mMockPlugin, mPluginContext);
+ }
+
+ @Test
+ public void testOnDestroy() {
+ mPluginInstance.onDestroy(mMockListener);
+ verify(mMockListener).onPluginDisconnected(mMockPlugin);
+ verify(mMockPlugin).onDestroy();
+ }
+
+ // This target class doesn't matter, it just needs to have a Requires to hit the flow where
+ // the mock version info is called.
+ @ProvidesInterface(action = TestPlugin.ACTION, version = TestPlugin.VERSION)
+ public interface TestPlugin extends Plugin {
+ int VERSION = 1;
+ String ACTION = "testAction";
+ }
+
+ @Requires(target = TestPlugin.class, version = TestPlugin.VERSION)
+ public static class TestPluginImpl implements TestPlugin {
+ @Override
+ public void onCreate(Context sysuiContext, Context pluginContext) {
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java
index 4590dd8..1eadd52 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginManagerTest.java
@@ -13,6 +13,7 @@
*/
package com.android.systemui.shared.plugins;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
@@ -54,10 +55,10 @@
private static final String PRIVILEGED_PACKAGE = "com.android.systemui";
- private PluginInstanceManager.Factory mMockFactory;
- private PluginInstanceManager<Plugin> mMockPluginInstance;
+ private PluginActionManager.Factory mMockFactory;
+ private PluginActionManager<TestPlugin> mMockPluginInstance;
private PluginManagerImpl mPluginManager;
- private PluginListener<?> mMockListener;
+ private PluginListener<TestPlugin> mMockListener;
private PackageManager mMockPackageManager;
private PluginEnabler mPluginEnabler;
private PluginPrefs mPluginPrefs;
@@ -70,11 +71,11 @@
public void setup() throws Exception {
mRealExceptionHandler = Thread.getUncaughtExceptionPreHandler();
mMockExceptionHandler = mock(UncaughtExceptionHandler.class);
- mMockFactory = mock(PluginInstanceManager.Factory.class);
- mMockPluginInstance = mock(PluginInstanceManager.class);
+ mMockFactory = mock(PluginActionManager.Factory.class);
+ mMockPluginInstance = mock(PluginActionManager.class);
mPluginEnabler = mock(PluginEnabler.class);
mPluginPrefs = mock(PluginPrefs.class);
- when(mMockFactory.create(any(), any(), Mockito.anyBoolean(), any(), Mockito.anyBoolean()))
+ when(mMockFactory.create(any(), any(), eq(TestPlugin.class), anyBoolean(), anyBoolean()))
.thenReturn(mMockPluginInstance);
mMockPackageManager = mock(PackageManager.class);
@@ -116,8 +117,8 @@
applicationInfo.sourceDir = sourceDir;
applicationInfo.packageName = PRIVILEGED_PACKAGE;
mPluginManager.addPluginListener("myAction", mMockListener, TestPlugin.class);
- verify(mMockFactory).create(eq("myAction"), eq(mMockListener), eq(false),
- any(VersionInfo.class), eq(false));
+ verify(mMockFactory).create(eq("myAction"), eq(mMockListener), eq(TestPlugin.class),
+ eq(false), eq(false));
verify(mMockPluginInstance).loadAll();
}
@@ -138,8 +139,8 @@
invalidApplicationInfo.sourceDir = sourceDir;
invalidApplicationInfo.packageName = "com.android.invalidpackage";
mPluginManager.addPluginListener("myAction", mMockListener, TestPlugin.class);
- verify(mMockFactory).create(eq("myAction"), eq(mMockListener), eq(false),
- any(VersionInfo.class), eq(false));
+ verify(mMockFactory).create(eq("myAction"), eq(mMockListener), eq(TestPlugin.class),
+ eq(false), eq(false));
verify(mMockPluginInstance).loadAll();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/DisableFlagsLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/DisableFlagsLoggerTest.kt
new file mode 100644
index 0000000..096efad
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/DisableFlagsLoggerTest.kt
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertThrows
+import org.junit.Test
+
+@SmallTest
+class DisableFlagsLoggerTest : SysuiTestCase() {
+ private val disable1Flags = listOf(
+ DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'),
+ DisableFlagsLogger.DisableFlag(0b010, 'B', 'b'),
+ DisableFlagsLogger.DisableFlag(0b001, 'C', 'c'),
+ )
+ private val disable2Flags = listOf(
+ DisableFlagsLogger.DisableFlag(0b10, 'M', 'm'),
+ DisableFlagsLogger.DisableFlag(0b01, 'N', 'n'),
+ )
+
+ private val disableFlagsLogger = DisableFlagsLogger(disable1Flags, disable2Flags)
+
+ @Test
+ fun getDisableFlagsString_oldAndNewSame_statesLoggedButDiffsNotLogged() {
+ val state = DisableFlagsLogger.DisableState(
+ 0b111, // ABC
+ 0b01 // mN
+ )
+
+ val result = disableFlagsLogger.getDisableFlagsString(state, state)
+
+ assertThat(result).contains("Old: ABC.mN")
+ assertThat(result).contains("New: ABC.mN")
+ assertThat(result).doesNotContain("(")
+ assertThat(result).doesNotContain(")")
+ }
+
+ @Test
+ fun getDisableFlagsString_oldAndNewDifferent_statesAndDiffLogged() {
+ val result = disableFlagsLogger.getDisableFlagsString(
+ DisableFlagsLogger.DisableState(
+ 0b111, // ABC
+ 0b01, // mN
+ ),
+ DisableFlagsLogger.DisableState(
+ 0b001, // abC
+ 0b10 // Mn
+ )
+ )
+
+ assertThat(result).contains("Old: ABC.mN")
+ assertThat(result).contains("New: abC.Mn")
+ assertThat(result).contains("(ab.Mn)")
+ }
+
+ @Test
+ fun getDisableFlagsString_onlyDisable2Different_diffLoggedCorrectly() {
+ val result = disableFlagsLogger.getDisableFlagsString(
+ DisableFlagsLogger.DisableState(
+ 0b001, // abC
+ 0b01, // mN
+ ),
+ DisableFlagsLogger.DisableState(
+ 0b001, // abC
+ 0b00 // mn
+ )
+ )
+
+ assertThat(result).contains("(.n)")
+ }
+
+ @Test
+ fun getDisableFlagsString_nullLocalModification_localModNotLogged() {
+ val result = disableFlagsLogger.getDisableFlagsString(
+ DisableFlagsLogger.DisableState(0, 0),
+ DisableFlagsLogger.DisableState(1, 1),
+ newAfterLocalModification = null
+ )
+
+ assertThat(result).doesNotContain("local modification")
+ }
+
+ @Test
+ fun getDisableFlagsString_newAfterLocalModificationSameAsNew_localModNotLogged() {
+ val newState = DisableFlagsLogger.DisableState(
+ 0b001, // abC
+ 0b10 // mn
+ )
+
+ val result = disableFlagsLogger.getDisableFlagsString(
+ DisableFlagsLogger.DisableState(0, 0), newState, newState
+ )
+
+ assertThat(result).doesNotContain("local modification")
+ }
+
+ @Test
+ fun getDisableFlagsString_newAfterLocalModificationDifferent_localModAndDiffLogged() {
+ val result = disableFlagsLogger.getDisableFlagsString(
+ old = DisableFlagsLogger.DisableState(0, 0),
+ new = DisableFlagsLogger.DisableState(
+ 0b000, // abc
+ 0b00 // mn
+ ),
+ newAfterLocalModification = DisableFlagsLogger.DisableState(
+ 0b100, // Abc
+ 0b10 // Mn
+ )
+ )
+
+ assertThat(result).contains("local modification: Abc.Mn (A.M)")
+ }
+
+ @Test
+ fun constructor_defaultDisableFlags_noException() {
+ // Just creating the logger with the default params will trigger the exception if there
+ // is one.
+ DisableFlagsLogger()
+ }
+
+ @Test
+ fun constructor_disable1_FlagIsSetSymbolNotUnique_exception() {
+ assertThrows(IllegalArgumentException::class.java) {
+ DisableFlagsLogger(
+ disable1FlagsList = listOf(
+ DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'),
+ DisableFlagsLogger.DisableFlag(0b010, 'A', 'b'),
+ ),
+ listOf()
+ )
+ }
+ }
+
+ @Test
+ fun constructor_disable1_FlagNotSetSymbolNotUnique_exception() {
+ assertThrows(IllegalArgumentException::class.java) {
+ DisableFlagsLogger(
+ disable1FlagsList = listOf(
+ DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'),
+ DisableFlagsLogger.DisableFlag(0b010, 'B', 'a'),
+ ),
+ listOf()
+ )
+ }
+ }
+
+ @Test
+ fun constructor_disable2_FlagIsSetSymbolNotUnique_exception() {
+ assertThrows(IllegalArgumentException::class.java) {
+ DisableFlagsLogger(
+ disable1FlagsList = listOf(),
+ disable2FlagsList = listOf(
+ DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'),
+ DisableFlagsLogger.DisableFlag(0b010, 'A', 'b'),
+ ),
+ )
+ }
+ }
+
+ @Test
+ fun constructor_disable2_FlagNotSetSymbolNotUnique_exception() {
+ assertThrows(IllegalArgumentException::class.java) {
+ DisableFlagsLogger(
+ disable1FlagsList = listOf(),
+ disable2FlagsList = listOf(
+ DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'),
+ DisableFlagsLogger.DisableFlag(0b010, 'B', 'a'),
+ ),
+ )
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
index 7f72f19..465370b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -33,6 +33,7 @@
import com.android.systemui.statusbar.phone.ScrimController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.eq
+import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -168,6 +169,22 @@
}
@Test
+ fun onPanelExpansionChanged_respectsMinPanelPullDownFraction() {
+ notificationShadeDepthController.panelPullDownMinFraction = 0.5f
+ notificationShadeDepthController.onPanelExpansionChanged(0.5f /* expansion */,
+ true /* tracking */)
+ assertThat(notificationShadeDepthController.shadeExpansion).isEqualTo(0f)
+
+ notificationShadeDepthController.onPanelExpansionChanged(0.75f /* expansion */,
+ true /* tracking */)
+ assertThat(notificationShadeDepthController.shadeExpansion).isEqualTo(0.5f)
+
+ notificationShadeDepthController.onPanelExpansionChanged(1f /* expansion */,
+ true /* tracking */)
+ assertThat(notificationShadeDepthController.shadeExpansion).isEqualTo(1f)
+ }
+
+ @Test
fun onStateChanged_reevalutesBlurs_ifSameRadiusAndNewState() {
onPanelExpansionChanged_apliesBlur_ifShade()
clearInvocations(choreographer)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
similarity index 98%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
index dd5b5f8..e05035d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
@@ -156,7 +156,7 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class NotificationPanelViewTest extends SysuiTestCase {
+public class NotificationPanelViewControllerTest extends SysuiTestCase {
private static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
@@ -539,6 +539,12 @@
}
@Test
+ public void testSetMinFraction() {
+ mNotificationPanelViewController.setMinFraction(0.5f);
+ verify(mNotificationShadeDepthController).setPanelPullDownMinFraction(eq(0.5f));
+ }
+
+ @Test
public void testSetDozing_notifiesNsslAndStateController() {
mNotificationPanelViewController.setDozing(true /* dozing */, false /* animate */,
null /* touch */);
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 d63730d..c7d4794 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
@@ -16,7 +16,10 @@
package com.android.systemui.statusbar.phone
+import android.view.LayoutInflater
+import android.widget.FrameLayout
import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.CommandQueue
import com.google.common.truth.Truth.assertThat
@@ -24,7 +27,10 @@
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+import com.android.systemui.R
+import com.android.systemui.util.mockito.any
@SmallTest
class PhoneStatusBarViewControllerTest : SysuiTestCase() {
@@ -32,14 +38,22 @@
@Mock
private lateinit var commandQueue: CommandQueue
+ @Mock
+ private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController
+
private lateinit var view: PhoneStatusBarView
private lateinit var controller: PhoneStatusBarViewController
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- view = PhoneStatusBarView(mContext, null)
- controller = PhoneStatusBarViewController(view, commandQueue)
+ // create the view on main thread as it requires main looper
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
+ val parent = FrameLayout(mContext) // add parent to keep layout params
+ view = LayoutInflater.from(mContext)
+ .inflate(R.layout.status_bar, parent, false) as PhoneStatusBarView
+ }
+ controller = PhoneStatusBarViewController(view, commandQueue, null)
}
@Test
@@ -56,4 +70,11 @@
assertThat(providerUsed).isTrue()
}
+
+ @Test
+ fun constructor_moveFromCenterAnimationIsNotNull_moveFromCenterAnimationInitialized() {
+ controller = PhoneStatusBarViewController(view, commandQueue, moveFromCenterAnimation)
+
+ verify(moveFromCenterAnimation).init(any(), any())
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacksTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacksTest.java
index 52538c7..8555306 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacksTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacksTest.java
@@ -38,6 +38,7 @@
import com.android.systemui.assist.AssistManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.DisableFlagsLogger;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
@@ -112,6 +113,7 @@
mVibratorHelper,
Optional.of(mVibrator),
mLightBarController,
+ new DisableFlagsLogger(),
DEFAULT_DISPLAY);
when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index b23414b..3c0382b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -254,6 +254,7 @@
@Mock private BrightnessSlider.Factory mBrightnessSliderFactory;
@Mock private UnfoldTransitionConfig mUnfoldTransitionConfig;
@Mock private Lazy<UnfoldLightRevealOverlayAnimation> mUnfoldLightRevealOverlayAnimationLazy;
+ @Mock private Lazy<StatusBarMoveFromCenterAnimationController> mMoveFromCenterAnimationLazy;
@Mock private OngoingCallController mOngoingCallController;
@Mock private SystemStatusAnimationScheduler mAnimationScheduler;
@Mock private StatusBarLocationPublisher mLocationPublisher;
@@ -428,6 +429,7 @@
mBrightnessSliderFactory,
mUnfoldTransitionConfig,
mUnfoldLightRevealOverlayAnimationLazy,
+ mMoveFromCenterAnimationLazy,
mOngoingCallController,
mAnimationScheduler,
mLocationPublisher,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index 2418243..73538fb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -124,7 +124,7 @@
boolean roaming = true;
MobileDataIndicators indicators = new MobileDataIndicators(
status, qs, type, qsType, in, out, typeDescription,
- typeDescriptionHtml, description, wide, subId, roaming, true);
+ typeDescriptionHtml, description, subId, roaming, true);
mHandler.setMobileDataIndicators(indicators);
waitForCallbacks();
@@ -142,7 +142,6 @@
assertEquals(typeDescription, expected.typeContentDescription);
assertEquals(typeDescriptionHtml, expected.typeContentDescriptionHtml);
assertEquals(description, expected.description);
- assertEquals(wide, expected.isWide);
assertEquals(subId, expected.subId);
assertTrue(expected.roaming);
assertTrue(expected.showTriangle);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java
index 8e1c0f7..d245c72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakePluginManager.java
@@ -30,24 +30,24 @@
@Override
public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
- Class<?> cls, boolean allowMultiple) {
+ Class<T> cls, boolean allowMultiple) {
mLeakChecker.addCallback(listener);
}
@Override
- public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls) {
+ public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<T> cls) {
mLeakChecker.addCallback(listener);
}
@Override
- public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<?> cls,
+ public <T extends Plugin> void addPluginListener(PluginListener<T> listener, Class<T> cls,
boolean allowMultiple) {
mLeakChecker.addCallback(listener);
}
@Override
public <T extends Plugin> void addPluginListener(String action, PluginListener<T> listener,
- Class<?> cls) {
+ Class<T> cls) {
mLeakChecker.addCallback(listener);
}
diff --git a/packages/VpnDialogs/res/values-as/strings.xml b/packages/VpnDialogs/res/values-as/strings.xml
index 4669a69..13c5cc9 100644
--- a/packages/VpnDialogs/res/values-as/strings.xml
+++ b/packages/VpnDialogs/res/values-as/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="prompt" msgid="3183836924226407828">"সংযোগৰ অনুৰোধ"</string>
- <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>এ নেটৱৰ্ক ট্ৰেফিক নিৰীক্ষণ কৰিবলৈ এটা ভিপিএন সংযোগ ছেট আপ কৰিবলৈ বিচাৰিছে৷ আপুনি কেৱল উৎসটোক বিশ্বাস কৰিলেহে অনুৰোধ স্বীকাৰ কৰিব৷ ভিপিএন সক্ৰিয় থকাৰ সময়ত আপোনাৰ স্ক্ৰীণৰ ওপৰত <br /> <br /> <img src=vpn_icon /> দৃশ্যমান হয়৷"</string>
+ <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>এ নেটৱৰ্ক ট্ৰেফিক নিৰীক্ষণ কৰিবলৈ এটা ভিপিএন সংযোগ ছেট আপ কৰিবলৈ বিচাৰিছে৷ আপুনি কেৱল উৎসটোক বিশ্বাস কৰিলেহে অনুৰোধ স্বীকাৰ কৰিব৷ ভিপিএন সক্ৰিয় থকাৰ সময়ত আপোনাৰ স্ক্ৰীনৰ ওপৰত <br /> <br /> <img src=vpn_icon /> দৃশ্যমান হয়৷"</string>
<string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g>এ এটা ভিপিএন সংযোগ ছেট আপ কৰিব বিচাৰে, যিটোৱে ইয়াক নেটৱৰ্ক ট্ৰেফিক নিৰীক্ষণ কৰিবলৈ দিয়ে। আপুনি উৎসটোক বিশ্বাস কৰিলেহে গ্ৰহণ কৰক। ভিপিএনটো সক্ৰিয় হৈ থকাৰ সময়ত আপোনাৰ স্ক্ৰীনত<br /> <br /> <img src=vpn_icon /> প্ৰদৰ্শিত হয়।"</string>
<string name="legacy_title" msgid="192936250066580964">"ভিপিএন সংযোগ হৈ আছে"</string>
<string name="session" msgid="6470628549473641030">"ছেশ্বন:"</string>
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index b88366b..acdbcb58 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -86,7 +86,7 @@
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityWindowManager.RemoteAccessibilityConnection;
-import com.android.server.accessibility.magnification.FullScreenMagnificationController;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -223,10 +223,10 @@
@Nullable FingerprintGestureDispatcher getFingerprintGestureDispatcher();
/**
- * @return The magnification controller
+ * @return The magnification processor
*/
@NonNull
- FullScreenMagnificationController getFullScreenMagnificationController();
+ MagnificationProcessor getMagnificationProcessor();
/**
* Called back to notify system that the client has changed
@@ -975,7 +975,7 @@
}
final long identity = Binder.clearCallingIdentity();
try {
- return mSystemSupport.getFullScreenMagnificationController().getScale(displayId);
+ return mSystemSupport.getMagnificationProcessor().getScale(displayId);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -991,19 +991,15 @@
if (!hasRightsToCurrentUserLocked()) {
return region;
}
- FullScreenMagnificationController magnificationController =
- mSystemSupport.getFullScreenMagnificationController();
- boolean registeredJustForThisCall =
- registerMagnificationIfNeeded(displayId, magnificationController);
+ MagnificationProcessor magnificationProcessor =
+ mSystemSupport.getMagnificationProcessor();
final long identity = Binder.clearCallingIdentity();
try {
- magnificationController.getMagnificationRegion(displayId, region);
+ magnificationProcessor.getMagnificationRegion(displayId, region,
+ mSecurityPolicy.canControlMagnification(this));
return region;
} finally {
Binder.restoreCallingIdentity(identity);
- if (registeredJustForThisCall) {
- magnificationController.unregister(displayId);
- }
}
}
}
@@ -1017,18 +1013,14 @@
if (!hasRightsToCurrentUserLocked()) {
return 0.0f;
}
- FullScreenMagnificationController magnificationController =
- mSystemSupport.getFullScreenMagnificationController();
- boolean registeredJustForThisCall =
- registerMagnificationIfNeeded(displayId, magnificationController);
+ MagnificationProcessor magnificationProcessor =
+ mSystemSupport.getMagnificationProcessor();
final long identity = Binder.clearCallingIdentity();
try {
- return magnificationController.getCenterX(displayId);
+ return magnificationProcessor.getCenterX(displayId,
+ mSecurityPolicy.canControlMagnification(this));
} finally {
Binder.restoreCallingIdentity(identity);
- if (registeredJustForThisCall) {
- magnificationController.unregister(displayId);
- }
}
}
}
@@ -1042,32 +1034,18 @@
if (!hasRightsToCurrentUserLocked()) {
return 0.0f;
}
- FullScreenMagnificationController magnificationController =
- mSystemSupport.getFullScreenMagnificationController();
- boolean registeredJustForThisCall =
- registerMagnificationIfNeeded(displayId, magnificationController);
+ MagnificationProcessor magnificationProcessor =
+ mSystemSupport.getMagnificationProcessor();
final long identity = Binder.clearCallingIdentity();
try {
- return magnificationController.getCenterY(displayId);
+ return magnificationProcessor.getCenterY(displayId,
+ mSecurityPolicy.canControlMagnification(this));
} finally {
Binder.restoreCallingIdentity(identity);
- if (registeredJustForThisCall) {
- magnificationController.unregister(displayId);
- }
}
}
}
- private boolean registerMagnificationIfNeeded(int displayId,
- FullScreenMagnificationController magnificationController) {
- if (!magnificationController.isRegistered(displayId)
- && mSecurityPolicy.canControlMagnification(this)) {
- magnificationController.register(displayId);
- return true;
- }
- return false;
- }
-
@Override
public boolean resetMagnification(int displayId, boolean animate) {
if (svcConnTracingEnabled()) {
@@ -1083,10 +1061,10 @@
}
final long identity = Binder.clearCallingIdentity();
try {
- FullScreenMagnificationController magnificationController =
- mSystemSupport.getFullScreenMagnificationController();
- return (magnificationController.reset(displayId, animate)
- || !magnificationController.isMagnifying(displayId));
+ MagnificationProcessor magnificationProcessor =
+ mSystemSupport.getMagnificationProcessor();
+ return (magnificationProcessor.reset(displayId, animate)
+ || !magnificationProcessor.isMagnifying(displayId));
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1109,12 +1087,9 @@
}
final long identity = Binder.clearCallingIdentity();
try {
- FullScreenMagnificationController magnificationController =
- mSystemSupport.getFullScreenMagnificationController();
- if (!magnificationController.isRegistered(displayId)) {
- magnificationController.register(displayId);
- }
- return magnificationController
+ MagnificationProcessor magnificationProcessor =
+ mSystemSupport.getMagnificationProcessor();
+ return magnificationProcessor
.setScaleAndCenter(displayId, scale, centerX, centerY, animate, mId);
} finally {
Binder.restoreCallingIdentity(identity);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 7d2b71f..10cfd04 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -608,7 +608,8 @@
final Context uiContext = displayContext.createWindowContext(
TYPE_MAGNIFICATION_OVERLAY, null /* options */);
magnificationGestureHandler = new FullScreenMagnificationGestureHandler(uiContext,
- mAms.getFullScreenMagnificationController(), mAms.getTraceManager(),
+ mAms.getMagnificationController().getFullScreenMagnificationController(),
+ mAms.getTraceManager(),
mAms.getMagnificationController(), detectControlGestures, triggerable,
new WindowMagnificationPromptController(displayContext, mUserId), displayId);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index a9cd0ed..aff7eb2 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -126,8 +126,8 @@
import com.android.internal.util.IntPair;
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.accessibility.magnification.FullScreenMagnificationController;
import com.android.server.accessibility.magnification.MagnificationController;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
import com.android.server.accessibility.magnification.WindowMagnificationManager;
import com.android.server.pm.UserManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -219,6 +219,9 @@
private final ActivityTaskManagerInternal mActivityTaskManagerService;
+ private final MagnificationController mMagnificationController;
+ private final MagnificationProcessor mMagnificationProcessor;
+
private final MainHandler mMainHandler;
// Lazily initialized - access through getSystemActionPerfomer()
@@ -261,7 +264,6 @@
private Point mTempPoint = new Point();
private boolean mIsAccessibilityButtonShown;
- private MagnificationController mMagnificationController;
private AccessibilityUserState getCurrentUserStateLocked() {
return getUserStateLocked(mCurrentUserId);
@@ -308,6 +310,7 @@
mA11yWindowManager = a11yWindowManager;
mA11yDisplayListener = a11yDisplayListener;
mMagnificationController = magnificationController;
+ mMagnificationProcessor = new MagnificationProcessor(mMagnificationController);
init();
}
@@ -336,6 +339,7 @@
mWindowManagerService, this, mSecurityPolicy, this, mTraceManager);
mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
mMagnificationController = new MagnificationController(this, mLock, mContext);
+ mMagnificationProcessor = new MagnificationProcessor(mMagnificationController);
init();
}
@@ -2535,7 +2539,7 @@
if (mUiAutomationManager.suppressingAccessibilityServicesLocked()
&& mMagnificationController.isFullScreenMagnificationControllerInitialized()) {
- getFullScreenMagnificationController().unregisterAll();
+ getMagnificationController().getFullScreenMagnificationController().unregisterAll();
return;
}
@@ -2547,7 +2551,8 @@
|| userState.isShortcutMagnificationEnabledLocked()) {
for (int i = 0; i < displays.size(); i++) {
final Display display = displays.get(i);
- getFullScreenMagnificationController().register(display.getDisplayId());
+ getMagnificationController().getFullScreenMagnificationController().register(
+ display.getDisplayId());
}
return;
}
@@ -2557,9 +2562,11 @@
final Display display = displays.get(i);
final int displayId = display.getDisplayId();
if (userHasListeningMagnificationServicesLocked(userState, displayId)) {
- getFullScreenMagnificationController().register(displayId);
+ getMagnificationController().getFullScreenMagnificationController().register(
+ displayId);
} else if (mMagnificationController.isFullScreenMagnificationControllerInitialized()) {
- getFullScreenMagnificationController().unregister(displayId);
+ getMagnificationController().getFullScreenMagnificationController().unregister(
+ displayId);
}
}
}
@@ -2922,7 +2929,9 @@
}
// In case user assigned magnification to the given shortcut.
if (targetName.equals(MAGNIFICATION_CONTROLLER_NAME)) {
- final boolean enabled = !getFullScreenMagnificationController().isMagnifying(displayId);
+ final boolean enabled =
+ !getMagnificationController().getFullScreenMagnificationController()
+ .isMagnifying(displayId);
logAccessibilityShortcutActivated(mContext, MAGNIFICATION_COMPONENT_NAME, shortcutType,
enabled);
sendAccessibilityButtonToInputFilter(displayId);
@@ -3259,9 +3268,7 @@
* @return MagnificationController
*/
MagnificationController getMagnificationController() {
- synchronized (mLock) {
- return mMagnificationController;
- }
+ return mMagnificationController;
}
@Override
@@ -3378,10 +3385,8 @@
}
@Override
- public FullScreenMagnificationController getFullScreenMagnificationController() {
- synchronized (mLock) {
- return mMagnificationController.getFullScreenMagnificationController();
- }
+ public MagnificationProcessor getMagnificationProcessor() {
+ return mMagnificationProcessor;
}
@Override
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index 467cab5..4bf48a2 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -123,7 +123,7 @@
AccessibilityUserState userState = mUserStateWeakReference.get();
if (userState == null) return;
userState.removeServiceLocked(this);
- mSystemSupport.getFullScreenMagnificationController().resetAllIfNeeded(mId);
+ mSystemSupport.getMagnificationProcessor().resetAllIfNeeded(mId);
mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(), -1,
userState.mUserId);
resetLocked();
@@ -334,7 +334,7 @@
userState.serviceDisconnectedLocked(this);
}
resetLocked();
- mSystemSupport.getFullScreenMagnificationController().resetAllIfNeeded(mId);
+ mSystemSupport.getMagnificationProcessor().resetAllIfNeeded(mId);
mSystemSupport.onClientChangeLocked(false);
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java
new file mode 100644
index 0000000..efc6d51
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility.magnification;
+
+import android.annotation.NonNull;
+import android.graphics.Region;
+
+/**
+ * Processor class for AccessibilityService connection to control magnification on the specified
+ * display. This wraps the function of magnification controller.
+ *
+ * @see MagnificationController
+ * @see FullScreenMagnificationController
+ */
+public class MagnificationProcessor {
+
+ private final MagnificationController mController;
+
+ public MagnificationProcessor(MagnificationController controller) {
+ mController = controller;
+ }
+
+ /**
+ * {@link FullScreenMagnificationController#getScale(int)}
+ */
+ public float getScale(int displayId) {
+ return mController.getFullScreenMagnificationController().getScale(displayId);
+ }
+
+ /**
+ * {@link FullScreenMagnificationController#getCenterX(int)}
+ */
+ public float getCenterX(int displayId, boolean canControlMagnification) {
+ boolean registeredJustForThisCall = registerMagnificationIfNeeded(displayId,
+ canControlMagnification);
+ try {
+ return mController.getFullScreenMagnificationController().getCenterX(displayId);
+ } finally {
+ if (registeredJustForThisCall) {
+ unregister(displayId);
+ }
+ }
+ }
+
+ /**
+ * {@link FullScreenMagnificationController#getCenterY(int)}
+ */
+ public float getCenterY(int displayId, boolean canControlMagnification) {
+ boolean registeredJustForThisCall = registerMagnificationIfNeeded(displayId,
+ canControlMagnification);
+ try {
+ return mController.getFullScreenMagnificationController().getCenterY(displayId);
+ } finally {
+ if (registeredJustForThisCall) {
+ unregister(displayId);
+ }
+ }
+ }
+
+ /**
+ * {@link FullScreenMagnificationController#getMagnificationRegion(int, Region)}
+ */
+ public Region getMagnificationRegion(int displayId, @NonNull Region outRegion,
+ boolean canControlMagnification) {
+ boolean registeredJustForThisCall = registerMagnificationIfNeeded(displayId,
+ canControlMagnification);
+ try {
+ mController.getFullScreenMagnificationController().getMagnificationRegion(displayId,
+ outRegion);
+ return outRegion;
+ } finally {
+ if (registeredJustForThisCall) {
+ unregister(displayId);
+ }
+ }
+ }
+
+ /**
+ * {@link FullScreenMagnificationController#setScaleAndCenter(int, float, float, float, boolean,
+ * int)}
+ */
+ public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
+ boolean animate, int id) {
+ if (!isRegistered(displayId)) {
+ register(displayId);
+ }
+ return mController.getFullScreenMagnificationController().setScaleAndCenter(displayId,
+ scale,
+ centerX, centerY, animate, id);
+ }
+
+ /**
+ * {@link FullScreenMagnificationController#reset(int, boolean)}
+ */
+ public boolean reset(int displayId, boolean animate) {
+ return mController.getFullScreenMagnificationController().reset(displayId, animate);
+ }
+
+ /**
+ * {@link FullScreenMagnificationController#resetIfNeeded(int, boolean)}
+ */
+ public void resetAllIfNeeded(int connectionId) {
+ mController.getFullScreenMagnificationController().resetAllIfNeeded(connectionId);
+ }
+
+ /**
+ * {@link FullScreenMagnificationController#register(int)}
+ */
+ public void register(int displayId) {
+ mController.getFullScreenMagnificationController().register(displayId);
+ }
+
+ /**
+ * {@link FullScreenMagnificationController#unregister(int)} (int)}
+ */
+ public void unregister(int displayId) {
+ mController.getFullScreenMagnificationController().unregister(displayId);
+ }
+
+ /**
+ * {@link FullScreenMagnificationController#isMagnifying(int)}
+ */
+ public boolean isMagnifying(int displayId) {
+ return mController.getFullScreenMagnificationController().isMagnifying(displayId);
+ }
+
+ /**
+ * {@link FullScreenMagnificationController#isRegistered(int)}
+ */
+ public boolean isRegistered(int displayId) {
+ return mController.getFullScreenMagnificationController().isRegistered(displayId);
+ }
+
+ private boolean registerMagnificationIfNeeded(int displayId, boolean canControlMagnification) {
+ if (!isRegistered(displayId) && canControlMagnification) {
+ register(displayId);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 44a4997..34d9c8a 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -208,7 +208,7 @@
private ScanCallback mBleScanCallback = new BleScanCallback();
private AssociationRequest mRequest;
private String mCallingPackage;
- private AndroidFuture<Association> mOngoingDeviceDiscovery;
+ private AndroidFuture<?> mOngoingDeviceDiscovery;
private PermissionControllerManager mPermissionControllerManager;
private BluetoothDeviceConnectedListener mBluetoothDeviceConnectedListener =
@@ -383,7 +383,7 @@
Slog.d(LOG_TAG, "cleanup(); discovery = "
+ mOngoingDeviceDiscovery + ", request = " + mRequest);
synchronized (mLock) {
- AndroidFuture<Association> ongoingDeviceDiscovery = mOngoingDeviceDiscovery;
+ AndroidFuture<?> ongoingDeviceDiscovery = mOngoingDeviceDiscovery;
if (ongoingDeviceDiscovery != null && !ongoingDeviceDiscovery.isDone()) {
ongoingDeviceDiscovery.cancel(true);
}
@@ -458,13 +458,16 @@
return mServiceConnectors.forUser(userId).postAsync(service -> {
Slog.d(LOG_TAG, "Connected to CDM service; starting discovery for " + request);
- AndroidFuture<Association> future = new AndroidFuture<>();
+ AndroidFuture<String> future = new AndroidFuture<>();
service.startDiscovery(request, callingPackage, callback, future);
return future;
}).cancelTimeout();
- }, FgThread.getExecutor()).whenComplete(uncheckExceptions((association, err) -> {
+ }, FgThread.getExecutor()).whenComplete(uncheckExceptions((deviceAddress, err) -> {
if (err == null) {
+ Association association = new Association(userId, deviceAddress, callingPackage,
+ mRequest.getDeviceProfile(), false,
+ System.currentTimeMillis());
addAssociation(association, userId);
} else {
Slog.e(LOG_TAG, "Failed to discover device(s)", err);
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 6529b11..c3bf03c 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -20,6 +20,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.content.ComponentName;
@@ -48,6 +49,8 @@
import com.android.server.pm.PackageList;
import com.android.server.pm.PackageSetting;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.AndroidPackageApi;
+import com.android.server.pm.pkg.PackageState;
import java.io.IOException;
import java.lang.annotation.Retention;
@@ -648,7 +651,15 @@
*/
public abstract @Nullable AndroidPackage getPackage(@NonNull String packageName);
- public abstract @Nullable PackageSetting getPackageSetting(String packageName);
+ /**
+ * Returns the {@link SystemApi} variant of a package for use with mainline.
+ */
+ @Nullable
+ public abstract AndroidPackageApi getAndroidPackage(@NonNull String packageName);
+
+ public abstract @Nullable PackageSetting getPackageSetting(@NonNull String packageName);
+
+ public abstract @Nullable PackageState getPackageState(@NonNull String packageName);
/**
* Returns a package for the given UID. If the UID is part of a shared user ID, one
@@ -874,6 +885,17 @@
public abstract void forEachPackageSetting(Consumer<PackageSetting> actionLocked);
/**
+ * Perform the given action for each package.
+ *
+ * @param locked whether to hold the packages lock. If the lock is not held, the objects will
+ * be iterated using a temporary data structure. In the vast majority of cases,
+ * the lock should not have to be held. This is exposed to mirror the
+ * functionality of the other forEach methods, for eventual migration.
+ * @param action action to be performed
+ */
+ public abstract void forEachPackageState(boolean locked, Consumer<PackageState> action);
+
+ /**
* Perform the given action for each installed package for a user.
* Note that packages lock will be held while performing the actions.
*/
diff --git a/services/core/java/android/content/pm/TEST_MAPPING b/services/core/java/android/content/pm/TEST_MAPPING
new file mode 100644
index 0000000..54303cb
--- /dev/null
+++ b/services/core/java/android/content/pm/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "frameworks/base/core/java/android/content/pm"
+ }
+ ]
+}
diff --git a/services/core/java/com/android/server/ExtconUEventObserver.java b/services/core/java/com/android/server/ExtconUEventObserver.java
index 5bd27c4..923db4f 100644
--- a/services/core/java/com/android/server/ExtconUEventObserver.java
+++ b/services/core/java/com/android/server/ExtconUEventObserver.java
@@ -16,17 +16,19 @@
package com.android.server;
import android.annotation.Nullable;
+import android.annotation.StringDef;
+import android.os.FileUtils;
import android.os.UEventObserver;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Slog;
-
+import com.android.internal.annotations.GuardedBy;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
-import java.util.regex.Pattern;
/**
* A specialized UEventObserver that receives UEvents from the kernel for devices in the {@code
@@ -87,41 +89,149 @@
/** An External Connection to watch. */
public static final class ExtconInfo {
- private static final String TAG = "ExtconInfo";
+ /* Copied from drivers/extcon/extcon.c */
- /** Returns a new list of all external connections whose name matches {@code regex}. */
- public static List<ExtconInfo> getExtconInfos(@Nullable String regex) {
- if (!extconExists()) {
- return new ArrayList<>(0); // Always return a new list.
+ /* USB external connector */
+ public static final String EXTCON_USB = "USB";
+ public static final String EXTCON_USB_HOST = "USB-HOST";
+
+ /* Charger external connector */
+ public static final String EXTCON_TA = "TA";
+ public static final String EXTCON_FAST_CHARGER = "FAST-CHARGER";
+ public static final String EXTCON_SLOW_CHARGER = "SLOW-CHARGER";
+ public static final String EXTCON_CHARGE_DOWNSTREAM = "CHARGE-DOWNSTREAM";
+
+ /* Audio/Video external connector */
+ public static final String EXTCON_LINE_IN = "LINE-IN";
+ public static final String EXTCON_LINE_OUT = "LINE-OUT";
+ public static final String EXTCON_MICROPHONE = "MICROPHONE";
+ public static final String EXTCON_HEADPHONE = "HEADPHONE";
+
+ public static final String EXTCON_HDMI = "HDMI";
+ public static final String EXTCON_MHL = "MHL";
+ public static final String EXTCON_DVI = "DVI";
+ public static final String EXTCON_VGA = "VGA";
+ public static final String EXTCON_SPDIF_IN = "SPDIF-IN";
+ public static final String EXTCON_SPDIF_OUT = "SPDIF-OUT";
+ public static final String EXTCON_VIDEO_IN = "VIDEO-IN";
+ public static final String EXTCON_VIDEO_OUT = "VIDEO-OUT";
+
+ /* Etc external connector */
+ public static final String EXTCON_DOCK = "DOCK";
+ public static final String EXTCON_JIG = "JIG";
+ public static final String EXTCON_MECHANICAL = "MECHANICAL";
+
+ @StringDef({
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_TA,
+ EXTCON_FAST_CHARGER,
+ EXTCON_SLOW_CHARGER,
+ EXTCON_CHARGE_DOWNSTREAM,
+ EXTCON_LINE_IN,
+ EXTCON_LINE_OUT,
+ EXTCON_MICROPHONE,
+ EXTCON_HEADPHONE,
+ EXTCON_HDMI,
+ EXTCON_MHL,
+ EXTCON_DVI,
+ EXTCON_VGA,
+ EXTCON_SPDIF_IN,
+ EXTCON_SPDIF_OUT,
+ EXTCON_VIDEO_IN,
+ EXTCON_VIDEO_OUT,
+ EXTCON_DOCK,
+ EXTCON_JIG,
+ EXTCON_MECHANICAL,
+ })
+
+ public @interface ExtconDeviceType {}
+
+ private static final Object sLock = new Object();
+ private static ExtconInfo[] sExtconInfos = null;
+
+ private final String mName;
+ private final @ExtconDeviceType HashSet<String> mDeviceTypes = new HashSet<>();
+
+ @GuardedBy("sLock")
+ private static void initExtconInfos() {
+ if (sExtconInfos != null) {
+ return;
}
- Pattern p = regex == null ? null : Pattern.compile(regex);
+
File file = new File("/sys/class/extcon");
File[] files = file.listFiles();
if (files == null) {
- Slog.wtf(TAG, file + " exists " + file.exists() + " isDir " + file.isDirectory()
- + " but listFiles returns null. "
- + SELINUX_POLICIES_NEED_TO_BE_CHANGED);
- return new ArrayList<>(0); // Always return a new list.
+ Slog.w(TAG,
+ file + " exists " + file.exists() + " isDir " + file.isDirectory()
+ + " but listFiles returns null."
+ + SELINUX_POLICIES_NEED_TO_BE_CHANGED);
+ sExtconInfos = new ExtconInfo[0];
} else {
- ArrayList list = new ArrayList(files.length);
+ List<ExtconInfo> list = new ArrayList<>(files.length);
for (File f : files) {
- String name = f.getName();
- if (p == null || p.matcher(name).matches()) {
- ExtconInfo uei = new ExtconInfo(name);
- list.add(uei);
- if (LOG) Slog.d(TAG, name + " matches " + regex);
- } else {
- if (LOG) Slog.d(TAG, name + " does not match " + regex);
- }
+ list.add(new ExtconInfo(f.getName()));
}
- return list;
+ sExtconInfos = list.toArray(new ExtconInfo[0]);
}
}
- private final String mName;
+ /**
+ * Returns a new list of all external connections for the types given.
+ */
+ public static List<ExtconInfo> getExtconInfoForTypes(
+ @ExtconDeviceType String[] extconTypes) {
+ synchronized (sLock) {
+ initExtconInfos();
+ }
- public ExtconInfo(String name) {
- mName = name;
+ List<ExtconInfo> extcons = new ArrayList<ExtconInfo>();
+ for (ExtconInfo extcon : sExtconInfos) {
+ for (String type : extconTypes) {
+ if (extcon.hasCableType(type)) {
+ extcons.add(extcon);
+ break;
+ }
+ }
+ }
+
+ return extcons;
+ }
+
+ /** True if the given type is supported */
+ public boolean hasCableType(@ExtconDeviceType String type) {
+ return mDeviceTypes.contains(type);
+ }
+
+ private ExtconInfo(String extconName) {
+ mName = extconName;
+
+ // Retrieve device types from /sys/class/extcon/extcon[X]/cable.[Y]/name
+ File[] cableDirs = FileUtils.listFilesOrEmpty(new File("/sys/class/extcon", mName),
+ (dir, cable) -> cable.startsWith("cable."));
+ if (cableDirs.length == 0) {
+ Slog.d(TAG,
+ "Unable to list cables in /sys/class/extcon/" + mName + ". "
+ + SELINUX_POLICIES_NEED_TO_BE_CHANGED);
+ }
+
+ for (File cableDir : cableDirs) {
+ String cableCanonicalPath = null;
+ try {
+ cableCanonicalPath = cableDir.getCanonicalPath();
+ String name = FileUtils.readTextFile(new File(cableDir, "name"), 0, null);
+ name = name.replace("\n", "").replace("\r", "");
+ if (LOG) {
+ Slog.v(TAG, "Add extcon cable " + cableCanonicalPath);
+ }
+ mDeviceTypes.add(name);
+ } catch (IOException ex) {
+ Slog.w(TAG,
+ "Unable to read " + cableCanonicalPath + "/name. "
+ + SELINUX_POLICIES_NEED_TO_BE_CHANGED,
+ ex);
+ }
+ }
}
/** The name of the external connection */
@@ -139,7 +249,7 @@
@Nullable
public String getDevicePath() {
try {
- String extconPath = String.format(Locale.US, "/sys/class/extcon/%s", mName);
+ String extconPath = TextUtils.formatSimple("/sys/class/extcon/%s", mName);
File devPath = new File(extconPath);
if (devPath.exists()) {
String canonicalPath = devPath.getCanonicalPath();
@@ -155,16 +265,10 @@
/** The path to the state file */
public String getStatePath() {
- return String.format(Locale.US, "/sys/class/extcon/%s/state", mName);
+ return TextUtils.formatSimple("/sys/class/extcon/%s/state", mName);
}
}
- /** Does the {@code /sys/class/extcon/<name>} directory exist */
- public static boolean namedExtconDirExists(String name) {
- File extconDir = new File("/sys/class/extcon/" + name);
- return extconDir.exists() && extconDir.isDirectory();
- }
-
/** Does the {@code /sys/class/extcon} directory exist */
public static boolean extconExists() {
File extconDir = new File("/sys/class/extcon");
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index c3543e7..c1c9fbb 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -327,18 +327,23 @@
}
}
- private static int getMaxRescueLevel() {
- return SystemProperties.getBoolean(PROP_DISABLE_FACTORY_RESET_FLAG, false)
- ? LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS : LEVEL_FACTORY_RESET;
+ private static int getMaxRescueLevel(boolean mayPerformFactoryReset) {
+ if (!mayPerformFactoryReset
+ || SystemProperties.getBoolean(PROP_DISABLE_FACTORY_RESET_FLAG, false)) {
+ return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS;
+ }
+ return LEVEL_FACTORY_RESET;
}
/**
* Get the rescue level to perform if this is the n-th attempt at mitigating failure.
*
* @param mitigationCount: the mitigation attempt number (1 = first attempt etc.)
+ * @param mayPerformFactoryReset: whether or not a factory reset may be performed for the given
+ * failure.
* @return the rescue level for the n-th mitigation attempt.
*/
- private static int getRescueLevel(int mitigationCount) {
+ private static int getRescueLevel(int mitigationCount, boolean mayPerformFactoryReset) {
if (mitigationCount == 1) {
return LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS;
} else if (mitigationCount == 2) {
@@ -346,9 +351,9 @@
} else if (mitigationCount == 3) {
return LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS;
} else if (mitigationCount == 4) {
- return Math.min(getMaxRescueLevel(), LEVEL_WARM_REBOOT);
+ return Math.min(getMaxRescueLevel(mayPerformFactoryReset), LEVEL_WARM_REBOOT);
} else if (mitigationCount >= 5) {
- return Math.min(getMaxRescueLevel(), LEVEL_FACTORY_RESET);
+ return Math.min(getMaxRescueLevel(mayPerformFactoryReset), LEVEL_FACTORY_RESET);
} else {
Slog.w(TAG, "Expected positive mitigation count, was " + mitigationCount);
return LEVEL_NONE;
@@ -614,7 +619,8 @@
@FailureReasons int failureReason, int mitigationCount) {
if (!isDisabled() && (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH
|| failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING)) {
- return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount));
+ return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount,
+ mayPerformFactoryReset(failedPackage)));
} else {
return PackageHealthObserverImpact.USER_IMPACT_NONE;
}
@@ -628,7 +634,8 @@
}
if (failureReason == PackageWatchdog.FAILURE_REASON_APP_CRASH
|| failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING) {
- final int level = getRescueLevel(mitigationCount);
+ final int level = getRescueLevel(mitigationCount,
+ mayPerformFactoryReset(failedPackage));
executeRescueLevel(mContext,
failedPackage == null ? null : failedPackage.getPackageName(), level);
return true;
@@ -653,12 +660,7 @@
} catch (PackageManager.NameNotFoundException ignore) {
}
- try {
- ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
- return (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK;
- } catch (PackageManager.NameNotFoundException e) {
- return false;
- }
+ return isPersistentSystemApp(packageName);
}
@Override
@@ -666,7 +668,7 @@
if (isDisabled()) {
return PackageHealthObserverImpact.USER_IMPACT_NONE;
}
- return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount));
+ return mapRescueLevelToUserImpact(getRescueLevel(mitigationCount, true));
}
@Override
@@ -674,7 +676,8 @@
if (isDisabled()) {
return false;
}
- executeRescueLevel(mContext, /*failedPackage=*/ null, getRescueLevel(mitigationCount));
+ executeRescueLevel(mContext, /*failedPackage=*/ null,
+ getRescueLevel(mitigationCount, true));
return true;
}
@@ -683,6 +686,29 @@
return NAME;
}
+ /**
+ * Returns {@code true} if the failing package is non-null and performing a reboot or
+ * prompting a factory reset is an acceptable mitigation strategy for the package's
+ * failure, {@code false} otherwise.
+ */
+ private boolean mayPerformFactoryReset(@Nullable VersionedPackage failingPackage) {
+ if (failingPackage == null) {
+ return false;
+ }
+
+ return isPersistentSystemApp(failingPackage.getPackageName());
+ }
+
+ private boolean isPersistentSystemApp(@NonNull String packageName) {
+ PackageManager pm = mContext.getPackageManager();
+ try {
+ ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
+ return (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
private synchronized void recordDeviceConfigAccess(@NonNull String callingPackage,
@NonNull String namespace) {
// Record it in calling packages to namespace map
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index edf832f..b4413a4 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1889,11 +1889,12 @@
try {
if (!mConfigurationProvider.isDisplayInfoNrAdvancedSupported(
r.callingPackage, Binder.getCallingUserHandle())) {
- telephonyDisplayInfo =
+ r.callback.onDisplayInfoChanged(
getBackwardCompatibleTelephonyDisplayInfo(
- telephonyDisplayInfo);
+ telephonyDisplayInfo));
+ } else {
+ r.callback.onDisplayInfoChanged(telephonyDisplayInfo);
}
- r.callback.onDisplayInfoChanged(telephonyDisplayInfo);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index 7fa93c0..b271d7e 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -490,8 +490,12 @@
private final List<ExtconInfo> mExtconInfos;
WiredAccessoryExtconObserver() {
- mExtconInfos = ExtconInfo.getExtconInfos(".*audio.*");
-
+ mExtconInfos = ExtconInfo.getExtconInfoForTypes(new String[] {
+ ExtconInfo.EXTCON_HEADPHONE,
+ ExtconInfo.EXTCON_MICROPHONE,
+ ExtconInfo.EXTCON_HDMI,
+ ExtconInfo.EXTCON_LINE_OUT,
+ });
}
private void init() {
@@ -521,15 +525,23 @@
@Override
public Pair<Integer, Integer> parseState(ExtconInfo extconInfo, String status) {
if (LOG) Slog.v(TAG, "status " + status);
- int []maskAndState = {0,0};
+ int[] maskAndState = {0, 0};
// extcon event state changes from kernel4.9
// new state will be like STATE=MICROPHONE=1\nHEADPHONE=0
- updateBit(maskAndState, BIT_HEADSET_NO_MIC, status, "HEADPHONE") ;
- updateBit(maskAndState, BIT_HEADSET, status,"MICROPHONE") ;
- updateBit(maskAndState, BIT_HDMI_AUDIO, status,"HDMI") ;
- updateBit(maskAndState, BIT_LINEOUT, status,"LINE-OUT") ;
+ if (extconInfo.hasCableType(ExtconInfo.EXTCON_HEADPHONE)) {
+ updateBit(maskAndState, BIT_HEADSET_NO_MIC, status, ExtconInfo.EXTCON_HEADPHONE);
+ }
+ if (extconInfo.hasCableType(ExtconInfo.EXTCON_MICROPHONE)) {
+ updateBit(maskAndState, BIT_HEADSET, status, ExtconInfo.EXTCON_MICROPHONE);
+ }
+ if (extconInfo.hasCableType(ExtconInfo.EXTCON_HDMI)) {
+ updateBit(maskAndState, BIT_HDMI_AUDIO, status, ExtconInfo.EXTCON_HDMI);
+ }
+ if (extconInfo.hasCableType(ExtconInfo.EXTCON_LINE_OUT)) {
+ updateBit(maskAndState, BIT_LINEOUT, status, ExtconInfo.EXTCON_LINE_OUT);
+ }
if (LOG) Slog.v(TAG, "mask " + maskAndState[0] + " state " + maskAndState[1]);
- return Pair.create(maskAndState[0],maskAndState[1]);
+ return Pair.create(maskAndState[0], maskAndState[1]);
}
@Override
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a369123..0e57236 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -377,6 +377,7 @@
import com.android.server.ThreadPriorityBooster;
import com.android.server.UserspaceRebootLogger;
import com.android.server.Watchdog;
+import com.android.server.am.ComponentAliasResolver.Resolution;
import com.android.server.am.LowMemDetector.MemFactor;
import com.android.server.appop.AppOpsService;
import com.android.server.compat.PlatformCompat;
@@ -7810,6 +7811,17 @@
} else {
killUid(UserHandle.getAppId(uid), UserHandle.getUserId(uid),
"Too many Binders sent to SYSTEM");
+ // We need to run a GC here, because killing the processes involved
+ // actually isn't guaranteed to free up the proxies; in fact, if the
+ // GC doesn't run for a long time, we may even exceed the global
+ // proxy limit for a process (20000), resulting in system_server itself
+ // being killed.
+ // Note that the GC here might not actually clean up all the proxies,
+ // because the binder reference decrements will come in asynchronously;
+ // but if new processes belonging to the UID keep adding proxies, we
+ // will get another callback here, and run the GC again - this time
+ // cleaning up the old proxies.
+ VMRuntime.getRuntime().requestConcurrentGC();
}
}, mHandler);
t.traceEnd(); // setBinderProxies
@@ -12766,9 +12778,26 @@
}
}
}
+ // Replace the alias receivers with their targets.
+ if (newReceivers != null) {
+ for (int i = newReceivers.size() - 1; i >= 0; i--) {
+ final ResolveInfo ri = newReceivers.get(i);
+ final Resolution<ResolveInfo> resolution = mComponentAliasResolver
+ .resolveReceiver(intent, ri, resolvedType, pmFlags, user, callingUid);
+ if (resolution == null) {
+ // It was an alias, but the target was not found.
+ newReceivers.remove(i);
+ continue;
+ }
+ if (resolution.isAlias()) {
+ newReceivers.set(i, resolution.getTarget());
+ }
+ }
+ }
if (newReceivers != null && newReceivers.size() == 0) {
newReceivers = null;
}
+
if (receivers == null) {
receivers = newReceivers;
} else if (newReceivers != null) {
diff --git a/services/core/java/com/android/server/am/ComponentAliasResolver.java b/services/core/java/com/android/server/am/ComponentAliasResolver.java
index 3577f72..cf3e968 100644
--- a/services/core/java/com/android/server/am/ComponentAliasResolver.java
+++ b/services/core/java/com/android/server/am/ComponentAliasResolver.java
@@ -27,7 +27,9 @@
import android.content.pm.ServiceInfo;
import android.os.Binder;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.Log;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
@@ -38,6 +40,7 @@
import java.io.PrintWriter;
import java.util.List;
import java.util.Objects;
+import java.util.function.Supplier;
/**
* Manages and handles component aliases, which is an experimental feature.
@@ -72,6 +75,13 @@
private static final String ALIAS_FILTER_ACTION = "android.intent.action.EXPERIMENTAL_IS_ALIAS";
private static final String META_DATA_ALIAS_TARGET = "alias_target";
+ private static final int PACKAGE_QUERY_FLAGS =
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_ANY_USER
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.GET_META_DATA;
+
public ComponentAliasResolver(ActivityManagerService service) {
mAm = service;
mContext = service.mContext;
@@ -151,24 +161,29 @@
*/
@GuardedBy("mLock")
private void loadFromMetadataLocked() {
- if (DEBUG) Slog.d(TAG, "Scanning aliases...");
+ if (DEBUG) Slog.d(TAG, "Scanning service aliases...");
Intent i = new Intent(ALIAS_FILTER_ACTION);
- List<ResolveInfo> services = mContext.getPackageManager().queryIntentServicesAsUser(
- i,
- PackageManager.MATCH_UNINSTALLED_PACKAGES
- | PackageManager.MATCH_ANY_USER
- | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
- | PackageManager.GET_META_DATA,
- UserHandle.USER_SYSTEM);
+ final List<ResolveInfo> services = mContext.getPackageManager().queryIntentServicesAsUser(
+ i, PACKAGE_QUERY_FLAGS, UserHandle.USER_SYSTEM);
- for (ResolveInfo ri : services) {
+ extractAliases(services);
+
+ if (DEBUG) Slog.d(TAG, "Scanning receiver aliases...");
+ final List<ResolveInfo> receivers = mContext.getPackageManager()
+ .queryBroadcastReceiversAsUser(i, PACKAGE_QUERY_FLAGS, UserHandle.USER_SYSTEM);
+
+ extractAliases(receivers);
+
+ // TODO: Scan for other component types as well.
+ }
+
+ private void extractAliases(List<ResolveInfo> components) {
+ for (ResolveInfo ri : components) {
final ComponentInfo ci = ri.getComponentInfo();
final ComponentName from = ci.getComponentName();
- final ComponentName to = ComponentName.unflattenFromString(
- ci.metaData.getString(META_DATA_ALIAS_TARGET));
- if (!validateComponentName(to)) {
+ final ComponentName to = unflatten(ci.metaData.getString(META_DATA_ALIAS_TARGET));
+ if (to == null) {
continue;
}
if (DEBUG) {
@@ -176,8 +191,6 @@
}
mFromTo.put(from, to);
}
-
- // TODO: Scan for other component types as well.
}
/**
@@ -191,8 +204,11 @@
if (DEBUG) Slog.d(TAG, "Loading aliases overrides ...");
for (String line : mOverrideString.split("\\,+")) {
final String[] fields = line.split("\\:+", 2);
- final ComponentName from = ComponentName.unflattenFromString(fields[0]);
- if (!validateComponentName(from)) {
+ if (TextUtils.isEmpty(fields[0])) {
+ continue;
+ }
+ final ComponentName from = unflatten(fields[0]);
+ if (from == null) {
continue;
}
@@ -200,8 +216,8 @@
if (DEBUG) Slog.d(TAG, "" + from.flattenToShortString() + " [removed]");
mFromTo.remove(from);
} else {
- final ComponentName to = ComponentName.unflattenFromString(fields[1]);
- if (!validateComponentName(to)) {
+ final ComponentName to = unflatten(fields[1]);
+ if (to == null) {
continue;
}
@@ -214,12 +230,13 @@
}
}
- private boolean validateComponentName(ComponentName cn) {
+ private ComponentName unflatten(String name) {
+ final ComponentName cn = ComponentName.unflattenFromString(name);
if (cn != null) {
- return true;
+ return cn;
}
- Slog.e(TAG, "Invalid component name detected: " + cn);
- return false;
+ Slog.e(TAG, "Invalid component name detected: " + name);
+ return null;
}
/**
@@ -277,10 +294,9 @@
}
}
- @Nullable
- public Resolution<ComponentName> resolveService(
- @NonNull Intent service, @Nullable String resolvedType,
- int packageFlags, int userId, int callingUid) {
+ @NonNull
+ public Resolution<ComponentName> resolveComponentAlias(
+ @NonNull Supplier<ComponentName> aliasSupplier) {
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -288,28 +304,17 @@
return new Resolution<>(null, null);
}
- PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
-
- ResolveInfo rInfo = pmi.resolveService(service,
- resolvedType, packageFlags, userId, callingUid);
- ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
- if (sInfo == null) {
- return null; // Service not found.
- }
- final ComponentName alias =
- new ComponentName(sInfo.applicationInfo.packageName, sInfo.name);
+ final ComponentName alias = aliasSupplier.get();
final ComponentName target = mFromTo.get(alias);
if (target != null) {
- // It's an alias. Keep the original intent, and rewrite it.
- service.setOriginalIntent(new Intent(service));
-
- service.setPackage(null);
- service.setComponent(target);
-
if (DEBUG) {
+ Exception stacktrace = null;
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ stacktrace = new RuntimeException("STACKTRACE");
+ }
Slog.d(TAG, "Alias resolved: " + alias.flattenToShortString()
- + " -> " + target.flattenToShortString());
+ + " -> " + target.flattenToShortString(), stacktrace);
}
}
return new Resolution<>(alias, target);
@@ -318,4 +323,69 @@
Binder.restoreCallingIdentity(identity);
}
}
+
+ @Nullable
+ public Resolution<ComponentName> resolveService(
+ @NonNull Intent service, @Nullable String resolvedType,
+ int packageFlags, int userId, int callingUid) {
+ Resolution<ComponentName> result = resolveComponentAlias(() -> {
+ PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+
+ ResolveInfo rInfo = pmi.resolveService(service,
+ resolvedType, packageFlags, userId, callingUid);
+ ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
+ if (sInfo == null) {
+ return null; // Service not found.
+ }
+ return new ComponentName(sInfo.applicationInfo.packageName, sInfo.name);
+ });
+
+ // TODO: To make it consistent with resolveReceiver(), let's ensure the target service
+ // is resolvable, and if not, return null.
+
+ if (result != null && result.isAlias()) {
+ // It's an alias. Keep the original intent, and rewrite it.
+ service.setOriginalIntent(new Intent(service));
+
+ service.setPackage(null);
+ service.setComponent(result.getTarget());
+ }
+ return result;
+ }
+
+ @Nullable
+ public Resolution<ResolveInfo> resolveReceiver(@NonNull Intent intent,
+ @NonNull ResolveInfo receiver, @Nullable String resolvedType,
+ int packageFlags, int userId, int callingUid) {
+ // Resolve this alias.
+ final Resolution<ComponentName> resolution = resolveComponentAlias(() ->
+ receiver.activityInfo.getComponentName());
+ final ComponentName target = resolution.getTarget();
+ if (target == null) {
+ return new Resolution<>(receiver, null); // It's not an alias.
+ }
+
+ // Convert the target component name to a ResolveInfo.
+
+ final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+
+ // Rewrite the intent to search the target intent.
+ // - We don't actually rewrite the intent we deliver to the receiver here, which is what
+ // resolveService() does, because this intent many be send to other receivers as well.
+ // - But we don't have to do that here either, because the actual receiver component
+ // will be set in BroadcastQueue anyway, before delivering the intent to each receiver.
+ // - However, we're not able to set the original intent either, for the time being.
+ Intent i = new Intent(intent);
+ i.setPackage(null);
+ i.setComponent(resolution.getTarget());
+
+ List<ResolveInfo> resolved = pmi.queryIntentReceivers(i,
+ resolvedType, packageFlags, callingUid, userId);
+ if (resolved == null || resolved.size() == 0) {
+ // Target component not found.
+ Slog.w(TAG, "Alias target " + target.flattenToShortString() + " not found");
+ return null;
+ }
+ return new Resolution<>(receiver, resolved.get(0));
+ }
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index cfd2978..fe6a5a3 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -4562,8 +4562,9 @@
}
if (pkgUid != Process.INVALID_UID) {
if (pkgUid != UserHandle.getAppId(uid)) {
- String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not";
- throw new SecurityException("Specified package " + packageName + " under uid "
+ //TODO 195339480: replace true with debug
+ String otherUidMessage = true ? " but it is really " + pkgUid : " but it is not";
+ throw new SecurityException("Specified package \"" + packageName + "\" under uid "
+ UserHandle.getAppId(uid) + otherUidMessage);
}
return new PackageVerificationResult(RestrictionBypass.UNRESTRICTED,
@@ -4618,8 +4619,9 @@
}
if (pkgUid != uid) {
- String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not";
- throw new SecurityException("Specified package " + packageName + " under uid " + uid
+ //TODO 195339480: replace true with debug
+ String otherUidMessage = true ? " but it is really " + pkgUid : " but it is not";
+ throw new SecurityException("Specified package \"" + packageName + "\" under uid " + uid
+ otherUidMessage);
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d12cf70..feda4e2 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -201,7 +201,8 @@
*/
public class AudioService extends IAudioService.Stub
implements AccessibilityManager.TouchExplorationStateChangeListener,
- AccessibilityManager.AccessibilityServicesStateChangeListener {
+ AccessibilityManager.AccessibilityServicesStateChangeListener,
+ AudioSystemAdapter.OnRoutingUpdatedListener {
private static final String TAG = "AS.AudioService";
@@ -315,12 +316,14 @@
private static final int MSG_SET_A2DP_DEV_CONNECTION_STATE = 38;
private static final int MSG_A2DP_DEV_CONFIG_CHANGE = 39;
private static final int MSG_DISPATCH_AUDIO_MODE = 40;
+ private static final int MSG_ROUTING_UPDATED = 41;
// start of messages handled under wakelock
// these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
// and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
private static final int MSG_DISABLE_AUDIO_FOR_UID = 100;
private static final int MSG_INIT_STREAMS_VOLUMES = 101;
+ private static final int MSG_INIT_SPATIALIZER = 102;
// end of messages handled under wakelock
// retry delay in case of failure to indicate system ready to AudioFlinger
@@ -871,6 +874,8 @@
mSfxHelper = new SoundEffectsHelper(mContext);
+ mSpatializerHelper = new SpatializerHelper(this, mAudioSystem);
+
mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
@@ -1035,6 +1040,9 @@
// done with service initialization, continue additional work in our Handler thread
queueMsgUnderWakeLock(mAudioHandler, MSG_INIT_STREAMS_VOLUMES,
0 /* arg1 */, 0 /* arg2 */, null /* obj */, 0 /* delay */);
+ queueMsgUnderWakeLock(mAudioHandler, MSG_INIT_SPATIALIZER,
+ 0 /* arg1 */, 0 /* arg2 */, null /* obj */, 0 /* delay */);
+
}
/**
@@ -1224,6 +1232,22 @@
updateVibratorInfos();
}
+ //-----------------------------------------------------------------
+ // routing monitoring from AudioSystemAdapter
+ @Override
+ public void onRoutingUpdatedFromNative() {
+ sendMsg(mAudioHandler,
+ MSG_ROUTING_UPDATED,
+ SENDMSG_REPLACE, 0, 0, null,
+ /*delay*/ 0);
+ }
+
+ void monitorRoutingChanges(boolean enabled) {
+ mAudioSystem.setRoutingListener(enabled ? this : null);
+ }
+
+
+ //-----------------------------------------------------------------
RoleObserver mRoleObserver;
class RoleObserver implements OnRoleHoldersChangedListener {
@@ -1408,6 +1432,9 @@
}
}
+ // TODO check property if feature enabled
+ mSpatializerHelper.reset(/* featureEnabled */ true);
+
onIndicateSystemReady();
// indicate the end of reconfiguration phase to audio HAL
AudioSystem.setParameters("restarting=false");
@@ -7549,6 +7576,13 @@
mAudioEventWakeLock.release();
break;
+ case MSG_INIT_SPATIALIZER:
+ mSpatializerHelper.init();
+ // TODO read property to see if enabled
+ mSpatializerHelper.setFeatureEnabled(true);
+ mAudioEventWakeLock.release();
+ break;
+
case MSG_CHECK_MUSIC_ACTIVE:
onCheckMusicActive((String) msg.obj);
break;
@@ -7681,6 +7715,10 @@
case MSG_DISPATCH_AUDIO_MODE:
dispatchMode(msg.arg1);
break;
+
+ case MSG_ROUTING_UPDATED:
+ mSpatializerHelper.onRoutingUpdated();
+ break;
}
}
}
@@ -8249,7 +8287,7 @@
}
//==========================================================================================
- private final SpatializerHelper mSpatializerHelper = new SpatializerHelper();
+ private final @NonNull SpatializerHelper mSpatializerHelper;
private void enforceModifyDefaultAudioEffectsPermission() {
if (mContext.checkCallingOrSelfPermission(
@@ -8259,9 +8297,12 @@
}
}
- /** @see AudioManager#getSpatializerImmersiveAudioLevel() */
+ /**
+ * Returns the immersive audio level that the platform is capable of
+ * @see Spatializer#getImmersiveAudioLevel()
+ */
public int getSpatializerImmersiveAudioLevel() {
- return mSpatializerHelper.getImmersiveAudioLevel();
+ return mSpatializerHelper.getCapableImmersiveAudioLevel();
}
/** @see Spatializer#isEnabled() */
@@ -8277,7 +8318,7 @@
/** @see Spatializer#setSpatializerEnabled(boolean) */
public void setSpatializerEnabled(boolean enabled) {
enforceModifyDefaultAudioEffectsPermission();
- mSpatializerHelper.setEnabled(enabled);
+ mSpatializerHelper.setFeatureEnabled(enabled);
}
/** @see Spatializer#canBeSpatialized() */
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
index 6d56780..ac212ee 100644
--- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -17,6 +17,7 @@
package com.android.server.audio;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.media.AudioAttributes;
import android.media.AudioDeviceAttributes;
import android.media.AudioSystem;
@@ -24,6 +25,8 @@
import android.os.SystemClock;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -59,6 +62,9 @@
private ConcurrentHashMap<AudioAttributes, ArrayList<AudioDeviceAttributes>>
mDevicesForAttrCache;
private int[] mMethodCacheHit;
+ private static final Object sRoutingListenerLock = new Object();
+ @GuardedBy("sRoutingListenerLock")
+ private static @Nullable OnRoutingUpdatedListener sRoutingListener;
/**
* should be false except when trying to debug caching errors. When true, the value retrieved
@@ -76,6 +82,23 @@
Log.d(TAG, "---- onRoutingUpdated (from native) ----------");
}
invalidateRoutingCache();
+ final OnRoutingUpdatedListener listener;
+ synchronized (sRoutingListenerLock) {
+ listener = sRoutingListener;
+ }
+ if (listener != null) {
+ listener.onRoutingUpdatedFromNative();
+ }
+ }
+
+ interface OnRoutingUpdatedListener {
+ void onRoutingUpdatedFromNative();
+ }
+
+ static void setRoutingListener(@Nullable OnRoutingUpdatedListener listener) {
+ synchronized (sRoutingListenerLock) {
+ sRoutingListener = listener;
+ }
}
/**
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index 708d9e1..2ca100c 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -17,9 +17,13 @@
package com.android.server.audio;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.media.AudioAttributes;
import android.media.AudioDeviceAttributes;
import android.media.AudioFormat;
+import android.media.AudioSystem;
+import android.media.INativeSpatializerCallback;
+import android.media.ISpatializer;
import android.media.ISpatializerCallback;
import android.media.Spatializer;
import android.os.RemoteCallbackList;
@@ -28,6 +32,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
/**
* A helper class to manage Spatializer related functionality
@@ -35,12 +40,167 @@
public class SpatializerHelper {
private static final String TAG = "AS.SpatializerHelper";
+ private static final boolean DEBUG = true;
+
+ private static void logd(String s) {
+ if (DEBUG) {
+ Log.i(TAG, s);
+ }
+ }
+
+ private final @NonNull AudioSystemAdapter mASA;
+ private final @NonNull AudioService mAudioService;
+
+ //------------------------------------------------------------
+ // Spatializer state machine
+ private static final int STATE_UNINITIALIZED = 0;
+ private static final int STATE_NOT_SUPPORTED = 1;
+ private static final int STATE_DISABLED_UNAVAILABLE = 3;
+ private static final int STATE_ENABLED_UNAVAILABLE = 4;
+ private static final int STATE_ENABLED_AVAILABLE = 5;
+ private static final int STATE_DISABLED_AVAILABLE = 6;
+ private int mState = STATE_UNINITIALIZED;
+
+ /** current level as reported by native Spatializer in callback */
+ private int mSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
+ private int mCapableSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
+ private @Nullable ISpatializer mSpat;
+ private @Nullable SpatializerCallback mSpatCallback;
+
+ // default attributes and format that determine basic availability of spatialization
+ private static final AudioAttributes DEFAULT_ATTRIBUTES = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_MEDIA)
+ .build();
+ private static final AudioFormat DEFAULT_FORMAT = new AudioFormat.Builder()
+ .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+ .setSampleRate(48000)
+ .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1)
+ .build();
+ // device array to store the routing for the default attributes and format, size 1 because
+ // media is never expected to be duplicated
+ private static final AudioDeviceAttributes[] ROUTING_DEVICES = new AudioDeviceAttributes[1];
//---------------------------------------------------------------
// audio device compatibility / enabled
private final ArrayList<AudioDeviceAttributes> mCompatibleAudioDevices = new ArrayList<>(0);
+ //------------------------------------------------------
+ // initialization
+ SpatializerHelper(@NonNull AudioService mother, @NonNull AudioSystemAdapter asa) {
+ mAudioService = mother;
+ mASA = asa;
+ }
+
+ synchronized void init() {
+ Log.i(TAG, "Initializing");
+ if (mState != STATE_UNINITIALIZED) {
+ throw new IllegalStateException(("init() called in state:" + mState));
+ }
+ // is there a spatializer?
+ mSpatCallback = new SpatializerCallback();
+ final ISpatializer spat = AudioSystem.getSpatializer(mSpatCallback);
+ if (spat == null) {
+ Log.i(TAG, "init(): No Spatializer found");
+ mState = STATE_NOT_SUPPORTED;
+ return;
+ }
+ // capabilities of spatializer?
+ try {
+ byte[] levels = spat.getSupportedLevels();
+ if (levels == null
+ || levels.length == 0
+ || (levels.length == 1
+ && levels[0] == Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE)) {
+ Log.e(TAG, "Spatializer is useless");
+ mState = STATE_NOT_SUPPORTED;
+ return;
+ }
+ for (byte level : levels) {
+ logd("found support for level: " + level);
+ if (level == Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL) {
+ logd("Setting Spatializer to LEVEL_MULTICHANNEL");
+ mCapableSpatLevel = level;
+ break;
+ }
+ }
+ } catch (RemoteException e) { /* capable level remains at NONE*/ }
+ if (mCapableSpatLevel == Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE) {
+ mState = STATE_NOT_SUPPORTED;
+ return;
+ }
+ mState = STATE_DISABLED_UNAVAILABLE;
+ // note at this point mSpat is still not instantiated
+ }
+
+ /**
+ * Like init() but resets the state and spatializer levels
+ * @param featureEnabled
+ */
+ synchronized void reset(boolean featureEnabled) {
+ Log.i(TAG, "Resetting");
+ mState = STATE_UNINITIALIZED;
+ mSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
+ mCapableSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
+ init();
+ setFeatureEnabled(featureEnabled);
+ }
+
+ //------------------------------------------------------
+ // routing monitoring
+ void onRoutingUpdated() {
+ switch (mState) {
+ case STATE_UNINITIALIZED:
+ case STATE_NOT_SUPPORTED:
+ return;
+ case STATE_DISABLED_UNAVAILABLE:
+ case STATE_ENABLED_UNAVAILABLE:
+ case STATE_ENABLED_AVAILABLE:
+ case STATE_DISABLED_AVAILABLE:
+ break;
+ }
+ mASA.getDevicesForAttributes(DEFAULT_ATTRIBUTES).toArray(ROUTING_DEVICES);
+ final boolean able =
+ AudioSystem.canBeSpatialized(DEFAULT_ATTRIBUTES, DEFAULT_FORMAT, ROUTING_DEVICES);
+ logd("onRoutingUpdated: can spatialize media 5.1:" + able
+ + " on device:" + ROUTING_DEVICES[0]);
+ setDispatchAvailableState(able);
+ }
+
+ //------------------------------------------------------
+ // spatializer callback from native
+ private final class SpatializerCallback extends INativeSpatializerCallback.Stub {
+
+ public void onLevelChanged(byte level) {
+ logd("SpatializerCallback.onLevelChanged level:" + level);
+ synchronized (SpatializerHelper.this) {
+ mSpatLevel = level;
+ }
+ // TODO use reported spat level to change state
+ }
+
+ public void onHeadTrackingModeChanged(byte mode) {
+ logd("SpatializerCallback.onHeadTrackingModeChanged mode:" + mode);
+ }
+
+ public void onHeadToSoundStagePoseUpdated(float[] headToStage) {
+ if (headToStage == null) {
+ Log.e(TAG, "SpatializerCallback.onHeadToStagePoseUpdated null transform");
+ return;
+ }
+ if (DEBUG) {
+ // 6 values * (4 digits + 1 dot + 2 brackets) = 42 characters
+ StringBuilder t = new StringBuilder(42);
+ for (float val : headToStage) {
+ t.append("[").append(String.format(Locale.ENGLISH, "%.3f", val)).append("]");
+ }
+ logd("SpatializerCallback.onHeadToStagePoseUpdated headToStage:" + t);
+ }
+ }
+ };
+
+ //------------------------------------------------------
+ // compatible devices
/**
* @return a shallow copy of the list of compatible audio devices
*/
@@ -59,37 +219,72 @@
}
//------------------------------------------------------
- // enabled state
-
- // global state of feature
- boolean mFeatureEnabled = false;
- // initialized state, checked after each audio_server start
- boolean mInitialized = false;
+ // states
synchronized boolean isEnabled() {
- return mFeatureEnabled;
+ switch (mState) {
+ case STATE_UNINITIALIZED:
+ case STATE_NOT_SUPPORTED:
+ case STATE_DISABLED_UNAVAILABLE:
+ case STATE_DISABLED_AVAILABLE:
+ return false;
+ case STATE_ENABLED_UNAVAILABLE:
+ case STATE_ENABLED_AVAILABLE:
+ default:
+ return true;
+ }
}
synchronized boolean isAvailable() {
- if (!mInitialized) {
- return false;
- }
- // TODO check device compatibility
- // ...
- return true;
- }
-
- synchronized void setEnabled(boolean enabled) {
- final boolean oldState = mFeatureEnabled;
- mFeatureEnabled = enabled;
- if (oldState != enabled) {
- dispatchEnabledState();
+ switch (mState) {
+ case STATE_UNINITIALIZED:
+ case STATE_NOT_SUPPORTED:
+ case STATE_ENABLED_UNAVAILABLE:
+ case STATE_DISABLED_UNAVAILABLE:
+ return false;
+ case STATE_DISABLED_AVAILABLE:
+ case STATE_ENABLED_AVAILABLE:
+ default:
+ return true;
}
}
- public int getImmersiveAudioLevel() {
- // TODO replace placeholder code with actual effect discovery
- return Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
+ synchronized void setFeatureEnabled(boolean enabled) {
+ switch (mState) {
+ case STATE_UNINITIALIZED:
+ if (enabled) {
+ throw(new IllegalStateException("Can't enable when uninitialized"));
+ }
+ return;
+ case STATE_NOT_SUPPORTED:
+ if (enabled) {
+ Log.e(TAG, "Can't enable when unsupported");
+ }
+ return;
+ case STATE_DISABLED_UNAVAILABLE:
+ case STATE_DISABLED_AVAILABLE:
+ if (enabled) {
+ createSpat();
+ break;
+ } else {
+ // already in disabled state
+ return;
+ }
+ case STATE_ENABLED_UNAVAILABLE:
+ case STATE_ENABLED_AVAILABLE:
+ if (!enabled) {
+ releaseSpat();
+ break;
+ } else {
+ // already in enabled state
+ return;
+ }
+ }
+ setDispatchFeatureEnabledState(enabled);
+ }
+
+ synchronized int getCapableImmersiveAudioLevel() {
+ return mCapableSpatLevel;
}
final RemoteCallbackList<ISpatializerCallback> mStateCallbacks =
@@ -105,12 +300,94 @@
mStateCallbacks.unregister(callback);
}
- private synchronized void dispatchEnabledState() {
+ /**
+ * precondition: mState = STATE_*
+ * isFeatureEnabled() != featureEnabled
+ * @param featureEnabled
+ */
+ private synchronized void setDispatchFeatureEnabledState(boolean featureEnabled) {
+ if (featureEnabled) {
+ switch (mState) {
+ case STATE_DISABLED_UNAVAILABLE:
+ mState = STATE_ENABLED_UNAVAILABLE;
+ break;
+ case STATE_DISABLED_AVAILABLE:
+ mState = STATE_ENABLED_AVAILABLE;
+ break;
+ default:
+ throw(new IllegalStateException("Invalid mState:" + mState
+ + " for enabled true"));
+ }
+ } else {
+ switch (mState) {
+ case STATE_ENABLED_UNAVAILABLE:
+ mState = STATE_DISABLED_UNAVAILABLE;
+ break;
+ case STATE_ENABLED_AVAILABLE:
+ mState = STATE_DISABLED_AVAILABLE;
+ break;
+ default:
+ throw (new IllegalStateException("Invalid mState:" + mState
+ + " for enabled false"));
+ }
+ }
final int nbCallbacks = mStateCallbacks.beginBroadcast();
for (int i = 0; i < nbCallbacks; i++) {
try {
mStateCallbacks.getBroadcastItem(i)
- .dispatchSpatializerEnabledChanged(mFeatureEnabled);
+ .dispatchSpatializerEnabledChanged(featureEnabled);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in dispatchSpatializerEnabledChanged", e);
+ }
+ }
+ mStateCallbacks.finishBroadcast();
+ // TODO persist enabled state
+ }
+
+ private synchronized void setDispatchAvailableState(boolean available) {
+ switch (mState) {
+ case STATE_UNINITIALIZED:
+ case STATE_NOT_SUPPORTED:
+ throw(new IllegalStateException(
+ "Should not update available state in state:" + mState));
+ case STATE_DISABLED_UNAVAILABLE:
+ if (available) {
+ mState = STATE_DISABLED_AVAILABLE;
+ break;
+ } else {
+ // already in unavailable state
+ return;
+ }
+ case STATE_ENABLED_UNAVAILABLE:
+ if (available) {
+ mState = STATE_ENABLED_AVAILABLE;
+ break;
+ } else {
+ // already in unavailable state
+ return;
+ }
+ case STATE_DISABLED_AVAILABLE:
+ if (available) {
+ // already in available state
+ return;
+ } else {
+ mState = STATE_DISABLED_UNAVAILABLE;
+ break;
+ }
+ case STATE_ENABLED_AVAILABLE:
+ if (available) {
+ // already in available state
+ return;
+ } else {
+ mState = STATE_ENABLED_UNAVAILABLE;
+ break;
+ }
+ }
+ final int nbCallbacks = mStateCallbacks.beginBroadcast();
+ for (int i = 0; i < nbCallbacks; i++) {
+ try {
+ mStateCallbacks.getBroadcastItem(i)
+ .dispatchSpatializerAvailableChanged(available);
} catch (RemoteException e) {
Log.e(TAG, "Error in dispatchSpatializerEnabledChanged", e);
}
@@ -119,10 +396,72 @@
}
//------------------------------------------------------
+ // native Spatializer management
+
+ /**
+ * precondition: mState == STATE_DISABLED_*
+ */
+ private void createSpat() {
+ if (mSpat == null) {
+ mSpatCallback = new SpatializerCallback();
+ mSpat = AudioSystem.getSpatializer(mSpatCallback);
+ try {
+ mSpat.setLevel((byte) Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Can't set spatializer level", e);
+ mState = STATE_NOT_SUPPORTED;
+ mCapableSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE;
+ }
+ }
+ }
+
+ /**
+ * precondition: mState == STATE_ENABLED_*
+ */
+ private void releaseSpat() {
+ if (mSpat != null) {
+ mSpatCallback = null;
+ try {
+ mSpat.release();
+ mSpat = null;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Can't set release spatializer cleanly", e);
+ }
+ }
+ }
+
+ //------------------------------------------------------
// virtualization capabilities
synchronized boolean canBeSpatialized(
@NonNull AudioAttributes attributes, @NonNull AudioFormat format) {
- // TODO hook up to spatializer effect for query
- return false;
+ logd("canBeSpatialized usage:" + attributes.getUsage()
+ + " format:" + format.toLogFriendlyString());
+ switch (mState) {
+ case STATE_UNINITIALIZED:
+ case STATE_NOT_SUPPORTED:
+ case STATE_ENABLED_UNAVAILABLE:
+ case STATE_DISABLED_UNAVAILABLE:
+ logd("canBeSpatialized false due to state:" + mState);
+ return false;
+ case STATE_DISABLED_AVAILABLE:
+ case STATE_ENABLED_AVAILABLE:
+ break;
+ }
+
+ // filter on AudioAttributes usage
+ switch (attributes.getUsage()) {
+ case AudioAttributes.USAGE_MEDIA:
+ case AudioAttributes.USAGE_GAME:
+ break;
+ default:
+ logd("canBeSpatialized false due to usage:" + attributes.getUsage());
+ return false;
+ }
+ AudioDeviceAttributes[] devices =
+ // going through adapter to take advantage of routing cache
+ (AudioDeviceAttributes[]) mASA.getDevicesForAttributes(attributes).toArray();
+ final boolean able = AudioSystem.canBeSpatialized(attributes, format, devices);
+ logd("canBeSpatialized returning " + able);
+ return able;
}
}
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 806bcc2..def9685 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -206,6 +206,13 @@
DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {}
/**
+ * Sets the user preferred display mode. Removes the user preferred display mode and sets
+ * default display mode as the mode chosen by HAL, if 'mode' is null
+ * Returns true if the mode set by user is supported by the display.
+ */
+ public void setUserPreferredDisplayModeLocked(Display.Mode mode) { }
+
+ /**
* Sets the requested color mode.
*/
public void setRequestedColorModeLocked(int colorMode) {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 73bcea6..a7b05ca 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -130,6 +130,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicLong;
@@ -213,6 +214,9 @@
private int[] mUserDisabledHdrTypes = {};
private boolean mAreUserDisabledHdrTypesAllowed = true;
+ // Display mode chosen by user.
+ private Display.Mode mUserPreferredMode;
+
// The synchronization root for the display manager.
// This lock guards most of the display manager's state.
// NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call
@@ -581,6 +585,7 @@
updateSettingsLocked();
updateUserDisabledHdrTypesFromSettingsLocked();
+ updateUserPreferredDisplayModeSettingsLocked();
}
mDisplayModeDirector.setDesiredDisplayModeSpecsListener(
@@ -795,9 +800,8 @@
mUserDisabledHdrTypes[i] = Integer.parseInt(userDisabledHdrTypeStrings[i]);
}
} catch (NumberFormatException e) {
- Slog.e(TAG,
- "Failed to parse USER_DISABLED_HDR_FORMATS. "
- + "Clearing the setting.", e);
+ Slog.e(TAG, "Failed to parse USER_DISABLED_HDR_FORMATS. "
+ + "Clearing the setting.", e);
clearUserDisabledHdrTypesLocked();
}
} else {
@@ -813,6 +817,17 @@
}
}
+ private void updateUserPreferredDisplayModeSettingsLocked() {
+ final float refreshRate = Settings.Global.getFloat(mContext.getContentResolver(),
+ Settings.Global.USER_PREFERRED_REFRESH_RATE, 0.0f);
+ final int height = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.USER_PREFERRED_RESOLUTION_HEIGHT, -1);
+ final int width = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH, -1);
+ Display.Mode mode = new Display.Mode(height, width, refreshRate);
+ mUserPreferredMode = isResolutionAndRefreshRateValid(mode) ? mode : null;
+ }
+
private DisplayInfo getDisplayInfoForFrameRateOverride(DisplayEventReceiver.FrameRateOverride[]
frameRateOverrides, DisplayInfo info, int callingUid) {
float frameRateHz = 0;
@@ -1259,6 +1274,9 @@
recordStableDisplayStatsIfNeededLocked(display);
recordTopInsetLocked(display);
}
+ if (mUserPreferredMode != null) {
+ device.setUserPreferredDisplayModeLocked(mUserPreferredMode);
+ }
addDisplayPowerControllerLocked(display);
mDisplayStates.append(displayId, Display.STATE_UNKNOWN);
@@ -1429,6 +1447,39 @@
return mWideColorSpace.getId();
}
+ void setUserPreferredDisplayModeInternal(Display.Mode mode) {
+ synchronized (mSyncRoot) {
+ if (Objects.equals(mUserPreferredMode, mode)) {
+ return;
+ }
+
+ if (mode != null && !isResolutionAndRefreshRateValid(mode)) {
+ throw new IllegalArgumentException("width, height and refresh rate of mode should "
+ + "be greater than 0");
+ }
+ mUserPreferredMode = mode;
+
+ final int resolutionHeight = mode == null ? -1 : mode.getPhysicalHeight();
+ final int resolutionWidth = mode == null ? -1 : mode.getPhysicalWidth();
+ final float refreshRate = mode == null ? 0.0f : mode.getRefreshRate();
+ Settings.Global.putFloat(mContext.getContentResolver(),
+ Settings.Global.USER_PREFERRED_REFRESH_RATE, refreshRate);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.USER_PREFERRED_RESOLUTION_HEIGHT, resolutionHeight);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH, resolutionWidth);
+ mDisplayDeviceRepo.forEachLocked((DisplayDevice device) -> {
+ device.setUserPreferredDisplayModeLocked(mode);
+ });
+ }
+ }
+
+ private Display.Mode getUserPreferredDisplayModeInternal() {
+ synchronized (mSyncRoot) {
+ return mUserPreferredMode;
+ }
+ }
+
void setShouldAlwaysRespectAppRequestedModeInternal(boolean enabled) {
mDisplayModeDirector.setShouldAlwaysRespectAppRequestedMode(enabled);
}
@@ -2019,6 +2070,10 @@
pw.println(" mStableDisplaySize=" + mStableDisplaySize);
pw.println(" mMinimumBrightnessCurve=" + mMinimumBrightnessCurve);
+ if (mUserPreferredMode != null) {
+ pw.println(mUserPreferredMode.toString());
+ }
+
pw.println();
if (!mAreUserDisabledHdrTypesAllowed) {
pw.println(" mUserDisabledHdrTypes: size=" + mUserDisabledHdrTypes.length);
@@ -2097,6 +2152,11 @@
return floatArray;
}
+ private static boolean isResolutionAndRefreshRateValid(Display.Mode mode) {
+ return mode.getPhysicalWidth() > 0 && mode.getPhysicalHeight() > 0
+ && mode.getRefreshRate() > 0.0f;
+ }
+
/**
* This is the object that everything in the display manager locks on.
* We make it an inner class within the {@link DisplayManagerService} to so that it is
@@ -2252,6 +2312,9 @@
int displayId = msg.arg1;
final LogicalDisplay display =
mLogicalDisplayMapper.getDisplayLocked(displayId);
+ if (display == null) {
+ break;
+ }
uids = display.getPendingFrameRateOverrideUids();
display.clearPendingFrameRateOverrideUids();
}
@@ -3084,6 +3147,29 @@
}
@Override // Binder call
+ public void setUserPreferredDisplayMode(Display.Mode mode) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.WRITE_SECURE_SETTINGS,
+ "Permission required to set the user preferred display mode.");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ setUserPreferredDisplayModeInternal(mode);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public Display.Mode getUserPreferredDisplayMode() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return getUserPreferredDisplayModeInternal();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index be4ec71..fce3fd53 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -97,8 +97,6 @@
// specific display.
private static final int GLOBAL_ID = -1;
- private static final int INVALID_DISPLAY_MODE_ID = -1;
-
private static final float FLOAT_TOLERANCE = RefreshRateRange.FLOAT_TOLERANCE;
private final Object mLock = new Object();
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 67df565..dbe17b7 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -16,6 +16,8 @@
package com.android.server.display;
+import static android.view.Display.Mode.INVALID_MODE_ID;
+
import android.app.ActivityThread;
import android.content.Context;
import android.content.res.Resources;
@@ -65,8 +67,6 @@
private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
- private static final int NO_DISPLAY_MODE_ID = 0;
-
private final LongSparseArray<LocalDisplayDevice> mDevices = new LongSparseArray<>();
private final Injector mInjector;
@@ -191,9 +191,11 @@
// This is only set in the runnable returned from requestDisplayStateLocked.
private float mBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
private float mSdrBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
- private int mDefaultModeId;
+ private int mDefaultModeId = INVALID_MODE_ID;
private int mDefaultModeGroup;
- private int mActiveModeId;
+ private int mUserPreferredModeId = INVALID_MODE_ID;
+ private Display.Mode mUserPreferredMode;
+ private int mActiveModeId = INVALID_MODE_ID;
private DisplayModeDirector.DesiredDisplayModeSpecs mDisplayModeSpecs =
new DisplayModeDirector.DesiredDisplayModeSpecs();
private boolean mDisplayModeSpecsInvalid;
@@ -323,7 +325,7 @@
// Check whether SurfaceFlinger or the display device changed the active mode out from
// under us.
- if (mActiveModeId != NO_DISPLAY_MODE_ID
+ if (mActiveModeId != INVALID_MODE_ID
&& mActiveModeId != activeRecord.mMode.getModeId()) {
Slog.d(TAG, "The active mode was changed from SurfaceFlinger or the display"
+ " device to " + activeRecord.mMode);
@@ -334,12 +336,12 @@
// Check whether surface flinger spontaneously changed display config specs out from
// under us. If so, schedule a traversal to reapply our display config specs.
- if (mDisplayModeSpecs.baseModeId != NO_DISPLAY_MODE_ID) {
+ if (mDisplayModeSpecs.baseModeId != INVALID_MODE_ID) {
int activeBaseMode = findMatchingModeIdLocked(modeSpecs.defaultMode);
// If we can't map the defaultMode index to a mode, then the physical display
// modes must have changed, and the code below for handling changes to the
// list of available modes will take care of updating display mode specs.
- if (activeBaseMode == NO_DISPLAY_MODE_ID
+ if (activeBaseMode == INVALID_MODE_ID
|| mDisplayModeSpecs.baseModeId != activeBaseMode
|| mDisplayModeSpecs.primaryRefreshRateRange.min
!= modeSpecs.primaryRefreshRateMin
@@ -366,7 +368,7 @@
}
// For a new display, we need to initialize the default mode ID.
- if (mDefaultModeId == NO_DISPLAY_MODE_ID) {
+ if (mDefaultModeId == INVALID_MODE_ID) {
mDefaultModeId = activeRecord.mMode.getModeId();
mDefaultModeGroup = mActiveSfDisplayMode.group;
} else if (modesAdded && activeModeChanged) {
@@ -383,7 +385,7 @@
// Determine whether the display mode specs' base mode is still there.
if (mSupportedModes.indexOfKey(mDisplayModeSpecs.baseModeId) < 0) {
- if (mDisplayModeSpecs.baseModeId != NO_DISPLAY_MODE_ID) {
+ if (mDisplayModeSpecs.baseModeId != INVALID_MODE_ID) {
Slog.w(TAG,
"DisplayModeSpecs base mode no longer available, using currently"
+ " active mode.");
@@ -392,13 +394,17 @@
mDisplayModeSpecsInvalid = true;
}
+ if (mUserPreferredMode != null) {
+ mUserPreferredModeId = findUserPreferredModeIdLocked(mUserPreferredMode);
+ }
+
// Determine whether the active mode is still there.
if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
- if (mActiveModeId != NO_DISPLAY_MODE_ID) {
+ if (mActiveModeId != INVALID_MODE_ID) {
Slog.w(TAG, "Active display mode no longer available, reverting to default"
+ " mode.");
}
- mActiveModeId = mDefaultModeId;
+ mActiveModeId = getPreferredModeId();
}
// Schedule traversals so that we apply pending changes.
@@ -414,6 +420,12 @@
return mDisplayDeviceConfig;
}
+ private int getPreferredModeId() {
+ return mUserPreferredModeId != INVALID_MODE_ID
+ ? mUserPreferredModeId
+ : mDefaultModeId;
+ }
+
private void loadDisplayDeviceConfig() {
// Load display device config
final Context context = getOverlayContext();
@@ -561,7 +573,7 @@
mInfo.width = mActiveSfDisplayMode.width;
mInfo.height = mActiveSfDisplayMode.height;
mInfo.modeId = mActiveModeId;
- mInfo.defaultModeId = mDefaultModeId;
+ mInfo.defaultModeId = getPreferredModeId();
mInfo.supportedModes = getDisplayModes(mSupportedModes);
mInfo.colorMode = mActiveColorMode;
mInfo.allmSupported = mAllmSupported;
@@ -823,6 +835,17 @@
}
@Override
+ public void setUserPreferredDisplayModeLocked(Display.Mode mode) {
+ final int oldModeId = getPreferredModeId();
+ mUserPreferredMode = mode;
+ mUserPreferredModeId = findUserPreferredModeIdLocked(mode);
+
+ if (oldModeId != getPreferredModeId()) {
+ updateDeviceInfoLocked();
+ }
+ }
+
+ @Override
public void setRequestedColorModeLocked(int colorMode) {
requestColorModeLocked(colorMode);
}
@@ -903,7 +926,7 @@
}
mActiveSfDisplayMode = getModeById(mSfDisplayModes, activeSfModeId);
mActiveModeId = findMatchingModeIdLocked(activeSfModeId);
- if (mActiveModeId == NO_DISPLAY_MODE_ID) {
+ if (mActiveModeId == INVALID_MODE_ID) {
Slog.w(TAG, "In unknown mode after setting allowed modes"
+ ", activeModeId=" + activeSfModeId);
}
@@ -988,6 +1011,7 @@
pw.println("mActiveModeId=" + mActiveModeId);
pw.println("mActiveColorMode=" + mActiveColorMode);
pw.println("mDefaultModeId=" + mDefaultModeId);
+ pw.println("mUserPreferredModeId=" + mUserPreferredModeId);
pw.println("mState=" + Display.stateToString(mState));
pw.println("mBrightnessState=" + mBrightnessState);
pw.println("mBacklightAdapter=" + mBacklightAdapter);
@@ -1010,13 +1034,12 @@
}
private int findDisplayModeIdLocked(int modeId, int modeGroup) {
- int matchingModeId = SurfaceControl.DisplayMode.INVALID_DISPLAY_MODE_ID;
+ int matchingModeId = INVALID_MODE_ID;
DisplayModeRecord record = mSupportedModes.get(modeId);
if (record != null) {
for (SurfaceControl.DisplayMode mode : mSfDisplayModes) {
if (record.hasMatchingMode(mode)) {
- if (matchingModeId
- == SurfaceControl.DisplayMode.INVALID_DISPLAY_MODE_ID) {
+ if (matchingModeId == INVALID_MODE_ID) {
matchingModeId = mode.id;
}
@@ -1030,11 +1053,25 @@
return matchingModeId;
}
+ private int findUserPreferredModeIdLocked(Display.Mode userPreferredMode) {
+ if (userPreferredMode != null) {
+ for (int i = 0; i < mSupportedModes.size(); i++) {
+ Display.Mode supportedMode = mSupportedModes.valueAt(i).mMode;
+ if (userPreferredMode.matches(supportedMode.getPhysicalWidth(),
+ supportedMode.getPhysicalHeight(),
+ supportedMode.getRefreshRate())) {
+ return supportedMode.getModeId();
+ }
+ }
+ }
+ return INVALID_MODE_ID;
+ }
+
private int findMatchingModeIdLocked(int sfModeId) {
SurfaceControl.DisplayMode mode = getModeById(mSfDisplayModes, sfModeId);
if (mode == null) {
Slog.e(TAG, "Invalid display mode ID " + sfModeId);
- return NO_DISPLAY_MODE_ID;
+ return INVALID_MODE_ID;
}
for (int i = 0; i < mSupportedModes.size(); i++) {
DisplayModeRecord record = mSupportedModes.valueAt(i);
@@ -1042,7 +1079,7 @@
return record.mMode.getModeId();
}
}
- return NO_DISPLAY_MODE_ID;
+ return INVALID_MODE_ID;
}
private void updateDeviceInfoLocked() {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 2813236..28261e8 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2384,12 +2384,6 @@
if (mCurSeq <= 0) mCurSeq = 1;
mCurClient = cs;
mCurInputContext = inputContext;
- if (cs.selfReportedDisplayId != displayIdToShowIme) {
- // CursorAnchorInfo API does not work as-is for cross-display scenario. Pretend that
- // InputConnection#requestCursorUpdates() is not implemented in the application so that
- // IMEs will always receive false from this API.
- missingMethods |= MissingMethodFlags.REQUEST_CURSOR_UPDATES;
- }
mCurInputContextMissingMethods = missingMethods;
mCurAttribute = attribute;
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 9f02c3c..a57d7db 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -903,26 +903,8 @@
if (intent.getAction().equals(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED)) {
BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
synchronized (mLock) {
- boolean wasA2dpOn = mGlobalBluetoothA2dpOn;
mActiveBluetoothDevice = btDevice;
mGlobalBluetoothA2dpOn = btDevice != null;
- if (wasA2dpOn != mGlobalBluetoothA2dpOn) {
- Slog.d(TAG, "GlobalBluetoothA2dpOn is changed to '"
- + mGlobalBluetoothA2dpOn + "'");
- UserRecord userRecord = mUserRecords.get(mCurrentUserId);
- if (userRecord != null) {
- for (ClientRecord cr : userRecord.mClientRecords) {
- // mSelectedRouteId will be null for BT and phone speaker.
- if (cr.mSelectedRouteId == null) {
- try {
- cr.mClient.onGlobalA2dpChanged(mGlobalBluetoothA2dpOn);
- } catch (RemoteException e) {
- // Ignore exception
- }
- }
- }
- }
- }
}
}
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 65a3ad0..31a82a3 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -1063,7 +1063,8 @@
// TODO(jaewan): Implement
}
} else if (mCurrentFullUserRecord.mLastMediaButtonReceiverHolder != null) {
- String packageName = mLastMediaButtonReceiverHolder.getPackageName();
+ String packageName =
+ mCurrentFullUserRecord.mLastMediaButtonReceiverHolder.getPackageName();
callback.onMediaKeyEventSessionChanged(packageName, null);
} else {
callback.onMediaKeyEventSessionChanged("", null);
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index 157a1fc..903d02a 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -229,7 +229,7 @@
private boolean matchesActorSignature(@NonNull AndroidPackage targetPackage,
@NonNull AndroidPackage overlayPackage, int userId) {
- String targetOverlayableName = overlayPackage.getOverlayTargetName();
+ String targetOverlayableName = overlayPackage.getOverlayTargetOverlayableName();
if (targetOverlayableName != null) {
try {
OverlayableInfo overlayableInfo = mPackageManager.getOverlayableForTarget(
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index e4ca5b6..ae683d4 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -100,7 +100,8 @@
if (!Objects.equals(theTruth.getOverlayTarget(), oldSettings.targetPackageName)) {
return true;
}
- if (!Objects.equals(theTruth.getOverlayTargetName(), oldSettings.targetOverlayableName)) {
+ if (!Objects.equals(theTruth.getOverlayTargetOverlayableName(),
+ oldSettings.targetOverlayableName)) {
return true;
}
if (oldSettings.isFabricated) {
@@ -343,7 +344,7 @@
}
currentInfo = mSettings.init(overlay, userId, pkg.getOverlayTarget(),
- pkg.getOverlayTargetName(), pkg.getBaseApkPath(),
+ pkg.getOverlayTargetOverlayableName(), pkg.getBaseApkPath(),
isPackageConfiguredMutable(pkg),
isPackageConfiguredEnabled(pkg),
getPackageConfiguredPriority(pkg), pkg.getOverlayCategory(),
diff --git a/services/core/java/com/android/server/om/OverlayReferenceMapper.java b/services/core/java/com/android/server/om/OverlayReferenceMapper.java
index 94a1f3b..539fecf 100644
--- a/services/core/java/com/android/server/om/OverlayReferenceMapper.java
+++ b/services/core/java/com/android/server/om/OverlayReferenceMapper.java
@@ -129,7 +129,7 @@
return Collections.emptyMap();
}
- String overlayable = pkg.getOverlayTargetName();
+ String overlayable = pkg.getOverlayTargetOverlayableName();
Map<String, Set<String>> targetToOverlayables = new HashMap<>();
Set<String> overlayables = new HashSet<>();
overlayables.add(overlayable);
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index f552606..db0f1eb 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -57,6 +57,7 @@
import com.android.server.compat.CompatChange;
import com.android.server.om.OverlayReferenceMapper;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;
import com.android.server.utils.Snapshots;
@@ -299,6 +300,8 @@
/**
* Provides system state to AppsFilter via {@link CurrentStateCallback} after properly guarding
* the data with the package lock.
+ *
+ * Don't call {@link #runWithState} with {@link #mCacheLock} held.
*/
@VisibleForTesting(visibility = PRIVATE)
public interface StateProvider {
@@ -448,7 +451,8 @@
// TODO(b/135203078): Do not use toAppInfo
// TODO(b/167551701): Make changeId non-logging
final boolean enabled = mInjector.getCompatibility().isChangeEnabledInternalNoLogging(
- PackageManager.FILTER_APPLICATION_QUERY, pkg.toAppInfoWithoutState());
+ PackageManager.FILTER_APPLICATION_QUERY,
+ AndroidPackageUtils.generateAppInfoWithoutState(pkg));
if (enabled) {
mDisabledPackages.remove(pkg.getPackageName());
} else {
@@ -921,15 +925,16 @@
}
private void updateShouldFilterCacheForPackage(String packageName) {
- synchronized (mCacheLock) {
- if (mShouldFilterCache != null) {
- mStateProvider.runWithState((settings, users) -> {
- updateShouldFilterCacheForPackage(mShouldFilterCache, null /* skipPackage */,
- settings.get(packageName), settings, users,
- settings.size() /*maxIndex*/);
- });
+ mStateProvider.runWithState((settings, users) -> {
+ synchronized (mCacheLock) {
+ if (mShouldFilterCache == null) {
+ return;
+ }
+ updateShouldFilterCacheForPackage(mShouldFilterCache, null /* skipPackage */,
+ settings.get(packageName), settings, users,
+ settings.size() /*maxIndex*/);
}
- }
+ });
}
private void updateShouldFilterCacheForPackage(WatchedSparseBooleanMatrix cache,
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
index dde9f82..e0f11e2 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -59,6 +59,7 @@
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.PackageInfoUtils.CachedApplicationInfoGenerator;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;
import com.android.server.utils.WatchableImpl;
@@ -684,7 +685,8 @@
AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName());
if (pkg != null) {
- pw.print(" applicationInfo="); pw.println(pkg.toAppInfoWithoutState());
+ pw.print(" applicationInfo=");
+ pw.println(AndroidPackageUtils.generateAppInfoWithoutState(pkg));
}
}
}
diff --git a/services/core/java/com/android/server/pm/DumpState.java b/services/core/java/com/android/server/pm/DumpState.java
index ed00609..6225753 100644
--- a/services/core/java/com/android/server/pm/DumpState.java
+++ b/services/core/java/com/android/server/pm/DumpState.java
@@ -46,6 +46,7 @@
public static final int DUMP_KNOWN_PACKAGES = 1 << 27;
public static final int DUMP_PER_UID_READ_TIMEOUTS = 1 << 28;
public static final int DUMP_SNAPSHOT_STATISTICS = 1 << 29;
+ public static final int DUMP_PROTECTED_BROADCASTS = 1 << 30;
public static final int OPTION_SHOW_FILTERS = 1 << 0;
public static final int OPTION_DUMP_ALL_COMPONENTS = 1 << 1;
diff --git a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java b/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java
index d600ae5..fd00106 100644
--- a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java
@@ -77,6 +77,7 @@
import com.android.server.pm.parsing.PackageCacher;
import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.utils.WatchedArrayMap;
@@ -960,7 +961,8 @@
PackageSetting pkgSetting;
synchronized (mPm.mLock) {
- renamedPkgName = mPm.mSettings.getRenamedPackageLPr(parsedPackage.getRealPackage());
+ renamedPkgName = mPm.mSettings.getRenamedPackageLPr(
+ AndroidPackageUtils.getRealPackageOrNull(parsedPackage));
final String realPkgName = PackageManagerService.getRealPackageName(parsedPackage,
renamedPkgName);
if (realPkgName != null) {
@@ -1310,7 +1312,7 @@
if (originalPkgSetting == null || !mPm.isDeviceUpgrading()) {
return;
}
- if (originalPkgSetting.versionCode == pkg.getVersionCode()) {
+ if (originalPkgSetting.versionCode == pkg.getLongVersionCode()) {
return;
}
@@ -1319,7 +1321,7 @@
Slog.d(TAG, originalPkgSetting.name
+ " clear profile due to version change "
+ originalPkgSetting.versionCode + " != "
- + pkg.getVersionCode());
+ + pkg.getLongVersionCode());
}
}
}
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index d4ebbe3..4709ba1 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -56,6 +56,7 @@
import com.android.internal.util.XmlUtils;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;
@@ -618,7 +619,8 @@
}
// TODO(b/135203078): Remove toAppInfo call? Requires significant additions/changes to PM
- Drawable icon = pkg.toAppInfoWithoutState().loadIcon(mService.mContext.getPackageManager());
+ Drawable icon = AndroidPackageUtils.generateAppInfoWithoutState(pkg)
+ .loadIcon(mService.mContext.getPackageManager());
final Bitmap bitmap;
if (icon instanceof BitmapDrawable) {
diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java
index 1b919f9..98eef07 100644
--- a/services/core/java/com/android/server/pm/KeySetManagerService.java
+++ b/services/core/java/com/android/server/pm/KeySetManagerService.java
@@ -343,7 +343,7 @@
return mKeySets.get(id) != null;
}
- public boolean shouldCheckUpgradeKeySetLocked(PackageSettingBase oldPs, int scanFlags) {
+ public boolean shouldCheckUpgradeKeySetLocked(PackageSetting oldPs, int scanFlags) {
// Can't rotate keys during boot or if sharedUser.
if (oldPs == null || (scanFlags&SCAN_INITIAL) != 0 || oldPs.isSharedUser()
|| !oldPs.keySetData.isUsingUpgradeKeySets()) {
@@ -364,7 +364,7 @@
return true;
}
- public boolean checkUpgradeKeySetLocked(PackageSettingBase oldPS, AndroidPackage pkg) {
+ public boolean checkUpgradeKeySetLocked(PackageSetting oldPS, AndroidPackage pkg) {
// Upgrade keysets are being used. Determine if new package has a superset of the
// required keys.
long[] upgradeKeySets = oldPS.keySetData.getUpgradeKeySets();
diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
index d851e6c..bf1fe31 100644
--- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
+++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
@@ -136,9 +136,9 @@
boolean isUpdatedSystemApp, File appLib32InstallDir) {
// Trying to derive the paths, thus need the raw ABI info from the parsed package, and the
// current state in PackageSetting is irrelevant.
- return deriveNativeLibraryPaths(new Abis(pkg.getPrimaryCpuAbi(), pkg.getSecondaryCpuAbi()),
- appLib32InstallDir, pkg.getPath(), pkg.getBaseApkPath(), pkg.isSystem(),
- isUpdatedSystemApp);
+ return deriveNativeLibraryPaths(new Abis(AndroidPackageUtils.getRawPrimaryCpuAbi(pkg),
+ AndroidPackageUtils.getRawSecondaryCpuAbi(pkg)), appLib32InstallDir, pkg.getPath(),
+ pkg.getBaseApkPath(), pkg.isSystem(), isUpdatedSystemApp);
}
private static NativeLibraryPaths deriveNativeLibraryPaths(final Abis abis,
diff --git a/services/core/java/com/android/server/pm/PackageHandler.java b/services/core/java/com/android/server/pm/PackageHandler.java
index 44a973e..a5a6cae 100644
--- a/services/core/java/com/android/server/pm/PackageHandler.java
+++ b/services/core/java/com/android/server/pm/PackageHandler.java
@@ -656,7 +656,8 @@
StorageManager.class);
VolumeInfo volume =
storage.findVolumeByUuid(
- res.mPkg.getStorageUuid().toString());
+ StorageManager.convert(
+ res.mPkg.getVolumeUuid()).toString());
int packageExternalStorageType =
PackageManagerService.getPackageExternalStorageType(volume,
res.mPkg.isExternalStorage());
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index ceee0fa..0f5f293 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -128,6 +128,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.ExceptionUtils;
+import android.util.IntArray;
import android.util.MathUtils;
import android.util.Slog;
import android.util.SparseArray;
@@ -280,6 +281,7 @@
private final PackageInstallerService.InternalCallback mCallback;
private final Context mContext;
private final PackageManagerService mPm;
+ private final Installer mInstaller;
private final Handler mHandler;
private final PackageSessionProvider mSessionProvider;
private final SilentUpdatePolicy mSilentUpdatePolicy;
@@ -587,7 +589,7 @@
@Override
public void installSession(IntentSender statusReceiver) {
assertCallerIsOwnerOrRootOrSystem();
- assertNotChildLocked("StagedSession#installSession");
+ assertNotChild("StagedSession#installSession");
Preconditions.checkArgument(isCommitted() && isSessionReady());
// Since staged sessions are installed during boot, the original reference to status
@@ -599,12 +601,12 @@
private void updateRemoteStatusReceiver(IntentSender remoteStatusReceiver) {
synchronized (mLock) {
- mRemoteStatusReceiver = remoteStatusReceiver;
+ setRemoteStatusReceiver(remoteStatusReceiver);
if (isMultiPackage()) {
final IntentSender childIntentSender = new ChildStatusIntentReceiver(
mChildSessions.clone(), remoteStatusReceiver).getIntentSender();
for (int i = mChildSessions.size() - 1; i >= 0; --i) {
- mChildSessions.valueAt(i).mRemoteStatusReceiver = childIntentSender;
+ mChildSessions.valueAt(i).setRemoteStatusReceiver(childIntentSender);
}
}
}
@@ -684,7 +686,7 @@
public void abandon() {
final Runnable r;
synchronized (mLock) {
- assertNotChildLocked("StagedSession#abandon");
+ assertNotChild("StagedSession#abandon");
assertCallerIsOwnerOrRoot();
if (isInTerminalState()) {
// We keep the session in the database if it's in a finalized state. It will be
@@ -754,7 +756,7 @@
public void verifySession() {
assertCallerIsOwnerOrRootOrSystem();
Preconditions.checkArgument(isCommitted());
- Preconditions.checkArgument(!mSessionApplied && !mSessionFailed);
+ Preconditions.checkArgument(!isInTerminalState());
notifyStartPreRebootVerification();
verify();
}
@@ -918,8 +920,10 @@
}
DevicePolicyManagerInternal dpmi =
LocalServices.getService(DevicePolicyManagerInternal.class);
+ // It may wait for a long time to finish {@code dpmi.canSilentlyInstallPackage}.
+ // Please don't acquire mLock before calling {@code dpmi.canSilentlyInstallPackage}.
return dpmi != null && dpmi.canSilentlyInstallPackage(
- mInstallSource.installerPackageName, mInstallerUid);
+ getInstallSource().installerPackageName, mInstallerUid);
}
private static final int USER_ACTION_NOT_NEEDED = 0;
@@ -1008,8 +1012,10 @@
return USER_ACTION_REQUIRED;
}
+ @SuppressWarnings("GuardedBy" /*mPm.mInstaller is {@code final} field*/)
public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
- Context context, PackageManagerService pm, PackageSessionProvider sessionProvider,
+ Context context, PackageManagerService pm,
+ PackageSessionProvider sessionProvider,
SilentUpdatePolicy silentUpdatePolicy, Looper looper, StagingManager stagingManager,
int sessionId, int userId, int installerUid, @NonNull InstallSource installSource,
SessionParams params, long createdMillis, long committedMillis,
@@ -1022,6 +1028,7 @@
mCallback = callback;
mContext = context;
mPm = pm;
+ mInstaller = (mPm != null) ? mPm.mInstaller : null;
mSessionProvider = sessionProvider;
mSilentUpdatePolicy = silentUpdatePolicy;
mHandler = new Handler(looper, mHandlerCallback);
@@ -1131,6 +1138,10 @@
private SessionInfo generateInfoInternal(boolean includeIcon, boolean scrubData) {
final SessionInfo info = new SessionInfo();
+ final float progress;
+ synchronized (mProgressLock) {
+ progress = mProgress;
+ }
synchronized (mLock) {
info.sessionId = sessionId;
info.userId = userId;
@@ -1138,7 +1149,7 @@
info.installerAttributionTag = mInstallSource.installerAttributionTag;
info.resolvedBaseCodePath = (mResolvedBaseFile != null) ?
mResolvedBaseFile.getAbsolutePath() : null;
- info.progress = mProgress;
+ info.progress = progress;
info.sealed = mSealed;
info.isCommitted = mCommitted.get();
info.active = mActiveCount.get() > 0;
@@ -1364,7 +1375,7 @@
return;
}
- final String initiatingPackageName = mInstallSource.initiatingPackageName;
+ final String initiatingPackageName = getInstallSource().initiatingPackageName;
final AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
appOps.checkPackage(Binder.getCallingUid(), initiatingPackageName);
@@ -1585,7 +1596,7 @@
if (params.sizeBytes > 0) {
final long delta = progress - last.value;
last.value = progress;
- synchronized (mLock) {
+ synchronized (mProgressLock) {
setClientProgressLocked(mClientProgress
+ (float) delta / (float) params.sizeBytes);
}
@@ -1897,13 +1908,6 @@
}
}
- /** {@hide} */
- private class StreamingException extends Exception {
- StreamingException(Throwable cause) {
- super(cause);
- }
- }
-
/**
* Returns whether or not a package can be installed while Secure FRP is enabled.
* <p>
@@ -1973,7 +1977,7 @@
}
}
- mRemoteStatusReceiver = statusReceiver;
+ setRemoteStatusReceiver(statusReceiver);
// After updating the observer, we can skip re-sealing.
if (mSealed) {
@@ -2140,7 +2144,7 @@
private void onSystemDataLoaderUnrecoverable() {
final PackageManagerService packageManagerService = mPm;
- final String packageName = mPackageName;
+ final String packageName = getPackageName();
if (TextUtils.isEmpty(packageName)) {
// The package has not been installed.
return;
@@ -2303,9 +2307,7 @@
*/
@WorkerThread
private boolean sendPendingUserActionIntentIfNeeded() {
- synchronized (mLock) {
- assertNotChildLocked("PackageInstallerSession#sendPendingUserActionIntentIfNeeded");
- }
+ assertNotChild("PackageInstallerSession#sendPendingUserActionIntentIfNeeded");
return sessionContains(PackageInstallerSession::checkUserActionRequirement);
}
@@ -2315,7 +2317,7 @@
if (isInstallerDeviceOwnerOrAffiliatedProfileOwner()) {
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.INSTALL_PACKAGE)
- .setAdmin(mInstallSource.installerPackageName)
+ .setAdmin(getInstallSource().installerPackageName)
.write();
}
@@ -2392,6 +2394,12 @@
}
}
+ private void setRemoteStatusReceiver(IntentSender remoteStatusReceiver) {
+ synchronized (mLock) {
+ mRemoteStatusReceiver = remoteStatusReceiver;
+ }
+ }
+
private void verifyNonStaged()
throws PackageManagerException {
final VerificationParams verifyingSession = prepareForVerification();
@@ -2882,7 +2890,7 @@
final List<File> addedFiles = getAddedApksLocked();
if (addedFiles.isEmpty()) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- String.format("Session: %d. No packages staged in %s", sessionId,
+ TextUtils.formatSimple("Session: %d. No packages staged in %s", sessionId,
stageDir.getAbsolutePath()));
}
@@ -2982,7 +2990,7 @@
final List<File> addedFiles = getAddedApksLocked();
if (addedFiles.isEmpty() && removeSplitList.size() == 0) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- String.format("Session: %d. No packages staged in %s", sessionId,
+ TextUtils.formatSimple("Session: %d. No packages staged in %s", sessionId,
stageDir.getAbsolutePath()));
}
@@ -3316,12 +3324,19 @@
DexMetadataHelper.isFsVerityRequired());
}
+ private IncrementalFileStorages getIncrementalFileStorages() {
+ synchronized (mLock) {
+ return mIncrementalFileStorages;
+ }
+ }
+
private void storeBytesToInstallationFile(final String localPath, final String absolutePath,
final byte[] bytes) throws IOException {
- if (!isIncrementalInstallation() || mIncrementalFileStorages == null) {
+ final IncrementalFileStorages incrementalFileStorages = getIncrementalFileStorages();
+ if (!isIncrementalInstallation() || incrementalFileStorages == null) {
FileUtils.bytesToFile(absolutePath, bytes);
} else {
- mIncrementalFileStorages.makeFile(localPath, bytes);
+ incrementalFileStorages.makeFile(localPath, bytes);
}
}
@@ -3583,7 +3598,7 @@
throws PackageManagerException {
for (String instructionSet : instructionSets) {
try {
- mPm.mInstaller.createOatDir(fromDir.getAbsolutePath(), instructionSet);
+ mInstaller.createOatDir(fromDir.getAbsolutePath(), instructionSet);
} catch (InstallerException e) {
throw PackageManagerException.from(e);
}
@@ -3593,11 +3608,12 @@
private void linkFile(String relativePath, String fromBase, String toBase) throws IOException {
try {
// Try
- if (mIncrementalFileStorages != null && mIncrementalFileStorages.makeLink(relativePath,
+ final IncrementalFileStorages incrementalFileStorages = getIncrementalFileStorages();
+ if (incrementalFileStorages != null && incrementalFileStorages.makeLink(relativePath,
fromBase, toBase)) {
return;
}
- mPm.mInstaller.linkFile(relativePath, fromBase, toBase);
+ mInstaller.linkFile(relativePath, fromBase, toBase);
} catch (InstallerException | IOException e) {
throw new IOException("failed linkOrCreateDir(" + relativePath + ", "
+ fromBase + ", " + toBase + ")", e);
@@ -3767,7 +3783,7 @@
private void abandonNonStaged() {
synchronized (mLock) {
- assertNotChildLocked("abandonNonStaged");
+ assertNotChild("abandonNonStaged");
assertCallerIsOwnerOrRoot();
if (mRelinquished) {
if (LOGD) Slog.d(TAG, "Ignoring abandon after commit relinquished control");
@@ -3779,8 +3795,7 @@
maybeCleanUpChildSessions();
}
- @GuardedBy("mLock")
- private void assertNotChildLocked(String cookie) {
+ private void assertNotChild(String cookie) {
if (hasParentSessionId()) {
throw new IllegalStateException(cookie + " can't be called on a child session, id="
+ sessionId + " parentId=" + getParentSessionId());
@@ -4324,7 +4339,7 @@
if (incrementalFileStorages != null) {
incrementalFileStorages.cleanUpAndMarkComplete();
}
- mPm.mInstaller.rmPackageDir(stageDir.getAbsolutePath());
+ mInstaller.rmPackageDir(stageDir.getAbsolutePath());
} catch (InstallerException ignored) {
}
}
@@ -4350,7 +4365,7 @@
if (incrementalFileStorages != null) {
incrementalFileStorages.cleanUpAndMarkComplete();
}
- mPm.mInstaller.rmPackageDir(stageDir.getAbsolutePath());
+ mInstaller.rmPackageDir(stageDir.getAbsolutePath());
} catch (InstallerException ignored) {
}
}
@@ -4382,8 +4397,14 @@
params.dump(pw);
- pw.printPair("mClientProgress", mClientProgress);
- pw.printPair("mProgress", mProgress);
+ final float clientProgress;
+ final float progress;
+ synchronized (mProgressLock) {
+ clientProgress = mClientProgress;
+ progress = mProgress;
+ }
+ pw.printPair("mClientProgress", clientProgress);
+ pw.printPair("mProgress", progress);
pw.printPair("mCommitted", mCommitted);
pw.printPair("mSealed", mSealed);
pw.printPair("mPermissionsManuallyAccepted", mPermissionsManuallyAccepted);
@@ -4693,7 +4714,7 @@
* @param installerThread Thread to be used for callbacks of this session
* @param sessionsDir The directory the sessions are stored in
*
- * @param sessionProvider
+ * @param sessionProvider to get the other PackageInstallerSession instance by sessionId.
* @return The newly created session
*/
public static PackageInstallerSession readFromXml(@NonNull TypedXmlPullParser in,
@@ -4781,7 +4802,7 @@
List<String> grantedRuntimePermissions = new ArrayList<>();
List<String> whitelistedRestrictedPermissions = new ArrayList<>();
int autoRevokePermissionsMode = MODE_DEFAULT;
- List<Integer> childSessionIds = new ArrayList<>();
+ IntArray childSessionIds = new IntArray();
List<InstallationFile> files = new ArrayList<>();
ArrayMap<String, List<Checksum>> checksums = new ArrayMap<>();
ArrayMap<String, byte[]> signatures = new ArrayMap<>();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2c2884f..2dfd409 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -350,6 +350,10 @@
import com.android.server.pm.permission.LegacyPermissionManagerService;
import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.pkg.AndroidPackageApi;
+import com.android.server.pm.pkg.PackageState;
+import com.android.server.pm.pkg.PackageStateImpl;
+import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import com.android.server.pm.verify.domain.DomainVerificationService;
import com.android.server.pm.verify.domain.DomainVerificationUtils;
@@ -1852,6 +1856,9 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected interface Computer {
+ @Nullable
+ PackageState getPackageState(@NonNull String packageName);
+
/**
* Every method must be annotated.
*/
@@ -3414,6 +3421,16 @@
return mSettings.getPackageLPr(packageName);
}
+ @Nullable
+ @Override
+ public PackageState getPackageState(@NonNull String packageName) {
+ int callingUid = Binder.getCallingUid();
+ packageName = resolveInternalPackageNameInternalLocked(
+ packageName, PackageManager.VERSION_CODE_HIGHEST, callingUid);
+ PackageSetting pkgSetting = mSettings.getPackageLPr(packageName);
+ return pkgSetting == null ? null : PackageStateImpl.copy(pkgSetting);
+ }
+
public final ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
final int callingUid = Binder.getCallingUid();
if (getInstantAppPackageName(callingUid) != null) {
@@ -5180,6 +5197,14 @@
return super.getPackageSettingInternal(packageName, callingUid);
}
}
+
+ @Nullable
+ public final PackageState getPackageState(@NonNull String packageName) {
+ synchronized (mLock) {
+ return super.getPackageState(packageName);
+ }
+ }
+
public final ParceledListSlice<PackageInfo> getInstalledPackagesBody(int flags, int userId,
int callingUid) {
synchronized (mLock) {
@@ -5515,6 +5540,17 @@
current.release();
}
}
+
+ @Nullable
+ public final PackageState getPackageState(@NonNull String packageName) {
+ ThreadComputer current = live();
+ try {
+ return current.mComputer.getPackageState(packageName);
+ } finally {
+ current.release();
+ }
+ }
+
public final ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
ThreadComputer current = snapshot();
try {
@@ -12205,7 +12241,7 @@
@Nullable UserHandle user, String cpuAbiOverride) throws PackageManagerException {
final String renamedPkgName = mSettings.getRenamedPackageLPr(
- parsedPackage.getRealPackage());
+ AndroidPackageUtils.getRealPackageOrNull(parsedPackage));
final String realPkgName = getRealPackageName(parsedPackage, renamedPkgName);
if (realPkgName != null) {
ensurePackageRenamed(parsedPackage, renamedPkgName);
@@ -12325,7 +12361,8 @@
} else {
pkgSetting = result.mPkgSetting;
if (originalPkgSetting != null) {
- mSettings.addRenamedPackageLPw(parsedPackage.getRealPackage(),
+ mSettings.addRenamedPackageLPw(
+ AndroidPackageUtils.getRealPackageOrNull(parsedPackage),
originalPkgSetting.name);
mTransferredPackages.add(originalPkgSetting.name);
} else {
@@ -12416,7 +12453,7 @@
static @Nullable String getRealPackageName(@NonNull AndroidPackage pkg,
@Nullable String renamedPkgName) {
if (isPackageRenamed(pkg, renamedPkgName)) {
- return pkg.getRealPackage();
+ return AndroidPackageUtils.getRealPackageOrNull(pkg);
}
return null;
}
@@ -12686,7 +12723,7 @@
destCodeFile, parsedPackage.getNativeLibraryRootDir(),
AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage),
AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage),
- parsedPackage.getVersionCode(), pkgFlags, pkgPrivateFlags, user,
+ parsedPackage.getLongVersionCode(), pkgFlags, pkgPrivateFlags, user,
true /*allowInstall*/, instantApp, virtualPreload,
UserManagerService.getInstance(), usesStaticLibraries,
parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups(),
@@ -12738,11 +12775,8 @@
pkgSetting.getPkgState().setUpdatedSystemApp(true);
}
- parsedPackage
- .setSeInfo(SELinuxMMAC.getSeInfo(parsedPackage, sharedUserSetting,
- injector.getCompatibility()))
- .setSeInfoUser(SELinuxUtil.assignSeinfoUser(pkgSetting.readUserState(
- userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId)));
+ parsedPackage.setSeInfo(SELinuxMMAC.getSeInfo(parsedPackage, sharedUserSetting,
+ injector.getCompatibility()));
if (parsedPackage.isSystem()) {
configurePackageComponents(parsedPackage);
@@ -13040,7 +13074,6 @@
if (!parsedPackage.isSystem()) {
// Only system apps can use these features.
parsedPackage.clearOriginalPackages()
- .setRealPackage(null)
.clearAdoptPermissions();
}
@@ -13384,7 +13417,7 @@
// If the target is already installed or 'overlay-config-signature' tag in
// SystemConfig is set, check this here to augment the last line of defense
// which is OMS.
- if (pkg.getOverlayTargetName() == null) {
+ if (pkg.getOverlayTargetOverlayableName() == null) {
final PackageSetting targetPkgSetting =
mSettings.getPackageLPr(pkg.getOverlayTarget());
if (targetPkgSetting != null) {
@@ -13560,11 +13593,8 @@
// The instance stored in PackageManagerService is special cased to be non-user
// specific, so initialize all the needed fields here.
- mAndroidApplication = pkg.toAppInfoWithoutState();
- mAndroidApplication.flags = PackageInfoUtils.appInfoFlags(pkg, pkgSetting);
- mAndroidApplication.privateFlags =
- PackageInfoUtils.appInfoPrivateFlags(pkg, pkgSetting);
- mAndroidApplication.initForUser(UserHandle.USER_SYSTEM);
+ mAndroidApplication = PackageInfoUtils.generateApplicationInfo(pkg, 0,
+ new PackageUserState(), UserHandle.USER_SYSTEM, pkgSetting);
if (!mResolverReplaced) {
mResolveActivity.applicationInfo = mAndroidApplication;
@@ -13713,11 +13743,8 @@
// The instance created in PackageManagerService is special cased to be non-user
// specific, so initialize all the needed fields here.
- ApplicationInfo appInfo = pkg.toAppInfoWithoutState();
- appInfo.flags = PackageInfoUtils.appInfoFlags(pkg, pkgSetting);
- appInfo.privateFlags =
- PackageInfoUtils.appInfoPrivateFlags(pkg, pkgSetting);
- appInfo.initForUser(UserHandle.USER_SYSTEM);
+ ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo(pkg, 0,
+ new PackageUserState(), UserHandle.USER_SYSTEM, pkgSetting);
// Set up information for custom user intent resolution activity.
mResolveActivity.applicationInfo = appInfo;
@@ -19175,6 +19202,7 @@
pw.println(" compiler-stats: dump compiler statistics");
pw.println(" service-permissions: dump permissions required by services");
pw.println(" snapshot: dump snapshot statistics");
+ pw.println(" protected-broadcasts: print list of protected broadcast actions");
pw.println(" known-packages: dump known packages");
pw.println(" <package.name>: info about given package");
return;
@@ -19334,6 +19362,8 @@
opti++;
}
}
+ } else if ("protected-broadcasts".equals(cmd)) {
+ dumpState.setDump(DumpState.DUMP_PROTECTED_BROADCASTS);
} else if ("write".equals(cmd)) {
synchronized (mLock) {
writeSettingsLPrTEMP();
@@ -19735,6 +19765,22 @@
mSnapshotStatistics.dump(pw, " ", now, hits, level, dumpState.isBrief());
}
}
+
+ if (!checkin
+ && dumpState.isDumping(DumpState.DUMP_PROTECTED_BROADCASTS)
+ && packageName == null) {
+ if (dumpState.onTitlePrinted()) {
+ pw.println();
+ }
+ pw.println("Protected broadcast actions:");
+ synchronized (mProtectedBroadcasts) {
+ for (int i = 0; i < mProtectedBroadcasts.size(); i++) {
+ pw.print(" ");
+ pw.println(mProtectedBroadcasts.valueAt(i));
+ }
+ }
+
+ }
}
/**
@@ -20367,8 +20413,10 @@
}
final PackageSetting ps;
+ final String seInfoUser;
synchronized (mLock) {
ps = mSettings.getPackageLPr(pkg.getPackageName());
+ seInfoUser = SELinuxUtil.getSeinfoUser(ps.readUserState(userId));
}
final String volumeUuid = pkg.getVolumeUuid();
final String packageName = pkg.getPackageName();
@@ -20379,7 +20427,7 @@
Preconditions.checkNotNull(pkgSeInfo);
- final String seInfo = pkgSeInfo + (pkg.getSeInfoUser() != null ? pkg.getSeInfoUser() : "");
+ final String seInfo = pkgSeInfo + seInfoUser;
final int targetSdkVersion = pkg.getTargetSdkVersion();
return batch.createAppData(volumeUuid, packageName, userId, flags, appId, seInfo,
@@ -20616,7 +20664,8 @@
packageAbiOverride = ps.cpuAbiOverrideString;
appId = UserHandle.getAppId(pkg.getUid());
seinfo = AndroidPackageUtils.getSeInfo(pkg, ps);
- label = String.valueOf(pm.getApplicationLabel(pkg.toAppInfoWithoutState()));
+ label = String.valueOf(pm.getApplicationLabel(
+ AndroidPackageUtils.generateAppInfoWithoutState(pkg)));
targetSdkVersion = pkg.getTargetSdkVersion();
freezer = freezePackage(packageName, "movePackageInternal");
installedUserIds = ps.queryInstalledUsers(mUserManager.getUserIds(), true);
@@ -20782,8 +20831,9 @@
return;
}
- final StorageManager storage = mInjector.getSystemService(StorageManager.class);
- VolumeInfo volume = storage.findVolumeByUuid(pkg.getStorageUuid().toString());
+ final StorageManager storage = mInjector.getSystemService(StorageManager.class);;
+ VolumeInfo volume = storage.findVolumeByUuid(
+ StorageManager.convert(pkg.getVolumeUuid()).toString());
int packageExternalStorageType = getPackageExternalStorageType(volume, pkg.isExternalStorage());
if (!isPreviousLocationExternal && pkg.isExternalStorage()) {
@@ -21558,6 +21608,12 @@
return PackageManagerService.this.getPackage(packageName);
}
+ @Nullable
+ @Override
+ public AndroidPackageApi getAndroidPackage(@NonNull String packageName) {
+ return PackageManagerService.this.getPackage(packageName);
+ }
+
@Override
public AndroidPackage getPackage(int uid) {
return PackageManagerService.this.getPackage(uid);
@@ -21569,6 +21625,12 @@
return PackageManagerService.this.getPackageSetting(packageName);
}
+ @Nullable
+ @Override
+ public PackageState getPackageState(@NonNull String packageName) {
+ return PackageManagerService.this.getPackageState(packageName);
+ }
+
@Override
public PackageList getPackageList(PackageListObserver observer) {
synchronized (mLock) {
@@ -22281,11 +22343,12 @@
@Override
public void forEachPackageSetting(Consumer<PackageSetting> actionLocked) {
- synchronized (mLock) {
- for (int index = 0; index < mSettings.getPackagesLocked().size(); index++) {
- actionLocked.accept(mSettings.getPackagesLocked().valueAt(index));
- }
- }
+ PackageManagerService.this.forEachPackageSetting(actionLocked);
+ }
+
+ @Override
+ public void forEachPackageState(boolean locked, Consumer<PackageState> action) {
+ PackageManagerService.this.forEachPackageState(locked, action);
}
@Override
@@ -22764,6 +22827,11 @@
return mComputer.getPackageSettingInternal(packageName, callingUid);
}
+ @Nullable
+ private PackageState getPackageState(String packageName) {
+ return mComputer.getPackageState(packageName);
+ }
+
void forEachPackage(Consumer<AndroidPackage> actionLocked) {
synchronized (mLock) {
int numPackages = mPackages.size();
@@ -22773,6 +22841,29 @@
}
}
+ private void forEachPackageSetting(Consumer<PackageSetting> actionLocked) {
+ synchronized (mLock) {
+ int size = mSettings.getPackagesLocked().size();
+ for (int index = 0; index < size; index++) {
+ actionLocked.accept(mSettings.getPackagesLocked().valueAt(index));
+ }
+ }
+ }
+
+ private void forEachPackageState(boolean locked, Consumer<PackageState> action) {
+ if (locked) {
+ forEachPackageSetting(action::accept);
+ } else {
+ List<PackageState> packageStates = new ArrayList<>();
+ forEachPackageSetting(pkgSetting ->
+ packageStates.add(PackageStateImpl.copy(pkgSetting)));
+ int size = packageStates.size();
+ for (int index = 0; index < size; index++) {
+ action.accept(packageStates.get(index));
+ }
+ }
+ }
+
void forEachInstalledPackage(@NonNull Consumer<AndroidPackage> actionLocked,
@UserIdInt int userId) {
synchronized (mLock) {
@@ -23388,6 +23479,37 @@
return new IntentSender(target);
}
+ @Override
+ public boolean mayPackageQuery(String sourcePackageName, String targetPackageName, int userId) {
+ if (!mUserManager.exists(userId)) return false;
+ final int callingUid = Binder.getCallingUid();
+ enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
+ false /*checkShell*/, "may package query");
+ synchronized (mLock) {
+ final PackageSetting sourceSetting = getPackageSetting(sourcePackageName);
+ final PackageSetting targetSetting = getPackageSetting(targetPackageName);
+ if (sourceSetting == null || targetSetting == null) {
+ throw new ParcelableException(new PackageManager.NameNotFoundException("Package(s) "
+ + (sourceSetting == null ? sourcePackageName + " " : "")
+ + (targetSetting == null ? targetPackageName + " " : "")
+ + "not found."));
+ }
+ final boolean filterSource =
+ shouldFilterApplicationLocked(sourceSetting, callingUid, userId);
+ final boolean filterTarget =
+ shouldFilterApplicationLocked(targetSetting, callingUid, userId);
+ // The caller must have visibility of the both packages
+ if (filterSource || filterTarget) {
+ throw new ParcelableException(new PackageManager.NameNotFoundException("Package(s) "
+ + (filterSource ? sourcePackageName + " " : "")
+ + (filterTarget ? targetPackageName + " " : "")
+ + "not found."));
+ }
+ final int sourcePackageUid = UserHandle.getUid(userId, sourceSetting.appId);
+ return !shouldFilterApplicationLocked(targetSetting, sourcePackageUid, userId);
+ }
+ }
+
private static class TempUserState {
public final int enabledState;
@Nullable
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 3763262..249423e 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -20,7 +20,10 @@
import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.SharedLibraryInfo;
+import android.content.pm.SigningInfo;
import android.content.pm.UserInfo;
+import android.content.pm.pkg.PackageUserState;
import android.service.pm.PackageProto;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -30,6 +33,7 @@
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.LegacyPermissionDataProvider;
import com.android.server.pm.permission.LegacyPermissionState;
+import com.android.server.pm.pkg.AndroidPackageApi;
import com.android.server.pm.pkg.PackageStateUnserialized;
import com.android.server.utils.SnapshotCache;
@@ -189,7 +193,14 @@
return pkg;
}
- public int getSharedUserId() {
+ public Integer getSharedUserId() {
+ if (sharedUser != null) {
+ return sharedUser.userId;
+ }
+ return null;
+ }
+
+ public int getSharedUserIdInt() {
if (sharedUser != null) {
return sharedUser.userId;
}
@@ -446,4 +457,8 @@
mDomainSetId = domainSetId;
return this;
}
+
+ public String getPackageName() {
+ return name;
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index d9c4d316..62c8477 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -42,6 +42,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.PackageState;
import java.io.File;
import java.util.Arrays;
@@ -53,7 +54,7 @@
/**
* Settings base class for pending and resolved classes.
*/
-public abstract class PackageSettingBase extends SettingBase {
+public abstract class PackageSettingBase extends SettingBase implements PackageState {
private static final int[] EMPTY_INT_ARRAY = new int[0];
@@ -297,7 +298,7 @@
if (state == null) {
return DEFAULT_USER_STATE;
}
- state.categoryHint = categoryHint;
+// state.categoryHint = categoryHint;
return state;
}
@@ -746,7 +747,7 @@
}
/** @see #mPath */
- File getPath() {
+ public File getPath() {
return mPath;
}
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index a7e1a62..9f3d190 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -28,6 +28,7 @@
import com.android.server.compat.PlatformCompat;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import libcore.io.IoUtils;
@@ -363,7 +364,7 @@
if ((sharedUserSetting != null) && (sharedUserSetting.packages.size() != 0)) {
return sharedUserSetting.seInfoTargetSdkVersion;
}
- final ApplicationInfo appInfo = pkg.toAppInfoWithoutState();
+ final ApplicationInfo appInfo = AndroidPackageUtils.generateAppInfoWithoutState(pkg);
if (compatibility.isChangeEnabledInternal(SELINUX_LATEST_CHANGES, appInfo)) {
return Math.max(
android.os.Build.VERSION_CODES.CUR_DEVELOPMENT, pkg.getTargetSdkVersion());
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index b111bbf..95e2d0a 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1161,7 +1161,7 @@
}
for (UserInfo user : allUsers) {
final PackageUserState oldUserState = oldPackage == null
- ? PackageSettingBase.DEFAULT_USER_STATE
+ ? PackageSetting.DEFAULT_USER_STATE
: oldPackage.readUserState(user.id);
if (!oldUserState.equals(newPackage.readUserState(user.id))) {
writePackageRestrictionsLPr(user.id);
@@ -2733,9 +2733,6 @@
} else {
serializer.attributeInt(null, "sharedUserId", pkg.appId);
}
- if (pkg.uidError) {
- serializer.attributeBoolean(null, "uidError", true);
- }
InstallSource installSource = pkg.installSource;
if (installSource.installerPackageName != null) {
serializer.attribute(null, "installer", installSource.installerPackageName);
@@ -3004,7 +3001,7 @@
for (int i = 0; i < N; i++) {
final PackageSetting p = mPendingPackages.get(i);
- final int sharedUserId = p.getSharedUserId();
+ final int sharedUserId = p.getSharedUserIdInt();
final Object idObj = getSettingLPr(sharedUserId);
if (idObj instanceof SharedUserSetting) {
final SharedUserSetting sharedUser = (SharedUserSetting) idObj;
@@ -3522,7 +3519,6 @@
String volumeUuid = null;
boolean updateAvailable = false;
int categoryHint = ApplicationInfo.CATEGORY_UNDEFINED;
- boolean uidError = false;
int pkgFlags = 0;
int pkgPrivateFlags = 0;
long timeStamp = 0;
@@ -3538,7 +3534,6 @@
name = parser.getAttributeValue(null, ATTR_NAME);
realName = parser.getAttributeValue(null, "realName");
userId = parser.getAttributeInt(null, "userId", 0);
- uidError = parser.getAttributeBoolean(null, "uidError", false);
sharedUserId = parser.getAttributeInt(null, "sharedUserId", 0);
codePathStr = parser.getAttributeValue(null, "codePath");
@@ -3695,7 +3690,6 @@
+ userId + " at " + parser.getPositionDescription());
}
if (packageSetting != null) {
- packageSetting.uidError = uidError;
InstallSource installSource = InstallSource.create(
installInitiatingPackageName, installOriginatingPackageName,
installerPackageName, installerAttributionTag, isOrphaned,
@@ -3877,8 +3871,8 @@
}
}
- private void readDisabledComponentsLPw(PackageSettingBase packageSetting,
- TypedXmlPullParser parser, int userId) throws IOException, XmlPullParserException {
+ private void readDisabledComponentsLPw(PackageSetting packageSetting, TypedXmlPullParser parser,
+ int userId) throws IOException, XmlPullParserException {
int outerDepth = parser.getDepth();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -3905,8 +3899,8 @@
}
}
- private void readEnabledComponentsLPw(PackageSettingBase packageSetting,
- TypedXmlPullParser parser, int userId) throws IOException, XmlPullParserException {
+ private void readEnabledComponentsLPw(PackageSetting packageSetting, TypedXmlPullParser parser,
+ int userId) throws IOException, XmlPullParserException {
int outerDepth = parser.getDepth();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -4512,8 +4506,6 @@
pw.print(prefix); pw.print(" splits="); dumpSplitNames(pw, pkg); pw.println();
final int apkSigningVersion = pkg.getSigningDetails().getSignatureSchemeVersion();
pw.print(prefix); pw.print(" apkSigningVersion="); pw.println(apkSigningVersion);
- pw.print(prefix); pw.print(" applicationInfo=");
- pw.println(pkg.toAppInfoToString());
pw.print(prefix); pw.print(" flags=");
printFlags(pw, PackageInfoUtils.appInfoFlags(pkg, ps), FLAG_DUMP_SPEC); pw.println();
int privateFlags = PackageInfoUtils.appInfoPrivateFlags(pkg, ps);
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index 95c9191..c8deffb 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -1,14 +1,6 @@
{
"presubmit": [
{
- "name": "CtsAtomicInstallTestCases",
- "file_patterns": [
- "core/java/.*Install.*",
- "services/core/.*Install.*",
- "services/core/java/com/android/server/pm/.*"
- ]
- },
- {
"name": "CtsPackageInstallTestCases",
"file_patterns": [
"core/java/.*Install.*",
diff --git a/services/core/java/com/android/server/pm/parsing/PackageCacher.java b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
index 74ec161..59b7cbd 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageCacher.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
@@ -76,7 +76,8 @@
p.unmarshall(bytes, 0, bytes.length);
p.setDataPosition(0);
- final PackageParserCacheHelper.ReadHelper helper = new PackageParserCacheHelper.ReadHelper(p);
+ final PackageParserCacheHelper.ReadHelper helper =
+ new PackageParserCacheHelper.ReadHelper(p);
helper.startAndInstall();
ParsedPackage pkg = new PackageImpl(p);
@@ -98,9 +99,10 @@
@VisibleForTesting
public static byte[] toCacheEntryStatic(ParsedPackage pkg) {
final Parcel p = Parcel.obtain();
- final PackageParserCacheHelper.WriteHelper helper = new PackageParserCacheHelper.WriteHelper(p);
+ final PackageParserCacheHelper.WriteHelper helper =
+ new PackageParserCacheHelper.WriteHelper(p);
- pkg.writeToParcel(p, 0 /* flags */);
+ ((PackageImpl) pkg).writeToParcel(p, 0 /* flags */);
helper.finishAndUninstall();
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 fa9ed66..876c534 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -208,8 +208,8 @@
*/
@Nullable
public static ApplicationInfo generateApplicationInfo(AndroidPackage pkg,
- @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId,
- @Nullable PackageSetting pkgSetting) {
+ @PackageManager.ApplicationInfoFlags int flags, @NonNull PackageUserState state,
+ int userId, @Nullable PackageSetting pkgSetting) {
if (pkg == null) {
return null;
}
@@ -233,6 +233,9 @@
info.sharedLibraryFiles = usesLibraryFiles.isEmpty()
? null : usesLibraryFiles.toArray(new String[0]);
info.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos;
+ if (info.category == ApplicationInfo.CATEGORY_UNDEFINED) {
+ info.category = pkgSetting.getCategoryOverride();
+ }
}
info.seInfo = AndroidPackageUtils.getSeInfo(pkg, pkgSetting);
diff --git a/services/core/java/com/android/server/pm/parsing/library/AndroidTestBaseUpdater.java b/services/core/java/com/android/server/pm/parsing/library/AndroidTestBaseUpdater.java
index 432394a..c67d0d2 100644
--- a/services/core/java/com/android/server/pm/parsing/library/AndroidTestBaseUpdater.java
+++ b/services/core/java/com/android/server/pm/parsing/library/AndroidTestBaseUpdater.java
@@ -29,6 +29,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.compat.IPlatformCompat;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.parsing.pkg.ParsedPackage;
/**
@@ -63,7 +64,7 @@
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
try {
return platformCompat.isChangeEnabled(REMOVE_ANDROID_TEST_BASE,
- pkg.toAppInfoWithoutState());
+ AndroidPackageUtils.generateAppInfoWithoutState(pkg));
} catch (RemoteException | NullPointerException e) {
Log.e(TAG, "Failed to get a response from PLATFORM_COMPAT_SERVICE", e);
}
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.aidl b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.aidl
deleted file mode 100644
index ab3cf7c..0000000
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.aidl
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-**
-** Copyright 2019, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License")
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.content.pm.parsing;
-
-/* @hide */
-parcelable AndroidPackage;
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
index 0d2bcec..bf7d897 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
@@ -17,87 +17,22 @@
package com.android.server.pm.parsing.pkg;
import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.SigningDetails;
import android.content.pm.parsing.ParsingPackageRead;
-import android.content.pm.parsing.ParsingPackageUtils;
-import android.content.pm.parsing.component.ParsedAttribution;
-import android.content.pm.parsing.component.ParsedIntentInfo;
-import android.content.pm.parsing.component.ParsedPermissionGroup;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.util.ArraySet;
-import android.util.Pair;
-import com.android.internal.R;
-
-import java.security.PublicKey;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
+import com.android.server.pm.pkg.AndroidPackageApi;
/**
- * The last state of a package during parsing/install before it is available in
- * {@link com.android.server.pm.PackageManagerService#mPackages}.
- *
+ * The last state of a package during parsing/install before it is available in {@link
+ * com.android.server.pm.PackageManagerService#mPackages}.
+ * <p>
* It is the responsibility of the caller to understand what data is available at what step of the
* parsing or install process.
- *
- * TODO(b/135203078): Nullability annotations
- * TODO(b/135203078): Remove get/setAppInfo differences
+ * <p>
*
* @hide
*/
-public interface AndroidPackage extends PkgAppInfo, PkgPackageInfo, ParsingPackageRead, Parcelable {
+public interface AndroidPackage extends ParsingPackageRead, AndroidPackageApi {
- /**
- * The names of packages to adopt ownership of permissions from, parsed under
- * {@link ParsingPackageUtils#TAG_ADOPT_PERMISSIONS}.
- * @see R.styleable#AndroidManifestOriginalPackage_name
- */
- @NonNull
- List<String> getAdoptPermissions();
-
- /** Path of base APK */
- @NonNull
- String getBaseApkPath();
-
- /** Revision code of base APK */
- int getBaseRevisionCode();
-
- /**
- * The path to the folder containing the base APK and any installed splits.
- */
- @NonNull
- String getPath();
-
- /**
- * Permissions requested but not in the manifest. These may have been split or migrated from
- * previous versions/definitions.
- */
- @NonNull
- List<String> getImplicitPermissions();
-
- /**
- * For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in
- * {@link ParsingPackageUtils#TAG_KEY_SETS}.
- * @see R.styleable#AndroidManifestKeySet
- * @see R.styleable#AndroidManifestPublicKey
- */
- @NonNull
- Map<String, ArraySet<PublicKey>> getKeySetMapping();
-
- /**
- * Library names this package is declared as, for use by other packages with "uses-library".
- * @see R.styleable#AndroidManifestLibrary
- */
- @NonNull
- List<String> getLibraryNames();
/**
* The package name as declared in the manifest, since the package can be renamed. For example,
@@ -105,224 +40,4 @@
*/
@NonNull
String getManifestPackageName();
-
- /**
- * We store the application meta-data independently to avoid multiple unwanted references
- * TODO(b/135203078): What does this comment mean?
- * TODO(b/135203078): Make all the Bundles immutable (and non-null by shared empty reference?)
- */
- @Nullable
- Bundle getMetaData();
-
- /**
- * For system use to migrate from an old package name to a new one, moving over data
- * if available.
- * @see R.styleable#AndroidManifestOriginalPackage}
- */
- @NonNull
- List<String> getOriginalPackages();
-
- /**
- * Map of overlayable name to actor name.
- */
- @NonNull
- Map<String, String> getOverlayables();
-
- /**
- * The name of the package as used to identify it in the system. This may be adjusted by the
- * system from the value declared in the manifest, and may not correspond to a Java code
- * package.
- * @see ApplicationInfo#packageName
- * @see PackageInfo#packageName
- */
- @NonNull
- String getPackageName();
-
- /**
- * @see PermissionGroupInfo
- */
- @NonNull
- List<ParsedPermissionGroup> getPermissionGroups();
-
- @NonNull
- List<ParsedAttribution> getAttributions();
-
- /**
- * Used to determine the default preferred handler of an {@link Intent}.
- *
- * Map of component className to intent info inside that component.
- * TODO(b/135203078): Is this actually used/working?
- */
- @NonNull
- List<Pair<String, ParsedIntentInfo>> getPreferredActivityFilters();
-
- /**
- * System protected broadcasts.
- * @see R.styleable#AndroidManifestProtectedBroadcast
- */
- @NonNull
- List<String> getProtectedBroadcasts();
-
- /**
- * Intents that this package may query or require and thus requires visibility into.
- * @see R.styleable#AndroidManifestQueriesIntent
- */
- @NonNull
- List<Intent> getQueriesIntents();
-
- /**
- * Other packages that this package may query or require and thus requires visibility into.
- * @see R.styleable#AndroidManifestQueriesPackage
- */
- @NonNull
- List<String> getQueriesPackages();
-
- /**
- * If a system app declares {@link #getOriginalPackages()}, and the app was previously installed
- * under one of those original package names, the {@link #getPackageName()} system identifier
- * will be changed to that previously installed name. This will then be non-null, set to the
- * manifest package name, for tracking the package under its true name.
- *
- * TODO(b/135203078): Remove this in favor of checking originalPackages.isEmpty and
- * getManifestPackageName
- */
- @Nullable
- String getRealPackage();
-
- /**
- * SHA-512 hash of the only APK that can be used to update a system package.
- * @see R.styleable#AndroidManifestRestrictUpdate
- */
- @Nullable
- byte[] getRestrictUpdateHash();
-
- /**
- * The signature data of all APKs in this package, which must be exactly the same across the
- * base and splits.
- */
- SigningDetails getSigningDetails();
-
- /**
- * TODO(b/135203078): Move split stuff to an inner data class
- * @see ApplicationInfo#splitNames
- * @see PackageInfo#splitNames
- */
- @Nullable
- String[] getSplitNames();
-
- /** Flags of any split APKs; ordered by parsed splitName */
- @Nullable
- int[] getSplitFlags();
-
- /** @see R.styleable#AndroidManifestStaticLibrary_name */
- @Nullable
- String getStaticSharedLibName();
-
- /** @see R.styleable#AndroidManifestStaticLibrary_version */
- long getStaticSharedLibVersion();
-
- /**
- * {@link android.os.storage.StorageManager#convert(String)} version of
- * {@link #getVolumeUuid()}.
- * TODO(b/135203078): All usages call toString() on this. Can the string be returned directly,
- * or does the parsing logic in StorageManager have to run?
- */
- UUID getStorageUuid();
-
- /**
- * For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in
- * {@link ParsingPackageUtils#TAG_KEY_SETS}.
- * @see R.styleable#AndroidManifestUpgradeKeySet
- */
- @NonNull
- Set<String> getUpgradeKeySets();
-
- /** @see R.styleable#AndroidManifestUsesLibrary */
- @NonNull
- List<String> getUsesLibraries();
-
- /**
- * Like {@link #getUsesLibraries()}, but marked optional by setting
- * {@link R.styleable#AndroidManifestUsesLibrary_required} to false . Application is expected
- * to handle absence manually.
- * @see R.styleable#AndroidManifestUsesLibrary
- */
- @NonNull
- List<String> getUsesOptionalLibraries();
-
- /** @see R.styleabele#AndroidManifestUsesNativeLibrary */
- @NonNull
- List<String> getUsesNativeLibraries();
-
- /**
- * Like {@link #getUsesNativeLibraries()}, but marked optional by setting
- * {@link R.styleable#AndroidManifestUsesNativeLibrary_required} to false . Application is
- * expected to handle absence manually.
- * @see R.styleable#AndroidManifestUsesNativeLibrary
- */
- @NonNull
- List<String> getUsesOptionalNativeLibraries();
-
- /**
- * TODO(b/135203078): Move static library stuff to an inner data class
- * @see R.styleable#AndroidManifestUsesStaticLibrary
- */
- @NonNull
- List<String> getUsesStaticLibraries();
-
- /** @see R.styleable#AndroidManifestUsesStaticLibrary_certDigest */
- @Nullable
- String[][] getUsesStaticLibrariesCertDigests();
-
- /** @see R.styleable#AndroidManifestUsesStaticLibrary_version */
- @Nullable
- long[] getUsesStaticLibrariesVersions();
-
- /** @see R.styleable#AndroidManifestApplication_forceQueryable */
- boolean isForceQueryable();
-
- boolean isCrossProfile();
-
- /**
- * The install time abi override to choose 32bit abi's when multiple abi's
- * are present. This is only meaningfull for multiarch applications.
- */
- boolean isUse32BitAbi();
-
- /**
- * Set if the any of components are visible to instant applications.
- * @see R.styleable#AndroidManifestActivity_visibleToInstantApps
- * @see R.styleable#AndroidManifestProvider_visibleToInstantApps
- * @see R.styleable#AndroidManifestService_visibleToInstantApps
- */
- boolean isVisibleToInstantApps();
-
- /**
- * Generates an {@link ApplicationInfo} object with only the data available in this object.
- *
- * TODO(b/135203078): Actually add this
- * This does not contain any system or user state data, and should be avoided. Prefer
- * com.android.server.pm.parsing.PackageInfoUtils#generateApplicationInfo(
- * AndroidPackage, int, PackageUserState, int, com.android.server.pm.PackageSetting)
- *
- * @deprecated Access AndroidPackage fields directly.
- */
- @Deprecated
- @NonNull
- ApplicationInfo toAppInfoWithoutState();
-
- /**
- * Same as toAppInfoWithoutState except it does not compute any flags.
- */
- @NonNull
- ApplicationInfo toAppInfoWithoutStateWithoutFlags();
-
- /**
- * TODO(b/135203078): Remove usages?
- * @return a mock of what the previous package.applicationInfo would've returned for logging
- * @deprecated don't use this in any new code, just print package name directly
- */
- @Deprecated
- @NonNull
- String toAppInfoToString();
}
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageHidden.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageHidden.java
new file mode 100644
index 0000000..944e4ad
--- /dev/null
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageHidden.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 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.parsing.pkg;
+
+import android.annotation.Nullable;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+
+/**
+ * Methods that normal consumers should not have access to. This usually means the field is stateful
+ * or deprecated and should be access through {@link AndroidPackageUtils} or a system manager
+ * class.
+ * <p>
+ * This is a separate interface, not implemented by the base {@link AndroidPackage} because Java
+ * doesn't support non-public interface methods. The class must be cast to this interface.
+ * <p>
+ * Because they exist in different packages, some methods are duplicated from
+ * android.content.pm.parsing.ParsingPackageHidden.
+ */
+interface AndroidPackageHidden {
+
+ /**
+ * @see ApplicationInfo#primaryCpuAbi
+ */
+ @Nullable
+ String getPrimaryCpuAbi();
+
+ /**
+ * @see ApplicationInfo#seInfo
+ * TODO: This field is deriveable and might not have to be cached here.
+ */
+ @Nullable
+ String getSeInfo();
+
+ /**
+ * @see ApplicationInfo#secondaryCpuAbi
+ */
+ @Nullable
+ String getSecondaryCpuAbi();
+
+ /**
+ * @see PackageInfo#versionCode
+ * @see ApplicationInfo#versionCode
+ */
+ @Deprecated
+ int getVersionCode();
+
+ /**
+ * @see PackageInfo#versionCodeMajor
+ */
+ int getVersionCodeMajor();
+
+ // TODO(b/135203078): Hide and enforce going through PackageInfoUtils
+ ApplicationInfo toAppInfoWithoutState();
+}
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
index d40aada..5a8e793 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.VersionedPackage;
@@ -128,7 +127,7 @@
throws PackageManagerException {
Collection<String> apkToDexMetadataList = getPackageDexMetadata(pkg).values();
String packageName = pkg.getPackageName();
- long versionCode = pkg.toAppInfoWithoutState().longVersionCode;
+ long versionCode = pkg.getLongVersionCode();
final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
for (String dexMetadata : apkToDexMetadataList) {
final ParseResult result = DexMetadataHelper.validateDexMetadataFile(
@@ -253,10 +252,6 @@
? pkg.getRoundIconRes() : pkg.getIconRes();
}
- public static long getLongVersionCode(AndroidPackage pkg) {
- return PackageInfo.composeLongVersionCode(pkg.getVersionCodeMajor(), pkg.getVersionCode());
- }
-
/**
* Returns false iff the provided flags include the {@link PackageManager#MATCH_SYSTEM_ONLY}
* flag and the provided package is not a system package. Otherwise returns {@code true}.
@@ -270,7 +265,7 @@
public static String getPrimaryCpuAbi(AndroidPackage pkg, @Nullable PackageSetting pkgSetting) {
if (pkgSetting == null || TextUtils.isEmpty(pkgSetting.primaryCpuAbiString)) {
- return pkg.getPrimaryCpuAbi();
+ return getRawPrimaryCpuAbi(pkg);
}
return pkgSetting.primaryCpuAbiString;
@@ -279,7 +274,7 @@
public static String getSecondaryCpuAbi(AndroidPackage pkg,
@Nullable PackageSetting pkgSetting) {
if (pkgSetting == null || TextUtils.isEmpty(pkgSetting.secondaryCpuAbiString)) {
- return pkg.getSecondaryCpuAbi();
+ return getRawSecondaryCpuAbi(pkg);
}
return pkgSetting.secondaryCpuAbiString;
@@ -288,23 +283,17 @@
/**
* Returns the primary ABI as parsed from the package. Used only during parsing and derivation.
* Otherwise prefer {@link #getPrimaryCpuAbi(AndroidPackage, PackageSetting)}.
- *
- * TODO(b/135203078): Actually hide the method
- * Placed in the utility to hide the method on the interface.
*/
public static String getRawPrimaryCpuAbi(AndroidPackage pkg) {
- return pkg.getPrimaryCpuAbi();
+ return ((AndroidPackageHidden) pkg).getPrimaryCpuAbi();
}
/**
* Returns the secondary ABI as parsed from the package. Used only during parsing and
* derivation. Otherwise prefer {@link #getSecondaryCpuAbi(AndroidPackage, PackageSetting)}.
- *
- * TODO(b/135203078): Actually hide the method
- * Placed in the utility to hide the method on the interface.
*/
public static String getRawSecondaryCpuAbi(AndroidPackage pkg) {
- return pkg.getSecondaryCpuAbi();
+ return ((AndroidPackageHidden) pkg).getSecondaryCpuAbi();
}
public static String getSeInfo(AndroidPackage pkg, @Nullable PackageSetting pkgSetting) {
@@ -314,6 +303,25 @@
return overrideSeInfo;
}
}
- return pkg.getSeInfo();
+ return ((AndroidPackageHidden) pkg).getSeInfo();
+ }
+
+ @Deprecated
+ @NonNull
+ public static ApplicationInfo generateAppInfoWithoutState(AndroidPackage pkg) {
+ return ((AndroidPackageHidden) pkg).toAppInfoWithoutState();
+ }
+
+ /**
+ * Replacement of unnecessary legacy getRealPackage. Only returns a value if the package was
+ * actually renamed.
+ */
+ @Nullable
+ public static String getRealPackageOrNull(AndroidPackage pkg) {
+ if (pkg.getOriginalPackages().isEmpty() || !pkg.isSystem()) {
+ return null;
+ }
+
+ return pkg.getManifestPackageName();
}
}
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
index 2fcc4b2..61f7daf 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
@@ -22,6 +22,7 @@
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.SELinuxUtil;
import android.content.pm.SigningDetails;
import android.content.pm.parsing.ParsingPackage;
import android.content.pm.parsing.ParsingPackageImpl;
@@ -32,7 +33,6 @@
import android.os.Environment;
import android.os.Parcel;
import android.os.UserHandle;
-import android.os.storage.StorageManager;
import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
@@ -42,7 +42,6 @@
import com.android.server.pm.parsing.PackageInfoUtils;
import java.io.File;
-import java.util.UUID;
/**
* Extensions to {@link ParsingPackageImpl} including fields/state contained in the system server
@@ -53,7 +52,8 @@
*
* @hide
*/
-public final class PackageImpl extends ParsingPackageImpl implements ParsedPackage, AndroidPackage {
+public class PackageImpl extends ParsingPackageImpl implements ParsedPackage, AndroidPackage,
+ AndroidPackageHidden {
@NonNull
public static PackageImpl forParsing(@NonNull String packageName, @NonNull String baseCodePath,
@@ -116,9 +116,6 @@
@Nullable
@DataClass.ParcelWith(ForInternedString.class)
protected String seInfo;
- @Nullable
- @DataClass.ParcelWith(ForInternedString.class)
- protected String seInfoUser;
/**
* This is an appId, the uid if the userId is == USER_SYSTEM
@@ -268,12 +265,6 @@
}
@Override
- public PackageImpl setRealPackage(@Nullable String realPackage) {
- super.setRealPackage(realPackage);
- return this;
- }
-
- @Override
public PackageImpl setPersistent(boolean value) {
super.setPersistent(value);
return this;
@@ -427,12 +418,6 @@
}
@Override
- public PackageImpl setSeInfoUser(@Nullable String seInfoUser) {
- this.seInfoUser = TextUtils.safeIntern(seInfoUser);
- return this;
- }
-
- @Override
public PackageImpl setSplitCodePaths(@Nullable String[] splitCodePaths) {
this.splitCodePaths = splitCodePaths;
if (splitCodePaths != null) {
@@ -487,19 +472,6 @@
}
@Override
- public UUID getStorageUuid() {
- return StorageManager.convert(volumeUuid);
- }
-
- @Deprecated
- @Override
- public String toAppInfoToString() {
- return "PackageImpl{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + getPackageName() + "}";
- }
-
- @Override
public ParsedPackage setCoreApp(boolean coreApp) {
return setBoolean(Booleans.CORE_APP, coreApp);
}
@@ -529,7 +501,7 @@
appInfo.secondaryCpuAbi = secondaryCpuAbi;
appInfo.secondaryNativeLibraryDir = secondaryNativeLibraryDir;
appInfo.seInfo = seInfo;
- appInfo.seInfoUser = seInfoUser;
+ appInfo.seInfoUser = SELinuxUtil.COMPLETE_STR;
appInfo.uid = uid;
return appInfo;
}
@@ -550,7 +522,6 @@
sForInternedString.parcel(this.secondaryCpuAbi, dest, flags);
dest.writeString(this.secondaryNativeLibraryDir);
dest.writeString(this.seInfo);
- dest.writeString(this.seInfoUser);
dest.writeInt(this.uid);
dest.writeInt(this.mBooleans);
}
@@ -565,7 +536,6 @@
this.secondaryCpuAbi = sForInternedString.unparcel(in);
this.secondaryNativeLibraryDir = in.readString();
this.seInfo = in.readString();
- this.seInfoUser = in.readString();
this.uid = in.readInt();
this.mBooleans = in.readInt();
@@ -636,12 +606,6 @@
return seInfo;
}
- @Nullable
- @Override
- public String getSeInfoUser() {
- return seInfoUser;
- }
-
@Override
public boolean isCoreApp() {
return getBoolean(Booleans.CORE_APP);
@@ -700,7 +664,7 @@
return uid;
}
- @DataClass.Generated.Member
+ @Override
public PackageImpl setStub(boolean value) {
setBoolean(Booleans.STUB, value);
return this;
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/ParsedPackage.java b/services/core/java/com/android/server/pm/parsing/pkg/ParsedPackage.java
index 0051bab..bb08f09 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/ParsedPackage.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/ParsedPackage.java
@@ -16,7 +16,6 @@
package com.android.server.pm.parsing.pkg;
-import android.annotation.Nullable;
import android.content.pm.SigningDetails;
/**
@@ -55,8 +54,6 @@
ParsedPackage setPrimaryCpuAbi(String primaryCpuAbi);
- ParsedPackage setRealPackage(@Nullable String realPackage);
-
ParsedPackage setSecondaryCpuAbi(String secondaryCpuAbi);
ParsedPackage setSigningDetails(SigningDetails signingDetails);
@@ -101,8 +98,6 @@
ParsedPackage setSeInfo(String seInfo);
- ParsedPackage setSeInfoUser(String seInfoUser);
-
ParsedPackage setSecondaryNativeLibraryDir(String secondaryNativeLibraryDir);
/**
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PkgAppInfo.java b/services/core/java/com/android/server/pm/parsing/pkg/PkgAppInfo.java
index 728e1bc..c7dc267 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/PkgAppInfo.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PkgAppInfo.java
@@ -16,484 +16,91 @@
package com.android.server.pm.parsing.pkg;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
-import android.util.SparseArray;
+import android.content.pm.parsing.PkgWithoutStateAppInfo;
-import com.android.internal.R;
+import com.android.server.pm.PackageManagerService;
/**
- * Container for fields that are eventually exposed through {@link ApplicationInfo}.
- *
- * Done to separate the meaningless, re-directed JavaDoc for methods and to separate what's
- * exposed vs not exposed to core.
- *
- * @hide
+ * Equivalent of {@link PkgWithoutStateAppInfo} but contains fields that are set inside {@link
+ * PackageManagerService} and thus are not available to the core SDK.
+ * <p>
+ * Everything in this interface is @SystemApi(client = SYSTEM_SERVER), but the interface itself is
+ * not.
*/
-interface PkgAppInfo {
-
- /** @see ApplicationInfo#PRIVATE_FLAG_CANT_SAVE_STATE */
- boolean isCantSaveState();
+public interface PkgAppInfo extends PkgWithoutStateAppInfo {
/**
- * @see ApplicationInfo#appComponentFactory
- * @see R.styleable#AndroidManifestApplication_appComponentFactory
+ * @see ApplicationInfo#nativeLibraryDir
*/
@Nullable
- String getAppComponentFactory();
-
- /**
- * @see ApplicationInfo#backupAgentName
- * @see R.styleable#AndroidManifestApplication_backupAgent
- */
- @Nullable
- String getBackupAgentName();
-
- /**
- * @see ApplicationInfo#banner
- * @see R.styleable#AndroidManifestApplication_banner
- */
- int getBanner();
-
- /**
- * @see ApplicationInfo#category
- * @see R.styleable#AndroidManifestApplication_appCategory
- */
- int getCategory();
-
- /**
- * @see ApplicationInfo#classLoaderName
- * @see R.styleable#AndroidManifestApplication_classLoader
- */
- @Nullable
- String getClassLoaderName();
-
- /**
- * @see ApplicationInfo#className
- * @see R.styleable#AndroidManifestApplication_name
- */
- @Nullable
- String getClassName();
-
- /**
- * @see ApplicationInfo#compatibleWidthLimitDp
- * @see R.styleable#AndroidManifestSupportsScreens_compatibleWidthLimitDp
- */
- int getCompatibleWidthLimitDp();
-
- /**
- * @see ApplicationInfo#compileSdkVersion
- * @see R.styleable#AndroidManifest_compileSdkVersion
- */
- int getCompileSdkVersion();
-
- /**
- * @see ApplicationInfo#compileSdkVersionCodename
- * @see R.styleable#AndroidManifest_compileSdkVersionCodename
- */
- @Nullable
- String getCompileSdkVersionCodeName();
-
- /**
- * @see ApplicationInfo#descriptionRes
- * @see R.styleable#AndroidManifestApplication_description
- */
- int getDescriptionRes();
-
- /**
- * @see ApplicationInfo#fullBackupContent
- * @see R.styleable#AndroidManifestApplication_fullBackupContent
- */
- int getFullBackupContent();
-
- /**
- * @see ApplicationInfo#iconRes
- * @see R.styleable#AndroidManifestApplication_icon
- */
- int getIconRes();
-
- /**
- * @see ApplicationInfo#labelRes
- * @see R.styleable#AndroidManifestApplication_label
- */
- int getLabelRes();
-
- /**
- * @see ApplicationInfo#largestWidthLimitDp
- * @see R.styleable#AndroidManifestSupportsScreens_largestWidthLimitDp
- */
- int getLargestWidthLimitDp();
-
- /**
- * @see ApplicationInfo#logo
- * @see R.styleable#AndroidManifestApplication_logo
- */
- int getLogo();
-
- /**
- * @see ApplicationInfo#manageSpaceActivityName
- * @see R.styleable#AndroidManifestApplication_manageSpaceActivity
- */
- @Nullable
- String getManageSpaceActivityName();
-
- /**
- * @see ApplicationInfo#maxAspectRatio
- * @see R.styleable#AndroidManifestApplication_maxAspectRatio
- */
- float getMaxAspectRatio();
-
- /**
- * @see ApplicationInfo#minAspectRatio
- * @see R.styleable#AndroidManifestApplication_minAspectRatio
- */
- float getMinAspectRatio();
-
- /**
- * @see ApplicationInfo#minSdkVersion
- * @see R.styleable#AndroidManifestUsesSdk_minSdkVersion
- */
- int getMinSdkVersion();
-
- /** @see ApplicationInfo#nativeLibraryDir */
- @Nullable
String getNativeLibraryDir();
- /** @see ApplicationInfo#nativeLibraryRootDir */
+ /**
+ * @see ApplicationInfo#nativeLibraryRootDir
+ */
@Nullable
String getNativeLibraryRootDir();
/**
- * @see ApplicationInfo#networkSecurityConfigRes
- * @see R.styleable#AndroidManifestApplication_networkSecurityConfig
+ * @see ApplicationInfo#secondaryNativeLibraryDir
*/
- int getNetworkSecurityConfigRes();
-
- /**
- * If {@link R.styleable#AndroidManifestApplication_label} is a string literal, this is it.
- * Otherwise, it's stored as {@link #getLabelRes()}.
- * @see ApplicationInfo#nonLocalizedLabel
- * @see R.styleable#AndroidManifestApplication_label
- */
- @Nullable
- CharSequence getNonLocalizedLabel();
-
- /**
- * @see ApplicationInfo#permission
- * @see R.styleable#AndroidManifestApplication_permission
- */
- @Nullable
- String getPermission();
-
- /**
- * TODO(b/135203078): Hide this in the utility, should never be accessed directly
- * @see ApplicationInfo#primaryCpuAbi
- */
- @Nullable
- String getPrimaryCpuAbi();
-
- /**
- * @see ApplicationInfo#processName
- * @see R.styleable#AndroidManifestApplication_process
- */
- @NonNull
- String getProcessName();
-
- /**
- * @see ApplicationInfo#requiresSmallestWidthDp
- * @see R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp
- */
- int getRequiresSmallestWidthDp();
-
- /**
- * @see ApplicationInfo#roundIconRes
- * @see R.styleable#AndroidManifestApplication_roundIcon
- */
- int getRoundIconRes();
-
- /**
- * @see ApplicationInfo#areAttributionsUserVisible()
- * @see R.styleable#AndroidManifestApplication_attributionsAreUserVisible
- */
- boolean areAttributionsUserVisible();
-
- /** @see ApplicationInfo#seInfo */
- @Nullable
- String getSeInfo();
-
- /** @see ApplicationInfo#seInfoUser */
- @Nullable
- String getSeInfoUser();
-
- /** @see ApplicationInfo#secondaryCpuAbi */
- @Nullable
- String getSecondaryCpuAbi();
-
- /** @see ApplicationInfo#secondaryNativeLibraryDir */
@Nullable
String getSecondaryNativeLibraryDir();
/**
- * @see ApplicationInfo#installLocation
- * @see R.styleable#AndroidManifest_installLocation
+ * @see ApplicationInfo#uid
*/
- int getInstallLocation();
-
- /**
- * @see ApplicationInfo#splitClassLoaderNames
- * @see R.styleable#AndroidManifestApplication_classLoader
- */
- @Nullable
- String[] getSplitClassLoaderNames();
-
- /** @see ApplicationInfo#splitSourceDirs */
- @Nullable
- String[] getSplitCodePaths();
-
- /** @see ApplicationInfo#splitDependencies */
- @Nullable
- SparseArray<int[]> getSplitDependencies();
-
- /**
- * @see ApplicationInfo#targetSandboxVersion
- * @see R.styleable#AndroidManifest_targetSandboxVersion
- */
- @Deprecated
- int getTargetSandboxVersion();
-
- /**
- * @see ApplicationInfo#targetSdkVersion
- * @see R.styleable#AndroidManifestUsesSdk_targetSdkVersion
- */
- int getTargetSdkVersion();
-
- /**
- * @see ApplicationInfo#taskAffinity
- * @see R.styleable#AndroidManifestApplication_taskAffinity
- */
- @Nullable
- String getTaskAffinity();
-
- /**
- * @see ApplicationInfo#theme
- * @see R.styleable#AndroidManifestApplication_theme
- */
- int getTheme();
-
- /**
- * @see ApplicationInfo#uiOptions
- * @see R.styleable#AndroidManifestApplication_uiOptions
- */
- int getUiOptions();
-
- /** @see ApplicationInfo#uid */
int getUid();
- /** @see ApplicationInfo#longVersionCode */
- long getLongVersionCode();
-
- /** @see ApplicationInfo#versionCode */
- @Deprecated
- int getVersionCode();
-
- /** @see ApplicationInfo#volumeUuid */
- @Nullable
- String getVolumeUuid();
-
- /** @see ApplicationInfo#zygotePreloadName */
- @Nullable
- String getZygotePreloadName();
-
- /** @see ApplicationInfo#FLAG_HAS_CODE */
- boolean isHasCode();
-
- /** @see ApplicationInfo#FLAG_ALLOW_TASK_REPARENTING */
- boolean isAllowTaskReparenting();
-
- /** @see ApplicationInfo#FLAG_MULTIARCH */
- boolean isMultiArch();
-
- /** @see ApplicationInfo#FLAG_EXTRACT_NATIVE_LIBS */
- boolean isExtractNativeLibs();
-
- /** @see ApplicationInfo#FLAG_DEBUGGABLE */
- boolean isDebuggable();
-
- /** @see ApplicationInfo#FLAG_VM_SAFE_MODE */
- boolean isVmSafeMode();
-
- /** @see ApplicationInfo#FLAG_PERSISTENT */
- boolean isPersistent();
-
- /** @see ApplicationInfo#FLAG_ALLOW_BACKUP */
- boolean isAllowBackup();
-
- /** @see ApplicationInfo#FLAG_TEST_ONLY */
- boolean isTestOnly();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION */
- boolean isResizeableActivityViaSdkVersion();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_HAS_DOMAIN_URLS */
- boolean isHasDomainUrls();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE */
- boolean isRequestLegacyExternalStorage();
-
- /** @see ApplicationInfo#FLAG_HARDWARE_ACCELERATED */
- boolean isBaseHardwareAccelerated();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE */
- boolean isDefaultToDeviceProtectedStorage();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_DIRECT_BOOT_AWARE */
- boolean isDirectBootAware();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE */
- boolean isPartiallyDirectBootAware();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_USE_EMBEDDED_DEX */
- boolean isUseEmbeddedDex();
-
- /** @see ApplicationInfo#FLAG_EXTERNAL_STORAGE */
- boolean isExternalStorage();
-
- /** @see ApplicationInfo#nativeLibraryRootRequiresIsa */
- boolean isNativeLibraryRootRequiresIsa();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_ODM */
- boolean isOdm();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_OEM */
- boolean isOem();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_PRIVILEGED */
- boolean isPrivileged();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_PRODUCT */
- boolean isProduct();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_PROFILEABLE_BY_SHELL */
- boolean isProfileableByShell();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_STATIC_SHARED_LIBRARY */
- boolean isStaticSharedLibrary();
-
- /** @see ApplicationInfo#FLAG_SYSTEM */
- boolean isSystem();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_SYSTEM_EXT */
- boolean isSystemExt();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_VENDOR */
- boolean isVendor();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_ISOLATED_SPLIT_LOADING */
- boolean isIsolatedSplitLoading();
-
/**
- * @see ApplicationInfo#enabled
- * @see R.styleable#AndroidManifestApplication_enabled
+ * @see ApplicationInfo#FLAG_FACTORY_TEST
*/
- boolean isEnabled();
-
- /**
- * @see ApplicationInfo#PRIVATE_FLAG_IS_RESOURCE_OVERLAY
- * @see ApplicationInfo#isResourceOverlay()
- */
- boolean isOverlay();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_USES_NON_SDK_API */
- boolean isUsesNonSdkApi();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY */
- boolean isSignedWithPlatformKey();
-
- /** @see ApplicationInfo#FLAG_KILL_AFTER_RESTORE */
- boolean isKillAfterRestore();
-
- /** @see ApplicationInfo#FLAG_RESTORE_ANY_VERSION */
- boolean isRestoreAnyVersion();
-
- /** @see ApplicationInfo#FLAG_FULL_BACKUP_ONLY */
- boolean isFullBackupOnly();
-
- /** @see ApplicationInfo#FLAG_ALLOW_CLEAR_USER_DATA */
- boolean isAllowClearUserData();
-
- /** @see ApplicationInfo#FLAG_LARGE_HEAP */
- boolean isLargeHeap();
-
- /** @see ApplicationInfo#FLAG_USES_CLEARTEXT_TRAFFIC */
- boolean isUsesCleartextTraffic();
-
- /** @see ApplicationInfo#FLAG_SUPPORTS_RTL */
- boolean isSupportsRtl();
-
- /** @see ApplicationInfo#FLAG_IS_GAME */
- @Deprecated
- boolean isGame();
-
- /** @see ApplicationInfo#FLAG_FACTORY_TEST */
boolean isFactoryTest();
/**
- * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
- * {@link android.os.Build.VERSION_CODES#DONUT}.
- * @see R.styleable#AndroidManifestSupportsScreens_smallScreens
- * @see ApplicationInfo#FLAG_SUPPORTS_SMALL_SCREENS
+ * @see ApplicationInfo#nativeLibraryRootRequiresIsa
*/
- boolean isSupportsSmallScreens();
+ boolean isNativeLibraryRootRequiresIsa();
/**
- * If omitted from manifest, returns true.
- * @see R.styleable#AndroidManifestSupportsScreens_normalScreens
- * @see ApplicationInfo#FLAG_SUPPORTS_NORMAL_SCREENS
+ * @see ApplicationInfo#PRIVATE_FLAG_ODM
*/
- boolean isSupportsNormalScreens();
+ boolean isOdm();
/**
- * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
- * {@link android.os.Build.VERSION_CODES#DONUT}.
- * @see R.styleable#AndroidManifestSupportsScreens_largeScreens
- * @see ApplicationInfo#FLAG_SUPPORTS_LARGE_SCREENS
+ * @see ApplicationInfo#PRIVATE_FLAG_OEM
*/
- boolean isSupportsLargeScreens();
+ boolean isOem();
/**
- * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
- * {@link android.os.Build.VERSION_CODES#GINGERBREAD}.
- * @see R.styleable#AndroidManifestSupportsScreens_xlargeScreens
- * @see ApplicationInfo#FLAG_SUPPORTS_XLARGE_SCREENS
+ * @see ApplicationInfo#PRIVATE_FLAG_PRIVILEGED
*/
- boolean isSupportsExtraLargeScreens();
+ boolean isPrivileged();
/**
- * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
- * {@link android.os.Build.VERSION_CODES#DONUT}.
- * @see R.styleable#AndroidManifestSupportsScreens_resizeable
- * @see ApplicationInfo#FLAG_RESIZEABLE_FOR_SCREENS
+ * @see ApplicationInfo#PRIVATE_FLAG_PRODUCT
*/
- boolean isResizeable();
+ boolean isProduct();
/**
- * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
- * {@link android.os.Build.VERSION_CODES#DONUT}.
- * @see R.styleable#AndroidManifestSupportsScreens_anyDensity
- * @see ApplicationInfo#FLAG_SUPPORTS_SCREEN_DENSITIES
+ * @see ApplicationInfo#PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY
*/
- boolean isAnyDensity();
+ boolean isSignedWithPlatformKey();
- /** @see ApplicationInfo#PRIVATE_FLAG_BACKUP_IN_FOREGROUND */
- boolean isBackupInForeground();
+ /**
+ * @see ApplicationInfo#FLAG_SYSTEM
+ */
+ boolean isSystem();
- /** @see ApplicationInfo#PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE */
- boolean isAllowClearUserDataOnFailedRestore();
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_SYSTEM_EXT
+ */
+ boolean isSystemExt();
- /** @see ApplicationInfo#PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE */
- boolean isAllowAudioPlaybackCapture();
-
- /** @see ApplicationInfo#PRIVATE_FLAG_HAS_FRAGILE_USER_DATA */
- boolean isHasFragileUserData();
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_VENDOR
+ */
+ boolean isVendor();
}
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PkgPackageInfo.java b/services/core/java/com/android/server/pm/parsing/pkg/PkgPackageInfo.java
index 89330a9..b3b3910 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/PkgPackageInfo.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PkgPackageInfo.java
@@ -16,143 +16,27 @@
package com.android.server.pm.parsing.pkg;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ConfigurationInfo;
-import android.content.pm.FeatureGroupInfo;
-import android.content.pm.FeatureInfo;
-import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
-import android.content.pm.PermissionInfo;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ServiceInfo;
-import android.content.pm.parsing.component.ParsedActivity;
-import android.content.pm.parsing.component.ParsedInstrumentation;
-import android.content.pm.parsing.component.ParsedPermission;
-import android.content.pm.parsing.component.ParsedProvider;
-import android.content.pm.parsing.component.ParsedService;
+import android.content.pm.parsing.PkgWithoutStatePackageInfo;
-import com.android.internal.R;
-
-import java.util.List;
+import com.android.server.pm.PackageManagerService;
/**
- * Container for fields that are eventually exposed through {@link PackageInfo}.
- *
- * Done to separate the meaningless, re-directed JavaDoc for methods and to separate what's
- * exposed vs not exposed to core.
- *
- * @hide
+ * Equivalent of {@link PkgWithoutStatePackageInfo} but contains fields that are set inside {@link
+ * PackageManagerService} and thus are not available to the core SDK.
+ * <p>
+ * Everything in this interface is @SystemApi(client = SYSTEM_SERVER), but the interface itself is
+ * not.
*/
-interface PkgPackageInfo {
+public interface PkgPackageInfo extends PkgWithoutStatePackageInfo {
/**
- * @see PackageInfo#overlayCategory
- * @see R.styleable#AndroidManifestResourceOverlay_category
- */
- @Nullable
- String getOverlayCategory();
-
- /**
- * @see PackageInfo#overlayPriority
- * @see R.styleable#AndroidManifestResourceOverlay_priority
- */
- int getOverlayPriority();
-
- /**
- * @see PackageInfo#overlayTarget
- * @see R.styleable#AndroidManifestResourceOverlay_targetPackage
- */
- @Nullable
- String getOverlayTarget();
-
- /**
- * @see PackageInfo#targetOverlayableName
- * @see R.styleable#AndroidManifestResourceOverlay_targetName
- */
- @Nullable
- String getOverlayTargetName();
-
- /**
- * @see PackageInfo#sharedUserId
- * @see R.styleable#AndroidManifest_sharedUserId
- */
- @Deprecated
- @Nullable
- String getSharedUserId();
-
- /**
- * @see PackageInfo#sharedUserLabel
- * @see R.styleable#AndroidManifest_sharedUserLabel
- */
- @Deprecated
- int getSharedUserLabel();
-
- /**
- * The required account type without which this application will not function.
+ * For marking packages required for a minimal boot state, through the "coreApp" manifest
+ * attribute.
*
- * @see PackageInfo#requiredAccountType
- * @see R.styleable#AndroidManifestApplication_requiredAccountType
+ * @see PackageInfo#coreApp
*/
- @Nullable
- String getRequiredAccountType();
-
- /**
- * The restricted account authenticator type that is used by this application
- *
- * @see PackageInfo#restrictedAccountType
- * @see R.styleable#AndroidManifestApplication_restrictedAccountType
- */
- @Nullable
- String getRestrictedAccountType();
-
- /** @see PackageInfo#splitRevisionCodes */
- int[] getSplitRevisionCodes();
-
- /** @see PackageInfo#getLongVersionCode() */
- long getLongVersionCode();
-
- /** @see PackageInfo#versionCode */
- @Deprecated
- int getVersionCode();
-
- /** @see PackageInfo#versionCodeMajor */
- int getVersionCodeMajor();
-
- /** @see PackageInfo#versionName */
- @Nullable
- String getVersionName();
-
- /** @see PackageInfo#mOverlayIsStatic */
- boolean isOverlayIsStatic();
-
- /**
- * @see PackageInfo#requiredForAllUsers
- * @see R.styleable#AndroidManifestApplication_requiredForAllUsers
- */
- boolean isRequiredForAllUsers();
-
- /**
- * @see PackageInfo#reqFeatures
- * @see R.styleable#AndroidManifestUsesFeature
- */
- @NonNull
- List<FeatureInfo> getReqFeatures();
-
- /**
- * @see PackageInfo#configPreferences
- * @see R.styleable#AndroidManifestUsesConfiguration
- */
- @NonNull
- List<ConfigurationInfo> getConfigPreferences();
-
- /**
- * @see PackageInfo#featureGroups
- * @see R.styleable#AndroidManifestUsesFeature
- */
- @NonNull
- List<FeatureGroupInfo> getFeatureGroups();
+ boolean isCoreApp();
/**
* Whether or not the package is a stub and must be replaced by the full version.
@@ -160,66 +44,4 @@
* @see PackageInfo#isStub
*/
boolean isStub();
-
- /**
- * For marking packages required for a minimal boot state, through the "coreApp" manifest
- * attribute.
- * @see PackageInfo#coreApp
- */
- boolean isCoreApp();
-
- /**
- * All the permissions declared. This is an effective set, and may include permissions
- * transformed from split/migrated permissions from previous versions, so may not be exactly
- * what the package declares in its manifest.
- * @see PackageInfo#requestedPermissions
- * @see R.styleable#AndroidManifestUsesPermission
- */
- @NonNull
- List<String> getRequestedPermissions();
-
- /**
- * @see ActivityInfo
- * @see PackageInfo#activities
- */
- @NonNull
- List<ParsedActivity> getActivities();
-
- /**
- * @see InstrumentationInfo
- * @see PackageInfo#instrumentation
- */
- @NonNull
- List<ParsedInstrumentation> getInstrumentations();
-
- /**
- * @see PermissionInfo
- * @see PackageInfo#permissions
- */
- @NonNull
- List<ParsedPermission> getPermissions();
-
- /**
- * @see ProviderInfo
- * @see PackageInfo#providers
- */
- @NonNull
- List<ParsedProvider> getProviders();
-
- /**
- * Since they share several attributes, receivers are parsed as {@link ParsedActivity}, even
- * though they represent different functionality.
- * TODO(b/135203078): Reconsider this and maybe make ParsedReceiver so it's not so confusing
- * @see ActivityInfo
- * @see PackageInfo#receivers
- */
- @NonNull
- List<ParsedActivity> getReceivers();
-
- /**
- * @see ServiceInfo
- * @see PackageInfo#services
- */
- @NonNull
- List<ParsedService> getServices();
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 904e889..e40cb40 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -154,6 +154,7 @@
import com.android.server.pm.UserManagerService;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.permission.PermissionManagerServiceInternal.HotwordDetectionServiceProvider;
import com.android.server.pm.permission.PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener;
import com.android.server.policy.PermissionPolicyInternal;
@@ -1485,7 +1486,8 @@
&& mayManageRolePermission(callingUid);
final boolean mayGrantSoftRestrictedPermission = isSoftRestrictedPermission
&& SoftRestrictedPermissionPolicy.forPermission(mContext,
- pkg.toAppInfoWithoutState(), pkg, UserHandle.of(userId), permName)
+ AndroidPackageUtils.generateAppInfoWithoutState(pkg), pkg,
+ UserHandle.of(userId), permName)
.mayGrantPermission();
final boolean isRuntimePermission;
@@ -6129,9 +6131,23 @@
proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
}
} else {
- startedOpResult = appOpsManager.startProxyOpNoThrow(startedOp,
- resolvedAttributionSource, message, skipProxyOperation,
- proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
+ try {
+ startedOpResult = appOpsManager.startProxyOpNoThrow(startedOp,
+ resolvedAttributionSource, message, skipProxyOperation,
+ proxyAttributionFlags, proxiedAttributionFlags, attributionChainId);
+ } catch (SecurityException e) {
+ //TODO 195339480: remove
+ String msg = "Security exception for op " + startedOp + " with source "
+ + attributionSource.getUid() + ":"
+ + attributionSource.getPackageName() + ", "
+ + attributionSource.getNextUid() + ":"
+ + attributionSource.getNextPackageName();
+ if (attributionSource.getNext() != null) {
+ AttributionSource next = attributionSource.getNext();
+ msg = msg + ", " + next.getNextPackageName() + ":" + next.getNextUid();
+ }
+ throw new SecurityException(msg + ":" + e.getMessage());
+ }
}
return Math.max(checkedOpResult, startedOpResult);
} else {
@@ -6178,8 +6194,22 @@
message, skipProxyOperation);
}
} else {
- notedOpResult = appOpsManager.noteProxyOpNoThrow(notedOp,
- resolvedAttributionSource, message, skipProxyOperation);
+ try {
+ notedOpResult = appOpsManager.noteProxyOpNoThrow(notedOp,
+ resolvedAttributionSource, message, skipProxyOperation);
+ } catch (SecurityException e) {
+ //TODO 195339480: remove
+ String msg = "Security exception for op " + notedOp + " with source "
+ + attributionSource.getUid() + ":"
+ + attributionSource.getPackageName() + ", "
+ + attributionSource.getNextUid() + ":"
+ + attributionSource.getNextPackageName();
+ if (attributionSource.getNext() != null) {
+ AttributionSource next = attributionSource.getNext();
+ msg = msg + ", " + next.getNextPackageName() + ":" + next.getNextUid();
+ }
+ throw new SecurityException(msg + ":" + e.getMessage());
+ }
}
return Math.max(checkedOpResult, notedOpResult);
}
diff --git a/services/core/java/com/android/server/pm/pkg/AndroidPackageApi.java b/services/core/java/com/android/server/pm/pkg/AndroidPackageApi.java
new file mode 100644
index 0000000..3fde41a
--- /dev/null
+++ b/services/core/java/com/android/server/pm/pkg/AndroidPackageApi.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 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.pkg;
+
+import android.annotation.SystemApi;
+
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PkgAppInfo;
+import com.android.server.pm.parsing.pkg.PkgPackageInfo;
+
+/**
+ * Explicit interface used for consumers like mainline who need a {@link SystemApi @SystemApi} form
+ * of {@link AndroidPackage}.
+ * <p>
+ * There should be no methods in this class. All of them must come from other interfaces that group
+ * the actual methods. This is done to ensure proper separation of the (legacy?) Info object APIs.
+ */
+// TODO(b/173807334): Expose API
+//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+public interface AndroidPackageApi extends PkgPackageInfo, PkgAppInfo {
+
+}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageState.java b/services/core/java/com/android/server/pm/pkg/PackageState.java
new file mode 100644
index 0000000..0d29bab
--- /dev/null
+++ b/services/core/java/com/android/server/pm/pkg/PackageState.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2020 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.pkg;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.UserIdInt;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.SharedLibraryInfo;
+import android.content.pm.SigningInfo;
+import android.content.pm.pkg.PackageUserState;
+
+import com.android.internal.R;
+import com.android.server.pm.PackageSetting;
+import com.android.server.pm.Settings;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The API surface for a {@link PackageSetting}. Methods are expected to return immutable objects.
+ * This may mean copying data on each invocation until related classes are refactored to be
+ * immutable.
+ * <p>
+ * Note that until immutability or read-only caching is enabled, {@link PackageSetting} cannot be
+ * returned directly, so {@link PackageStateImpl} is used to temporarily copy the data. This is a
+ * relatively expensive operation since it has to create an object for every package, but it's much
+ * lighter than the alternative of generating {@link PackageInfo} objects.
+ * <p>
+ * TODO: Documentation TODO: Currently missing, should be exposed as API?
+ * <ul>
+ * <li>keySetData</li>
+ * <li>installSource</li>
+ * <li>incrementalStates</li>
+ * </ul>
+ *
+ * @hide
+ *
+ * TODO(chiuwinson): Delete all of the method defaults
+ */
+// TODO(b/173807334): Expose API
+//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+public interface PackageState {
+
+ /**
+ * This can be null whenever a physical APK on device is missing. This can be the result of
+ * removing an external storage device where the APK resides.
+ * <p>
+ * This will result in the system reading the {@link PackageSetting} from disk, but without
+ * being able to parse the base APK's AndroidManifest.xml to read all of its metadata. The data
+ * that is written and read in {@link Settings} includes a minimal set of metadata needed to
+ * perform other checks in the system.
+ * <p>
+ * This is important in order to enforce uniqueness within the system, as the package, even if
+ * on a removed storage device, is still considered installed. Another package of the same
+ * application ID or declaring the same permissions or similar cannot be installed.
+ * <p>
+ * Re-attaching the storage device to make the APK available should allow the user to use the
+ * app once the device reboots or otherwise re-scans it.
+ */
+ @Nullable
+ default AndroidPackageApi getAndroidPackage() { return null; }
+
+ /**
+ * The non-user-specific UID
+ */
+ default int getAppId() { return -1; }
+
+ /**
+ * Value set through {@link PackageManager#setApplicationCategoryHint(String, int)}. Only
+ * applied if the application itself does not declare a category.
+ *
+ * @see AndroidPackageApi#getCategory()
+ */
+ default int getCategoryOverride() { return -1; }
+
+ @Nullable
+ default String getCpuAbiOverride() { return null; }
+
+ /**
+ * In epoch milliseconds.
+ */
+ default long getFirstInstallTime() { return -1; }
+
+ /**
+ * In epoch milliseconds.
+ */
+ default long getLastModifiedTime() { return -1; }
+
+ @NonNull
+ default long[] getLastPackageUsageTime() { return null; }
+
+ /**
+ * In epoch milliseconds.
+ */
+ default long getLastUpdateTime() { return -1; }
+
+ /**
+ * @see AndroidPackageApi#getLongVersionCode()
+ */
+ default long getLongVersionCode() { return -1; }
+
+ /**
+ * Maps mime group name to the set of Mime types in a group. Mime groups declared by app are
+ * populated with empty sets at construction. Mime groups can not be created/removed at runtime,
+ * thus keys in this map should not change
+ */
+ @NonNull
+ default Map<String, Set<String>> getMimeGroups() { return null; }
+
+ /**
+ * @see AndroidPackageApi#getPackageName()
+ */
+ @NonNull
+ default String getPackageName() { return null; }
+
+ /**
+ * @see AndroidPackageApi#getPath()
+ */
+ @NonNull
+ default File getPath() { return null; }
+
+ @Nullable
+ default String getPrimaryCpuAbi() { return null; }
+
+ @Nullable
+ default String getSeInfoOverride() { return null; }
+
+ @Nullable
+ default String getSecondaryCpuAbi() { return null; }
+
+ /**
+ * Retrieves the shared user ID. Note that the actual shared user data is not available here and
+ * must be queried separately.
+ *
+ * @return the shared user this package is a part of, or null if it's not part of a shared user.
+ */
+ @Nullable
+ default Integer getSharedUserId() { return null; }
+
+ @NonNull
+ default SigningInfo getSigningInfo() { return null; }
+
+ /**
+ * Valid users for this package, for use with {@link #getUserState(int)}.
+ */
+ default int[] getUserIds() { return null; }
+
+ /**
+ * Retrieves per-user state for this package. Acceptable user IDs are in {@link #getUserIds()}.
+ */
+ @Nullable
+ default PackageUserState getUserState(@UserIdInt int userId) { return null; }
+
+ /**
+ * The actual files resolved for each shared library.
+ *
+ * @see R.styleable#AndroidManifestUsesLibrary
+ */
+ @NonNull
+ default List<String> getUsesLibraryFiles() { return null; }
+
+ /**
+ * @see R.styleable#AndroidManifestUsesLibrary
+ */
+ @NonNull
+ default List<SharedLibraryInfo> getUsesLibraryInfos() { return null; }
+
+ /**
+ * @see R.styleable#AndroidManifestUsesStaticLibrary
+ */
+ @NonNull
+ default String[] getUsesStaticLibraries() { return null; }
+
+ /**
+ * @see R.styleable#AndroidManifestUsesStaticLibrary_version
+ */
+ @NonNull
+ default long[] getUsesStaticLibrariesVersions() { return null; }
+
+ /**
+ * @see AndroidPackageApi#getVolumeUuid()
+ */
+ @Nullable
+ default String getVolumeUuid() { return null; }
+
+ /**
+ * @see AndroidPackageApi#isExternalStorage()
+ */
+ default boolean isExternalStorage() { return false; }
+
+ /**
+ * Whether a package was installed --force-queryable such that it is always queryable by any
+ * package, regardless of their manifest content.
+ */
+ default boolean isForceQueryableOverride() { return false; }
+
+ /**
+ * Whether a package is treated as hidden until it is installed for a user.
+ *
+ * @see PackageManager#MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
+ * @see PackageManager#setSystemAppState
+ */
+ default boolean isHiddenUntilInstalled() { return false; }
+
+ default boolean isInstallPermissionsFixed() { return false; }
+
+ /**
+ * @see AndroidPackageApi#isOdm()
+ */
+ default boolean isOdm() { return false; }
+
+ /**
+ * @see AndroidPackageApi#isOem()
+ */
+ default boolean isOem() { return false; }
+
+ /**
+ * @see AndroidPackageApi#isPrivileged()
+ */
+ default boolean isPrivileged() { return false; }
+
+ /**
+ * @see AndroidPackageApi#isProduct()
+ */
+ default boolean isProduct() { return false; }
+
+ /**
+ * @see ApplicationInfo#PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER
+ */
+ default boolean isRequiredForSystemUser() { return false; }
+
+ /**
+ * @see AndroidPackageApi#isSystem()
+ */
+ default boolean isSystem() { return false; }
+
+ /**
+ * @see AndroidPackageApi#isSystemExt()
+ */
+ default boolean isSystemExt() { return false; }
+
+ /**
+ * Whether or not an update is available. Ostensibly only for instant apps.
+ */
+ default boolean isUpdateAvailable() { return false; }
+
+ /**
+ * Whether this app is on the /data partition having been upgraded from a preinstalled app on a
+ * system partition.
+ */
+ default boolean isUpdatedSystemApp() { return false; }
+
+ /**
+ * @see AndroidPackageApi#isVendor()
+ */
+ default boolean isVendor() { return false; }
+}
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
new file mode 100644
index 0000000..6cd55c1
--- /dev/null
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
@@ -0,0 +1,651 @@
+/*
+ * Copyright (C) 2020 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.pkg;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.content.pm.SharedLibraryInfo;
+import android.content.pm.SigningInfo;
+import android.content.pm.overlay.OverlayPaths;
+import android.content.pm.pkg.PackageUserState;
+import android.util.SparseArray;
+
+import com.android.internal.util.DataClass;
+import com.android.server.pm.PackageManagerService;
+import com.android.server.pm.PackageSetting;
+import com.android.server.pm.Settings;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+
+/**
+ * Because a {@link PackageSetting} cannot be returned from {@link Settings} without holding the
+ * {@link PackageManagerService#mLock}, this class serves as a memory snapshot of the state of a
+ * single package, for use with {@link PackageManagerInternal#getPackageState(String)} and {@link
+ * PackageManagerInternal#forEachPackageState(boolean, Consumer)}.
+ *
+ * @hide
+ */
+@DataClass(genConstructor = false)
+@DataClass.Suppress({"mUserStates"})
+public class PackageStateImpl implements PackageState {
+
+ public static PackageState copy(@NonNull PackageSetting pkgSetting) {
+ return new PackageStateImpl(pkgSetting, pkgSetting.getPkg());
+ }
+
+ private static class Booleans {
+ @IntDef({
+ SYSTEM,
+ EXTERNAL_STORAGE,
+ PRIVILEGED,
+ OEM,
+ VENDOR,
+ PRODUCT,
+ SYSTEM_EXT,
+ REQUIRED_FOR_SYSTEM_USER,
+ ODM,
+ FORCE_QUERYABLE_OVERRIDE,
+ HIDDEN_UNTIL_INSTALLED,
+ INSTALL_PERMISSIONS_FIXED,
+ UPDATE_AVAILABLE,
+ UPDATED_SYSTEM_APP,
+ })
+ public @interface Flags {
+ }
+
+ private static final int SYSTEM = 1;
+ private static final int EXTERNAL_STORAGE = 1 << 1;
+ private static final int PRIVILEGED = 1 << 2;
+ private static final int OEM = 1 << 3;
+ private static final int VENDOR = 1 << 4;
+ private static final int PRODUCT = 1 << 5;
+ private static final int SYSTEM_EXT = 1 << 6;
+ private static final int REQUIRED_FOR_SYSTEM_USER = 1 << 7;
+ private static final int ODM = 1 << 8;
+ private static final int FORCE_QUERYABLE_OVERRIDE = 1 << 9;
+ private static final int HIDDEN_UNTIL_INSTALLED = 1 << 10;
+ private static final int INSTALL_PERMISSIONS_FIXED = 1 << 11;
+ private static final int UPDATE_AVAILABLE = 1 << 12;
+ private static final int UPDATED_SYSTEM_APP = 1 << 13;
+ }
+
+ private int mBooleans;
+
+ private void setBoolean(@Booleans.Flags int flag, boolean value) {
+ if (value) {
+ mBooleans |= flag;
+ } else {
+ mBooleans &= ~flag;
+ }
+ }
+
+ private boolean getBoolean(@Booleans.Flags int flag) {
+ return (mBooleans & flag) != 0;
+ }
+
+ @Nullable
+ private final AndroidPackageApi mAndroidPackage;
+
+ @NonNull
+ private final String mPackageName;
+ @Nullable
+ private final String mVolumeUuid;
+ private final int mAppId;
+ private final int mCategoryOverride;
+ @Nullable
+ private final String mCpuAbiOverride;
+ private final long mFirstInstallTime;
+ private final long mLastModifiedTime;
+ private final long mLastUpdateTime;
+ private final long mLongVersionCode;
+ @NonNull
+ private final Map<String, Set<String>> mMimeGroups;
+ @NonNull
+ private final File mPath;
+ @Nullable
+ private final String mPrimaryCpuAbi;
+ @Nullable
+ private final String mSecondaryCpuAbi;
+ @Nullable
+ private final Integer mSharedUserId;
+ @NonNull
+ private final String[] mUsesStaticLibraries;
+ @NonNull
+ private final long[] mUsesStaticLibrariesVersions;
+ @NonNull
+ private final List<SharedLibraryInfo> mUsesLibraryInfos;
+ @NonNull
+ private final List<String> mUsesLibraryFiles;
+ @Nullable
+ private final String mSeInfoOverride;
+ @NonNull
+ private final long[] mLastPackageUsageTime;
+ @NonNull
+ private final SigningInfo mSigningInfo;
+ @NonNull
+ private final int[] mUserIds;
+ @NonNull
+ private final SparseArray<PackageUserState> mUserStates;
+
+ private PackageStateImpl(@NonNull PackageState pkgState, @Nullable AndroidPackage pkg) {
+ mAndroidPackage = pkg;
+
+ setBoolean(Booleans.SYSTEM, pkgState.isSystem());
+ setBoolean(Booleans.EXTERNAL_STORAGE, pkgState.isExternalStorage());
+ setBoolean(Booleans.PRIVILEGED, pkgState.isPrivileged());
+ setBoolean(Booleans.OEM, pkgState.isOem());
+ setBoolean(Booleans.VENDOR, pkgState.isVendor());
+ setBoolean(Booleans.PRODUCT, pkgState.isProduct());
+ setBoolean(Booleans.SYSTEM_EXT, pkgState.isSystemExt());
+ setBoolean(Booleans.REQUIRED_FOR_SYSTEM_USER, pkgState.isRequiredForSystemUser());
+ setBoolean(Booleans.ODM, pkgState.isOdm());
+
+ mPackageName = pkgState.getPackageName();
+ mVolumeUuid = pkgState.getVolumeUuid();
+ mAppId = pkgState.getAppId();
+ mCategoryOverride = pkgState.getCategoryOverride();
+ mCpuAbiOverride = pkgState.getCpuAbiOverride();
+ mFirstInstallTime = pkgState.getFirstInstallTime();
+ mLastModifiedTime = pkgState.getLastModifiedTime();
+ mLastUpdateTime = pkgState.getLastUpdateTime();
+ mLongVersionCode = pkgState.getLongVersionCode();
+ mMimeGroups = pkgState.getMimeGroups();
+ mPath = pkgState.getPath();
+ mPrimaryCpuAbi = pkgState.getPrimaryCpuAbi();
+ mSecondaryCpuAbi = pkgState.getSecondaryCpuAbi();
+ mSharedUserId = pkgState.getSharedUserId();
+ mUsesStaticLibraries = pkgState.getUsesStaticLibraries();
+ mUsesStaticLibrariesVersions = pkgState.getUsesStaticLibrariesVersions();
+ mUsesLibraryInfos = pkgState.getUsesLibraryInfos();
+ mUsesLibraryFiles = pkgState.getUsesLibraryFiles();
+ setBoolean(Booleans.FORCE_QUERYABLE_OVERRIDE, pkgState.isForceQueryableOverride());
+ setBoolean(Booleans.HIDDEN_UNTIL_INSTALLED, pkgState.isHiddenUntilInstalled());
+ setBoolean(Booleans.INSTALL_PERMISSIONS_FIXED, pkgState.isInstallPermissionsFixed());
+ setBoolean(Booleans.UPDATE_AVAILABLE, pkgState.isUpdateAvailable());
+ mSeInfoOverride = pkgState.getSeInfoOverride();
+ mLastPackageUsageTime = pkgState.getLastPackageUsageTime();
+ setBoolean(Booleans.UPDATED_SYSTEM_APP, pkgState.isUpdatedSystemApp());
+ mSigningInfo = pkgState.getSigningInfo();
+
+ mUserIds = pkgState.getUserIds();
+ mUserStates = new SparseArray<>(mUserIds.length);
+ for (int userId : mUserIds) {
+ mUserStates.put(userId, UserStateImpl.copy(pkgState.getUserState(userId)));
+ }
+ }
+
+ @Nullable
+ @Override
+ public PackageUserState getUserState(int userId) {
+ return mUserStates.get(userId);
+ }
+
+ @Override
+ public boolean isExternalStorage() {
+ return getBoolean(Booleans.EXTERNAL_STORAGE);
+ }
+
+ @Override
+ public boolean isForceQueryableOverride() {
+ return getBoolean(Booleans.FORCE_QUERYABLE_OVERRIDE);
+ }
+
+ @Override
+ public boolean isHiddenUntilInstalled() {
+ return getBoolean(Booleans.HIDDEN_UNTIL_INSTALLED);
+ }
+
+ @Override
+ public boolean isInstallPermissionsFixed() {
+ return getBoolean(Booleans.INSTALL_PERMISSIONS_FIXED);
+ }
+
+ @Override
+ public boolean isOdm() {
+ return getBoolean(Booleans.ODM);
+ }
+
+ @Override
+ public boolean isOem() {
+ return getBoolean(Booleans.OEM);
+ }
+
+ @Override
+ public boolean isPrivileged() {
+ return getBoolean(Booleans.PRIVILEGED);
+ }
+
+ @Override
+ public boolean isProduct() {
+ return getBoolean(Booleans.PRODUCT);
+ }
+
+ @Override
+ public boolean isRequiredForSystemUser() {
+ return getBoolean(Booleans.REQUIRED_FOR_SYSTEM_USER);
+ }
+
+ @Override
+ public boolean isSystem() {
+ return getBoolean(Booleans.SYSTEM);
+ }
+
+ @Override
+ public boolean isSystemExt() {
+ return getBoolean(Booleans.SYSTEM_EXT);
+ }
+
+ @Override
+ public boolean isUpdateAvailable() {
+ return getBoolean(Booleans.UPDATE_AVAILABLE);
+ }
+
+ @Override
+ public boolean isUpdatedSystemApp() {
+ return getBoolean(Booleans.UPDATED_SYSTEM_APP);
+ }
+
+ @Override
+ public boolean isVendor() {
+ return getBoolean(Booleans.VENDOR);
+ }
+
+ /**
+ * @hide
+ */
+ @DataClass(genConstructor = false)
+ public static class UserStateImpl implements PackageUserState {
+
+ public static PackageUserState copy(@NonNull PackageUserState state) {
+ return new UserStateImpl(state);
+ }
+
+ private static class Booleans {
+ @IntDef({
+ HIDDEN,
+ INSTALLED,
+ INSTANT_APP,
+ NOT_LAUNCHED,
+ STOPPED,
+ SUSPENDED,
+ VIRTUAL_PRELOAD,
+ })
+ public @interface Flags {
+ }
+
+ private static final int HIDDEN = 1;
+ private static final int INSTALLED = 1 << 1;
+ private static final int INSTANT_APP = 1 << 2;
+ private static final int NOT_LAUNCHED = 1 << 3;
+ private static final int STOPPED = 1 << 4;
+ private static final int SUSPENDED = 1 << 5;
+ private static final int VIRTUAL_PRELOAD = 1 << 6;
+ }
+
+ private int mBooleans;
+
+ private void setBoolean(@Booleans.Flags int flag, boolean value) {
+ if (value) {
+ mBooleans |= flag;
+ } else {
+ mBooleans &= ~flag;
+ }
+ }
+
+ private boolean getBoolean(@Booleans.Flags int flag) {
+ return (mBooleans & flag) != 0;
+ }
+
+ private final long mCeDataInode;
+ @NonNull
+ private final Set<String> mDisabledComponents;
+ @PackageManager.DistractionRestriction
+ private final int mDistractionFlags;
+ @NonNull
+ private final Set<String> mEnabledComponents;
+ private final int mEnabledState;
+ @Nullable
+ private final String mHarmfulAppWarning;
+ @PackageManager.InstallReason
+ private final int mInstallReason;
+ @Nullable
+ private final String mLastDisableAppCaller;
+ @NonNull
+ private final OverlayPaths mOverlayPaths;
+ @NonNull
+ private final Map<String, OverlayPaths> mSharedLibraryOverlayPaths;
+ @PackageManager.UninstallReason
+ private final int mUninstallReason;
+
+ private UserStateImpl(@NonNull PackageUserState userState) {
+ mCeDataInode = userState.getCeDataInode();
+ mDisabledComponents = userState.getDisabledComponents();
+ mDistractionFlags = userState.getDistractionFlags();
+ mEnabledComponents = userState.getEnabledComponents();
+ mEnabledState = userState.getEnabledState();
+ mHarmfulAppWarning = userState.getHarmfulAppWarning();
+ mInstallReason = userState.getInstallReason();
+ mLastDisableAppCaller = userState.getLastDisableAppCaller();
+ mOverlayPaths = userState.getOverlayPaths();
+ mSharedLibraryOverlayPaths = userState.getSharedLibraryOverlayPaths();
+ mUninstallReason = userState.getUninstallReason();
+ setBoolean(Booleans.HIDDEN, userState.isHidden());
+ setBoolean(Booleans.INSTALLED, userState.isInstalled());
+ setBoolean(Booleans.INSTANT_APP, userState.isInstantApp());
+ setBoolean(Booleans.NOT_LAUNCHED, userState.isNotLaunched());
+ setBoolean(Booleans.STOPPED, userState.isStopped());
+ setBoolean(Booleans.SUSPENDED, userState.isSuspended());
+ setBoolean(Booleans.VIRTUAL_PRELOAD, userState.isVirtualPreload());
+ }
+
+ @Override
+ public boolean isHidden() {
+ return getBoolean(Booleans.HIDDEN);
+ }
+
+ @Override
+ public boolean isInstalled() {
+ return getBoolean(Booleans.INSTALLED);
+ }
+
+ @Override
+ public boolean isInstantApp() {
+ return getBoolean(Booleans.INSTANT_APP);
+ }
+
+ @Override
+ public boolean isNotLaunched() {
+ return getBoolean(Booleans.NOT_LAUNCHED);
+ }
+
+ @Override
+ public boolean isStopped() {
+ return getBoolean(Booleans.STOPPED);
+ }
+
+ @Override
+ public boolean isSuspended() {
+ return getBoolean(Booleans.SUSPENDED);
+ }
+
+ @Override
+ public boolean isVirtualPreload() {
+ return getBoolean(Booleans.VIRTUAL_PRELOAD);
+ }
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ public int getBooleans() {
+ return mBooleans;
+ }
+
+ @DataClass.Generated.Member
+ public long getCeDataInode() {
+ return mCeDataInode;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull Set<String> getDisabledComponents() {
+ return mDisabledComponents;
+ }
+
+ @DataClass.Generated.Member
+ public @PackageManager.DistractionRestriction int getDistractionFlags() {
+ return mDistractionFlags;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull Set<String> getEnabledComponents() {
+ return mEnabledComponents;
+ }
+
+ @DataClass.Generated.Member
+ public int getEnabledState() {
+ return mEnabledState;
+ }
+
+ @DataClass.Generated.Member
+ public @Nullable String getHarmfulAppWarning() {
+ return mHarmfulAppWarning;
+ }
+
+ @DataClass.Generated.Member
+ public @PackageManager.InstallReason int getInstallReason() {
+ return mInstallReason;
+ }
+
+ @DataClass.Generated.Member
+ public @Nullable String getLastDisableAppCaller() {
+ return mLastDisableAppCaller;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull OverlayPaths getOverlayPaths() {
+ return mOverlayPaths;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull Map<String,OverlayPaths> getSharedLibraryOverlayPaths() {
+ return mSharedLibraryOverlayPaths;
+ }
+
+ @DataClass.Generated.Member
+ public @PackageManager.UninstallReason int getUninstallReason() {
+ return mUninstallReason;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull UserStateImpl setBooleans( int value) {
+ mBooleans = value;
+ return this;
+ }
+
+ @DataClass.Generated(
+ time = 1630602933994L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java",
+ inputSignatures = "private int mBooleans\nprivate final long mCeDataInode\nprivate final @android.annotation.NonNull java.util.Set<java.lang.String> mDisabledComponents\nprivate final @android.content.pm.PackageManager.DistractionRestriction int mDistractionFlags\nprivate final @android.annotation.NonNull java.util.Set<java.lang.String> mEnabledComponents\nprivate final int mEnabledState\nprivate final @android.annotation.Nullable java.lang.String mHarmfulAppWarning\nprivate final @android.content.pm.PackageManager.InstallReason int mInstallReason\nprivate final @android.annotation.Nullable java.lang.String mLastDisableAppCaller\nprivate final @android.annotation.NonNull android.content.pm.overlay.OverlayPaths mOverlayPaths\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,android.content.pm.overlay.OverlayPaths> mSharedLibraryOverlayPaths\nprivate final @android.content.pm.PackageManager.UninstallReason int mUninstallReason\npublic static android.content.pm.pkg.PackageUserState copy(android.content.pm.pkg.PackageUserState)\nprivate void setBoolean(int,boolean)\nprivate boolean getBoolean(int)\npublic @java.lang.Override boolean isHidden()\npublic @java.lang.Override boolean isInstalled()\npublic @java.lang.Override boolean isInstantApp()\npublic @java.lang.Override boolean isNotLaunched()\npublic @java.lang.Override boolean isStopped()\npublic @java.lang.Override boolean isSuspended()\npublic @java.lang.Override boolean isVirtualPreload()\nclass UserStateImpl extends java.lang.Object implements [android.content.pm.pkg.PackageUserState]\nprivate static final int HIDDEN\nprivate static final int INSTALLED\nprivate static final int INSTANT_APP\nprivate static final int NOT_LAUNCHED\nprivate static final int STOPPED\nprivate static final int SUSPENDED\nprivate static final int VIRTUAL_PRELOAD\nclass Booleans extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+ }
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ public int getBooleans() {
+ return mBooleans;
+ }
+
+ @DataClass.Generated.Member
+ public @Nullable AndroidPackageApi getAndroidPackage() {
+ return mAndroidPackage;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull String getPackageName() {
+ return mPackageName;
+ }
+
+ @DataClass.Generated.Member
+ public @Nullable String getVolumeUuid() {
+ return mVolumeUuid;
+ }
+
+ @DataClass.Generated.Member
+ public int getAppId() {
+ return mAppId;
+ }
+
+ @DataClass.Generated.Member
+ public int getCategoryOverride() {
+ return mCategoryOverride;
+ }
+
+ @DataClass.Generated.Member
+ public @Nullable String getCpuAbiOverride() {
+ return mCpuAbiOverride;
+ }
+
+ @DataClass.Generated.Member
+ public long getFirstInstallTime() {
+ return mFirstInstallTime;
+ }
+
+ @DataClass.Generated.Member
+ public long getLastModifiedTime() {
+ return mLastModifiedTime;
+ }
+
+ @DataClass.Generated.Member
+ public long getLastUpdateTime() {
+ return mLastUpdateTime;
+ }
+
+ @DataClass.Generated.Member
+ public long getLongVersionCode() {
+ return mLongVersionCode;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull Map<String,Set<String>> getMimeGroups() {
+ return mMimeGroups;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull File getPath() {
+ return mPath;
+ }
+
+ @DataClass.Generated.Member
+ public @Nullable String getPrimaryCpuAbi() {
+ return mPrimaryCpuAbi;
+ }
+
+ @DataClass.Generated.Member
+ public @Nullable String getSecondaryCpuAbi() {
+ return mSecondaryCpuAbi;
+ }
+
+ @DataClass.Generated.Member
+ public @Nullable Integer getSharedUserId() {
+ return mSharedUserId;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull String[] getUsesStaticLibraries() {
+ return mUsesStaticLibraries;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull long[] getUsesStaticLibrariesVersions() {
+ return mUsesStaticLibrariesVersions;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull List<SharedLibraryInfo> getUsesLibraryInfos() {
+ return mUsesLibraryInfos;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull List<String> getUsesLibraryFiles() {
+ return mUsesLibraryFiles;
+ }
+
+ @DataClass.Generated.Member
+ public @Nullable String getSeInfoOverride() {
+ return mSeInfoOverride;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull long[] getLastPackageUsageTime() {
+ return mLastPackageUsageTime;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull SigningInfo getSigningInfo() {
+ return mSigningInfo;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull int[] getUserIds() {
+ return mUserIds;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull SparseArray<PackageUserState> getUserStates() {
+ return mUserStates;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull PackageStateImpl setBooleans( int value) {
+ mBooleans = value;
+ return this;
+ }
+
+ @DataClass.Generated(
+ time = 1630602934025L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java",
+ inputSignatures = "private int mBooleans\nprivate final @android.annotation.Nullable com.android.server.pm.pkg.AndroidPackageApi mAndroidPackage\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mVolumeUuid\nprivate final int mAppId\nprivate final int mCategoryOverride\nprivate final @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate final long mFirstInstallTime\nprivate final long mLastModifiedTime\nprivate final long mLastUpdateTime\nprivate final long mLongVersionCode\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mMimeGroups\nprivate final @android.annotation.NonNull java.io.File mPath\nprivate final @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.Integer mSharedUserId\nprivate final @android.annotation.NonNull java.lang.String[] mUsesStaticLibraries\nprivate final @android.annotation.NonNull long[] mUsesStaticLibrariesVersions\nprivate final @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> mUsesLibraryInfos\nprivate final @android.annotation.NonNull java.util.List<java.lang.String> mUsesLibraryFiles\nprivate final @android.annotation.Nullable java.lang.String mSeInfoOverride\nprivate final @android.annotation.NonNull long[] mLastPackageUsageTime\nprivate final @android.annotation.NonNull android.content.pm.SigningInfo mSigningInfo\nprivate final @android.annotation.NonNull int[] mUserIds\nprivate final @android.annotation.NonNull android.util.SparseArray<android.content.pm.pkg.PackageUserState> mUserStates\npublic static com.android.server.pm.pkg.PackageState copy(com.android.server.pm.PackageSetting)\nprivate void setBoolean(int,boolean)\nprivate boolean getBoolean(int)\npublic @android.annotation.Nullable @java.lang.Override android.content.pm.pkg.PackageUserState getUserState(int)\npublic @java.lang.Override boolean isExternalStorage()\npublic @java.lang.Override boolean isForceQueryableOverride()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @java.lang.Override boolean isInstallPermissionsFixed()\npublic @java.lang.Override boolean isOdm()\npublic @java.lang.Override boolean isOem()\npublic @java.lang.Override boolean isPrivileged()\npublic @java.lang.Override boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic @java.lang.Override boolean isSystem()\npublic @java.lang.Override boolean isSystemExt()\npublic @java.lang.Override boolean isUpdateAvailable()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Override boolean isVendor()\nclass PackageStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageState]\nprivate static final int SYSTEM\nprivate static final int EXTERNAL_STORAGE\nprivate static final int PRIVILEGED\nprivate static final int OEM\nprivate static final int VENDOR\nprivate static final int PRODUCT\nprivate static final int SYSTEM_EXT\nprivate static final int REQUIRED_FOR_SYSTEM_USER\nprivate static final int ODM\nprivate static final int FORCE_QUERYABLE_OVERRIDE\nprivate static final int HIDDEN_UNTIL_INSTALLED\nprivate static final int INSTALL_PERMISSIONS_FIXED\nprivate static final int UPDATE_AVAILABLE\nprivate static final int UPDATED_SYSTEM_APP\nclass Booleans extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
index ba64d25..8dc02b7 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
@@ -843,7 +843,7 @@
@Override
public void migrateState(@NonNull PackageSetting oldPkgSetting,
@NonNull PackageSetting newPkgSetting) {
- String pkgName = newPkgSetting.getName();
+ String pkgName = newPkgSetting.getPackageName();
boolean sendBroadcast;
synchronized (mLock) {
@@ -936,7 +936,7 @@
// gains or loses all domains.
UUID domainSetId = newPkgSetting.getDomainSetId();
- String pkgName = newPkgSetting.getName();
+ String pkgName = newPkgSetting.getPackageName();
boolean sendBroadcast = true;
@@ -1032,7 +1032,7 @@
@NonNull ArrayMap<String, Integer> stateMap,
@NonNull ArraySet<String> autoVerifyDomains) {
if (pkgSetting.isSystem()
- && mSystemConfig.getLinkedApps().contains(pkgSetting.getName())) {
+ && mSystemConfig.getLinkedApps().contains(pkgSetting.getPackageName())) {
int domainsSize = autoVerifyDomains.size();
for (int index = 0; index < domainsSize; index++) {
stateMap.put(autoVerifyDomains.valueAt(index),
@@ -1718,7 +1718,7 @@
@Override
public int approvalLevelForDomain(@NonNull PackageSetting pkgSetting, @NonNull Intent intent,
@PackageManager.ResolveInfoFlags int resolveInfoFlags, @UserIdInt int userId) {
- String packageName = pkgSetting.getName();
+ String packageName = pkgSetting.getPackageName();
if (!DomainVerificationUtils.isDomainVerificationIntent(intent, resolveInfoFlags)) {
if (DEBUG_APPROVAL) {
debugApproval(packageName, intent, userId, false, "not valid intent");
@@ -1762,7 +1762,7 @@
private int approvalLevelForDomainInternal(@NonNull PackageSetting pkgSetting,
@NonNull String host, boolean includeNegative, @UserIdInt int userId,
@NonNull Object debugObject) {
- String packageName = pkgSetting.getName();
+ String packageName = pkgSetting.getPackageName();
final AndroidPackage pkg = pkgSetting.getPkg();
if (pkg != null && includeNegative && !mCollector.containsWebDomain(pkg, host)) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ccd9709..3185a28 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -230,6 +230,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
+import java.util.List;
/**
* WindowManagerPolicy implementation for the Android phone UI. This
@@ -3385,13 +3386,18 @@
}
}
}
- } else if (ExtconUEventObserver.extconExists()
- && ExtconUEventObserver.namedExtconDirExists(HdmiVideoExtconUEventObserver.NAME)) {
- HdmiVideoExtconUEventObserver observer = new HdmiVideoExtconUEventObserver();
- plugged = observer.init();
- mHDMIObserver = observer;
- } else if (localLOGV) {
- Slog.v(TAG, "Not observing HDMI plug state because HDMI was not found.");
+ } else {
+ final List<ExtconUEventObserver.ExtconInfo> extcons =
+ ExtconUEventObserver.ExtconInfo.getExtconInfoForTypes(
+ new String[] {ExtconUEventObserver.ExtconInfo.EXTCON_HDMI});
+ if (!extcons.isEmpty()) {
+ // TODO: handle more than one HDMI
+ HdmiVideoExtconUEventObserver observer = new HdmiVideoExtconUEventObserver();
+ plugged = observer.init(extcons.get(0));
+ mHDMIObserver = observer;
+ } else if (localLOGV) {
+ Slog.v(TAG, "Not observing HDMI plug state because HDMI was not found.");
+ }
}
// This dance forces the code in setHdmiPlugged to run.
@@ -5604,23 +5610,23 @@
private class HdmiVideoExtconUEventObserver extends ExtconStateObserver<Boolean> {
private static final String HDMI_EXIST = "HDMI=1";
private static final String NAME = "hdmi";
- private final ExtconInfo mHdmi = new ExtconInfo(NAME);
- private boolean init() {
+ private boolean init(ExtconInfo hdmi) {
boolean plugged = false;
try {
- plugged = parseStateFromFile(mHdmi);
+ plugged = parseStateFromFile(hdmi);
} catch (FileNotFoundException e) {
- Slog.w(TAG, mHdmi.getStatePath()
- + " not found while attempting to determine initial state", e);
+ Slog.w(TAG,
+ hdmi.getStatePath()
+ + " not found while attempting to determine initial state",
+ e);
} catch (IOException e) {
- Slog.e(
- TAG,
- "Error reading " + mHdmi.getStatePath()
+ Slog.e(TAG,
+ "Error reading " + hdmi.getStatePath()
+ " while attempting to determine initial state",
e);
}
- startObserving(mHdmi);
+ startObserving(hdmi);
return plugged;
}
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 2cfc785..f973f5c 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -43,7 +43,6 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.PrintWriter;
import java.nio.file.Files;
import java.text.ParseException;
import java.time.Instant;
@@ -323,9 +322,8 @@
"extensionVersions", extensionVersionsToJson(rollback.getExtensionVersions()));
fos = file.startWrite();
- PrintWriter pw = new PrintWriter(fos);
- pw.println(dataJson.toString());
- pw.close();
+ fos.write(dataJson.toString().getBytes());
+ fos.flush();
file.finishWrite(fos);
} catch (JSONException | IOException e) {
Slog.e(TAG, "Unable to save rollback for: " + rollback.info.getRollbackId(), e);
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index 382398a..e0cc8e1 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -352,7 +352,7 @@
}
private void handleSafeModeStatusChanged() {
- logDbg("VcnGatewayConnection safe mode status changed");
+ logVdbg("VcnGatewayConnection safe mode status changed");
boolean hasSafeModeGatewayConnection = false;
// If any VcnGatewayConnection is in safe mode, mark the entire VCN as being in safe mode
@@ -368,7 +368,7 @@
hasSafeModeGatewayConnection ? VCN_STATUS_CODE_SAFE_MODE : VCN_STATUS_CODE_ACTIVE;
if (oldStatus != mCurrentStatus) {
mVcnCallback.onSafeModeStatusChanged(hasSafeModeGatewayConnection);
- logDbg(
+ logInfo(
"Safe mode "
+ (mCurrentStatus == VCN_STATUS_CODE_SAFE_MODE ? "entered" : "exited"));
}
@@ -539,6 +539,16 @@
Slog.d(TAG, getLogPrefix() + msg, tr);
}
+ private void logInfo(String msg) {
+ Slog.i(TAG, getLogPrefix() + msg);
+ LOCAL_LOG.log(getLogPrefix() + "INFO: " + msg);
+ }
+
+ private void logInfo(String msg, Throwable tr) {
+ Slog.i(TAG, getLogPrefix() + msg, tr);
+ LOCAL_LOG.log(getLogPrefix() + "INFO: " + msg + tr);
+ }
+
private void logErr(String msg) {
Slog.e(TAG, getLogPrefix() + msg);
LOCAL_LOG.log(getLogPrefix() + "ERR: " + msg);
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 450257f..7dec4e7 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -1677,10 +1677,8 @@
mFailedAttempts = 0;
cancelSafeModeAlarm();
- if (mIsInSafeMode) {
- mIsInSafeMode = false;
- mGatewayStatusCallback.onSafeModeStatusChanged();
- }
+ mIsInSafeMode = false;
+ mGatewayStatusCallback.onSafeModeStatusChanged();
}
protected void applyTransform(
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index e48593c..6d89daa 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -208,7 +208,7 @@
* wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
* every time the wallpaper is changed.
*/
- private class WallpaperObserver extends FileObserver {
+ class WallpaperObserver extends FileObserver {
final int mUserId;
final WallpaperData mWallpaper;
@@ -226,7 +226,7 @@
mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG);
}
- private WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
+ WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
WallpaperData wallpaper = null;
synchronized (mLock) {
if (lockChanged) {
@@ -309,9 +309,18 @@
}
wallpaper.imageWallpaperPending = false;
if (sysWallpaperChanged) {
+ IRemoteCallback.Stub callback = new IRemoteCallback.Stub() {
+ @Override
+ public void sendResult(Bundle data) throws RemoteException {
+ if (DEBUG) {
+ Slog.d(TAG, "publish system wallpaper changed!");
+ }
+ notifyWallpaperChanged(wallpaper);
+ }
+ };
// If this was the system wallpaper, rebind...
bindWallpaperComponentLocked(mImageWallpaper, true,
- false, wallpaper, null);
+ false, wallpaper, callback);
notifyColorsWhich |= FLAG_SYSTEM;
}
if (lockWallpaperChanged
@@ -331,15 +340,9 @@
}
saveSettingsLocked(wallpaper.userId);
-
- // Publish completion *after* we've persisted the changes
- if (wallpaper.setComplete != null) {
- try {
- wallpaper.setComplete.onWallpaperChanged();
- } catch (RemoteException e) {
- // if this fails we don't really care; the setting app may just
- // have crashed and that sort of thing is a fact of life.
- }
+ // Notify the client immediately if only lockscreen wallpaper changed.
+ if (lockWallpaperChanged && !sysWallpaperChanged) {
+ notifyWallpaperChanged(wallpaper);
}
}
}
@@ -353,6 +356,18 @@
}
}
+ private void notifyWallpaperChanged(WallpaperData wallpaper) {
+ // Publish completion *after* we've persisted the changes
+ if (wallpaper.setComplete != null) {
+ try {
+ wallpaper.setComplete.onWallpaperChanged();
+ } catch (RemoteException e) {
+ // if this fails we don't really care; the setting app may just
+ // have crashed and that sort of thing is a fact of life.
+ }
+ }
+ }
+
private void notifyLockWallpaperChanged() {
final IWallpaperManagerCallback cb = mKeyguardListener;
if (cb != null) {
@@ -364,7 +379,7 @@
}
}
- private void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) {
+ void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) {
if (wallpaper.connection != null) {
wallpaper.connection.forEachDisplayConnector(connector -> {
notifyWallpaperColorsChangedOnDisplay(wallpaper, which, connector.mDisplayId);
@@ -568,7 +583,7 @@
* Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
* for display.
*/
- private void generateCrop(WallpaperData wallpaper) {
+ void generateCrop(WallpaperData wallpaper) {
boolean success = false;
// Only generate crop for default display.
@@ -2834,7 +2849,7 @@
return false;
}
- private boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
+ boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
if (DEBUG_LIVE) {
Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
@@ -3121,7 +3136,7 @@
return new JournaledFile(new File(base), new File(base + ".tmp"));
}
- private void saveSettingsLocked(int userId) {
+ void saveSettingsLocked(int userId) {
JournaledFile journal = makeJournaledFile(userId);
FileOutputStream fstream = null;
try {
@@ -3270,7 +3285,7 @@
* Important: this method loads settings to initialize the given user's wallpaper data if
* there is no current in-memory state.
*/
- private WallpaperData getWallpaperSafeLocked(int userId, int which) {
+ WallpaperData getWallpaperSafeLocked(int userId, int which) {
// We're setting either just system (work with the system wallpaper),
// both (also work with the system wallpaper), or just the lock
// wallpaper (update against the existing lock wallpaper if any).
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 2b57179..ab799d1 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -1590,7 +1590,7 @@
boolean focusedWindowAdded = false;
final int visibleWindowCount = visibleWindows.size();
- HashSet<Integer> skipRemainingWindowsForTasks = new HashSet<>();
+ ArrayList<TaskFragment> skipRemainingWindowsForTaskFragments = new ArrayList<>();
ArrayList<ShellRoot> shellRoots = getSortedShellRoots(dc.mShellRoots);
@@ -1612,10 +1612,10 @@
computeWindowRegionInScreen(windowState, regionInScreen);
if (windowMattersToAccessibility(windowState, regionInScreen, unaccountedSpace,
- skipRemainingWindowsForTasks)) {
+ skipRemainingWindowsForTaskFragments)) {
addPopulatedWindowInfo(windowState, regionInScreen, windows, addedWindows);
updateUnaccountedSpace(windowState, regionInScreen, unaccountedSpace,
- skipRemainingWindowsForTasks);
+ skipRemainingWindowsForTaskFragments);
focusedWindowAdded |= windowState.isFocused();
} else if (isUntouchableNavigationBar(windowState, mTempRegion1)) {
// If this widow is navigation bar without touchable region, accounting the
@@ -1666,7 +1666,7 @@
private boolean windowMattersToAccessibility(WindowState windowState,
Region regionInScreen, Region unaccountedSpace,
- HashSet<Integer> skipRemainingWindowsForTasks) {
+ ArrayList<TaskFragment> skipRemainingWindowsForTaskFragments) {
final RecentsAnimationController controller = mService.getRecentsAnimationController();
if (controller != null && controller.shouldIgnoreForAccessibility(windowState)) {
return false;
@@ -1677,8 +1677,9 @@
}
// If the window is part of a task that we're finished with - ignore.
- final Task task = windowState.getTask();
- if (task != null && skipRemainingWindowsForTasks.contains(task.mTaskId)) {
+ final TaskFragment taskFragment = windowState.getTaskFragment();
+ if (taskFragment != null
+ && skipRemainingWindowsForTaskFragments.contains(taskFragment)) {
return false;
}
@@ -1704,7 +1705,8 @@
}
private void updateUnaccountedSpace(WindowState windowState, Region regionInScreen,
- Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) {
+ Region unaccountedSpace,
+ ArrayList<TaskFragment> skipRemainingWindowsForTaskFragments) {
if (windowState.mAttrs.type
!= WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
@@ -1734,11 +1736,11 @@
Region.Op.REVERSE_DIFFERENCE);
}
- final Task task = windowState.getTask();
- if (task != null) {
+ final TaskFragment taskFragment = windowState.getTaskFragment();
+ if (taskFragment != null) {
// If the window is associated with a particular task, we can skip the
// rest of the windows for that task.
- skipRemainingWindowsForTasks.add(task.mTaskId);
+ skipRemainingWindowsForTaskFragments.add(taskFragment);
} else if (!windowState.hasTapExcludeRegion()) {
// If the window is not associated with a particular task, then it is
// globally modal. In this case we can skip all remaining windows when
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 042f4f6..7f12fff 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -7528,11 +7528,7 @@
parentAppBounds.width(), screenResolvedBounds.width());
} else {
float positionMultiplier =
- mWmService.mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier();
- positionMultiplier =
- (positionMultiplier < 0.0f || positionMultiplier > 1.0f)
- // Default to central position if invalid value is provided.
- ? 0.5f : positionMultiplier;
+ mLetterboxUiController.getHorizontalPositionMultiplier(newParentConfiguration);
offsetX = (int) Math.ceil((parentAppBounds.width() - screenResolvedBounds.width())
* positionMultiplier);
}
@@ -7549,6 +7545,15 @@
getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration);
}
+ void recomputeConfiguration() {
+ onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
+ }
+
+ boolean isInTransition() {
+ return mAtmService.getTransitionController().inTransition() // Shell transitions.
+ || isAnimating(PARENTS | TRANSITION); // Legacy transitions.
+ }
+
/**
* Whether this activity is letterboxed for fixed orientation. If letterboxed due to fixed
* orientation then aspect ratio restrictions are also already respected.
@@ -7651,6 +7656,7 @@
// If the activity requires a different orientation (either by override or activityInfo),
// make it fit the available bounds by scaling down its bounds.
final int forcedOrientation = getRequestedConfigurationOrientation();
+
if (forcedOrientation == ORIENTATION_UNDEFINED
|| (forcedOrientation == parentOrientation && orientationRespectedWithInsets)) {
return;
@@ -7702,10 +7708,8 @@
final Rect prevResolvedBounds = new Rect(resolvedBounds);
resolvedBounds.set(containingBounds);
- // Override from config_fixedOrientationLetterboxAspectRatio or via ADB with
- // set-fixed-orientation-letterbox-aspect-ratio.
final float letterboxAspectRatioOverride =
- mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
+ mLetterboxUiController.getFixedOrientationLetterboxAspectRatio(newParentConfig);
final float desiredAspectRatio =
letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO
? letterboxAspectRatioOverride : computeAspectRatio(parentBounds);
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 3b43e48..c721c24 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -30,7 +30,6 @@
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -1573,11 +1572,7 @@
newTransition.setRemoteTransition(remoteTransition);
}
mService.getTransitionController().collect(r);
- // TODO(b/188669821): Remove when navbar reparenting moves to shell
- if (r.getActivityType() == ACTIVITY_TYPE_HOME && r.getOptions() != null
- && r.getOptions().getTransientLaunch()) {
- mService.getTransitionController().setIsLegacyRecents();
- }
+ final boolean isTransient = r.getOptions() != null && r.getOptions().getTransientLaunch();
try {
mService.deferWindowLayout();
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
@@ -1625,6 +1620,11 @@
// it as an existence change.
mService.getTransitionController().collectExistenceChange(r);
}
+ if (isTransient) {
+ // `r` isn't guaranteed to be the actual relevant activity, so we must wait
+ // until after we launched to identify the relevant activity.
+ mService.getTransitionController().setTransientLaunch(mLastStartActivityRecord);
+ }
if (newTransition != null) {
mService.getTransitionController().requestStartTransition(newTransition,
mTargetTask, remoteTransition);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 5174a38..0ba77d8 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -30,6 +30,7 @@
import android.content.res.CompatibilityInfo;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.LocaleList;
import android.os.RemoteException;
import android.service.voice.IVoiceInteractionSession;
import android.util.IntArray;
@@ -611,6 +612,14 @@
PackageConfigurationUpdater setNightMode(int nightMode);
/**
+ * Sets the app-specific locales for the application referenced by this updater.
+ * This setting is persisted and will overlay on top of the system locales for
+ * the said application.
+ * @return the current {@link PackageConfigurationUpdater} updated with the provided locale.
+ */
+ PackageConfigurationUpdater setLocales(LocaleList locales);
+
+ /**
* Commit changes.
*/
void commit();
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 808d138..3f205c9 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -652,16 +652,25 @@
*/
volatile int mTopProcessState = ActivityManager.PROCESS_STATE_TOP;
+ /** Whether to keep higher priority to launch app while device is sleeping. */
+ private volatile boolean mRetainPowerModeAndTopProcessState;
+
+ /** The timeout to restore power mode if {@link #mRetainPowerModeAndTopProcessState} is set. */
+ private static final long POWER_MODE_UNKNOWN_VISIBILITY_TIMEOUT_MS = 1000;
+
@Retention(RetentionPolicy.SOURCE)
@IntDef({
POWER_MODE_REASON_START_ACTIVITY,
POWER_MODE_REASON_FREEZE_DISPLAY,
+ POWER_MODE_REASON_UNKNOWN_VISIBILITY,
POWER_MODE_REASON_ALL,
})
@interface PowerModeReason {}
static final int POWER_MODE_REASON_START_ACTIVITY = 1 << 0;
static final int POWER_MODE_REASON_FREEZE_DISPLAY = 1 << 1;
+ /** @see UnknownAppVisibilityController */
+ static final int POWER_MODE_REASON_UNKNOWN_VISIBILITY = 1 << 2;
/** This can only be used by {@link #endLaunchPowerMode(int)}.*/
static final int POWER_MODE_REASON_ALL = (1 << 2) - 1;
@@ -946,7 +955,7 @@
setRecentTasks(new RecentTasks(this, mTaskSupervisor));
mVrController = new VrController(mGlobalLock);
mKeyguardController = mTaskSupervisor.getKeyguardController();
- mPackageConfigPersister = new PackageConfigPersister(mTaskSupervisor.mPersisterQueue);
+ mPackageConfigPersister = new PackageConfigPersister(mTaskSupervisor.mPersisterQueue, this);
}
public void onActivityManagerInternalAdded() {
@@ -4247,15 +4256,39 @@
}
void startLaunchPowerMode(@PowerModeReason int reason) {
- if (mPowerManagerInternal == null) return;
- mPowerManagerInternal.setPowerMode(Mode.LAUNCH, true);
+ if (mPowerManagerInternal != null) {
+ mPowerManagerInternal.setPowerMode(Mode.LAUNCH, true);
+ }
mLaunchPowerModeReasons |= reason;
+ if ((reason & POWER_MODE_REASON_UNKNOWN_VISIBILITY) != 0) {
+ if (mRetainPowerModeAndTopProcessState) {
+ mH.removeMessages(H.END_POWER_MODE_UNKNOWN_VISIBILITY_MSG);
+ }
+ mRetainPowerModeAndTopProcessState = true;
+ mH.sendEmptyMessageDelayed(H.END_POWER_MODE_UNKNOWN_VISIBILITY_MSG,
+ POWER_MODE_UNKNOWN_VISIBILITY_TIMEOUT_MS);
+ Slog.d(TAG, "Temporarily retain top process state for launching app");
+ }
}
void endLaunchPowerMode(@PowerModeReason int reason) {
- if (mPowerManagerInternal == null || mLaunchPowerModeReasons == 0) return;
+ if (mLaunchPowerModeReasons == 0) return;
mLaunchPowerModeReasons &= ~reason;
- if (mLaunchPowerModeReasons == 0) {
+
+ if ((mLaunchPowerModeReasons & POWER_MODE_REASON_UNKNOWN_VISIBILITY) != 0) {
+ boolean allResolved = true;
+ for (int i = mRootWindowContainer.getChildCount() - 1; i >= 0; i--) {
+ allResolved &= mRootWindowContainer.getChildAt(i).mUnknownAppVisibilityController
+ .allResolved();
+ }
+ if (allResolved) {
+ mLaunchPowerModeReasons &= ~POWER_MODE_REASON_UNKNOWN_VISIBILITY;
+ mRetainPowerModeAndTopProcessState = false;
+ mH.removeMessages(H.END_POWER_MODE_UNKNOWN_VISIBILITY_MSG);
+ }
+ }
+
+ if (mLaunchPowerModeReasons == 0 && mPowerManagerInternal != null) {
mPowerManagerInternal.setPowerMode(Mode.LAUNCH, false);
}
}
@@ -5117,6 +5150,7 @@
final class H extends Handler {
static final int REPORT_TIME_TRACKER_MSG = 1;
static final int UPDATE_PROCESS_ANIMATING_STATE = 2;
+ static final int END_POWER_MODE_UNKNOWN_VISIBILITY_MSG = 3;
static final int FIRST_ACTIVITY_TASK_MSG = 100;
static final int FIRST_SUPERVISOR_TASK_MSG = 200;
@@ -5140,6 +5174,20 @@
}
}
break;
+ case END_POWER_MODE_UNKNOWN_VISIBILITY_MSG: {
+ synchronized (mGlobalLock) {
+ mRetainPowerModeAndTopProcessState = false;
+ endLaunchPowerMode(POWER_MODE_REASON_UNKNOWN_VISIBILITY);
+ if (mTopApp != null
+ && mTopProcessState == ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
+ // Restore the scheduling group for sleeping.
+ mTopApp.updateProcessInfo(false /* updateServiceConnection */,
+ false /* activityChange */, true /* updateOomAdj */,
+ false /* addPendingTopUid */);
+ }
+ }
+ }
+ break;
}
}
}
@@ -5458,6 +5506,11 @@
@HotPath(caller = HotPath.OOM_ADJUSTMENT)
@Override
public int getTopProcessState() {
+ if (mRetainPowerModeAndTopProcessState) {
+ // There is a launching app while device may be sleeping, force the top state so
+ // the launching process can have top-app scheduling group.
+ return ActivityManager.PROCESS_STATE_TOP;
+ }
return mTopProcessState;
}
@@ -6516,7 +6569,8 @@
final class PackageConfigurationUpdaterImpl implements
ActivityTaskManagerInternal.PackageConfigurationUpdater {
private final int mPid;
- private int mNightMode;
+ private Integer mNightMode;
+ private LocaleList mLocales;
PackageConfigurationUpdaterImpl(int pid) {
mPid = pid;
@@ -6529,6 +6583,13 @@
}
@Override
+ public ActivityTaskManagerInternal.PackageConfigurationUpdater
+ setLocales(LocaleList locales) {
+ mLocales = locales;
+ return this;
+ }
+
+ @Override
public void commit() {
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
@@ -6538,8 +6599,10 @@
Slog.w(TAG, "Override application configuration: cannot find pid " + mPid);
return;
}
- wpc.setOverrideNightMode(mNightMode);
- wpc.updateNightModeForAllActivities(mNightMode);
+ LocaleList localesOverride = LocaleOverlayHelper.combineLocalesIfOverlayExists(
+ mLocales, getGlobalConfiguration().getLocales());
+ wpc.applyAppSpecificConfig(mNightMode, localesOverride);
+ wpc.updateAppSpecificSettingsForAllActivities(mNightMode, localesOverride);
mPackageConfigPersister.updateFromImpl(wpc.mName, wpc.mUserId, this);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -6547,8 +6610,12 @@
}
}
- int getNightMode() {
+ Integer getNightMode() {
return mNightMode;
}
+
+ LocaleList getLocales() {
+ return mLocales;
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 7a42351..1e3b194 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -844,7 +844,7 @@
final AccessibilityController accessibilityController =
mDisplayContent.mWmService.mAccessibilityController;
- if (accessibilityController != null) {
+ if (accessibilityController.hasCallbacks()) {
accessibilityController.onAppWindowTransition(mDisplayContent.getDisplayId(), transit);
}
}
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 6fafc02..5a2cf17 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -28,6 +28,8 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.activityTypeToString;
import static android.app.WindowConfiguration.windowingModeToString;
+import static android.app.WindowConfigurationProto.WINDOWING_MODE;
+import static android.content.ConfigurationProto.WINDOW_CONFIGURATION;
import static com.android.server.wm.ConfigurationContainerProto.FULL_CONFIGURATION;
import static com.android.server.wm.ConfigurationContainerProto.MERGED_OVERRIDE_CONFIGURATION;
@@ -39,6 +41,7 @@
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.LocaleList;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
@@ -512,7 +515,7 @@
return mFullConfiguration.windowConfiguration.getWindowingMode() == WINDOWING_MODE_FREEFORM;
}
- /** Returns the activity type associated with the the configuration container. */
+ /** Returns the activity type associated with the configuration container. */
/*@WindowConfiguration.ActivityType*/
public int getActivityType() {
return mFullConfiguration.windowConfiguration.getActivityType();
@@ -546,20 +549,48 @@
}
/**
+ * Applies app-specific nightMode and {@link LocaleList} on requested configuration.
+ * @return true if any of the requested configuration has been updated.
+ */
+ public boolean applyAppSpecificConfig(Integer nightMode, LocaleList locales) {
+ mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
+ boolean newNightModeSet = (nightMode != null) && setOverrideNightMode(mRequestsTmpConfig,
+ nightMode);
+ boolean newLocalesSet = (locales != null) && setOverrideLocales(mRequestsTmpConfig,
+ locales);
+ if (newNightModeSet || newLocalesSet) {
+ onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
+ }
+ return newNightModeSet || newLocalesSet;
+ }
+
+ /**
* Overrides the night mode applied to this ConfigurationContainer.
* @return true if the nightMode has been changed.
*/
- public boolean setOverrideNightMode(int nightMode) {
+ private boolean setOverrideNightMode(Configuration requestsTmpConfig, int nightMode) {
final int currentUiMode = mRequestedOverrideConfiguration.uiMode;
final int currentNightMode = currentUiMode & Configuration.UI_MODE_NIGHT_MASK;
final int validNightMode = nightMode & Configuration.UI_MODE_NIGHT_MASK;
if (currentNightMode == validNightMode) {
return false;
}
- mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
- mRequestsTmpConfig.uiMode = validNightMode
+ requestsTmpConfig.uiMode = validNightMode
| (currentUiMode & ~Configuration.UI_MODE_NIGHT_MASK);
- onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
+ return true;
+ }
+
+ /**
+ * Overrides the locales applied to this ConfigurationContainer.
+ * @return true if the LocaleList has been changed.
+ */
+ private boolean setOverrideLocales(Configuration requestsTmpConfig,
+ @NonNull LocaleList overrideLocales) {
+ if (mRequestedOverrideConfiguration.getLocales().equals(overrideLocales)) {
+ return false;
+ }
+ requestsTmpConfig.setLocales(overrideLocales);
+ requestsTmpConfig.userSetLocale = true;
return true;
}
@@ -666,22 +697,40 @@
@CallSuper
protected void dumpDebug(ProtoOutputStream proto, long fieldId,
@WindowTraceLogLevel int logLevel) {
- // Critical log level logs only visible elements to mitigate performance overheard
- if (logLevel != WindowTraceLogLevel.ALL && !mHasOverrideConfiguration) {
- return;
+ final long token = proto.start(fieldId);
+
+ if (logLevel == WindowTraceLogLevel.ALL || mHasOverrideConfiguration) {
+ mRequestedOverrideConfiguration.dumpDebug(proto, OVERRIDE_CONFIGURATION,
+ logLevel == WindowTraceLogLevel.CRITICAL);
}
- final long token = proto.start(fieldId);
- mRequestedOverrideConfiguration.dumpDebug(proto, OVERRIDE_CONFIGURATION,
- logLevel == WindowTraceLogLevel.CRITICAL);
+ // Unless trace level is set to `WindowTraceLogLevel.ALL` don't dump anything that isn't
+ // required to mitigate performance overhead
if (logLevel == WindowTraceLogLevel.ALL) {
mFullConfiguration.dumpDebug(proto, FULL_CONFIGURATION, false /* critical */);
mMergedOverrideConfiguration.dumpDebug(proto, MERGED_OVERRIDE_CONFIGURATION,
false /* critical */);
}
+
+ if (logLevel == WindowTraceLogLevel.TRIM) {
+ // Required for Fass to automatically detect pip transitions in Winscope traces
+ dumpDebugWindowingMode(proto);
+ }
+
proto.end(token);
}
+ private void dumpDebugWindowingMode(ProtoOutputStream proto) {
+ final long fullConfigToken = proto.start(FULL_CONFIGURATION);
+ final long windowConfigToken = proto.start(WINDOW_CONFIGURATION);
+
+ int windowingMode = mFullConfiguration.windowConfiguration.getWindowingMode();
+ proto.write(WINDOWING_MODE, windowingMode);
+
+ proto.end(windowConfigToken);
+ proto.end(fullConfigToken);
+ }
+
/**
* Dumps the names of this container children in the input print writer indenting each
* level with the input prefix.
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index dacae17..ea3b725 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -111,6 +111,7 @@
import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_CONTROL_TARGET;
import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_INPUT_TARGET;
import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_TARGET;
+import static com.android.server.wm.DisplayContentProto.INSETS_SOURCE_PROVIDERS;
import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY;
import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA;
@@ -574,6 +575,7 @@
* Specifies the count to determine whether to defer updating the IME target until ready.
*/
private int mDeferUpdateImeTargetCount;
+ private boolean mUpdateImeRequestedWhileDeferred;
private MagnificationSpec mMagnificationSpec;
@@ -1276,7 +1278,7 @@
addWindowToken(token.token, token);
- if (mWmService.mAccessibilityController != null) {
+ if (mWmService.mAccessibilityController.hasCallbacks()) {
final int prevDisplayId = prevDc != null ? prevDc.getDisplayId() : INVALID_DISPLAY;
mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(prevDisplayId,
getDisplayId());
@@ -3225,10 +3227,15 @@
if (mCurrentFocus != null) {
mCurrentFocus.dumpDebug(proto, CURRENT_FOCUS, logLevel);
}
- if (mInsetsStateController != null
- && mInsetsStateController.getImeSourceProvider() != null) {
- mInsetsStateController.getImeSourceProvider().dumpDebug(proto,
- IME_INSETS_SOURCE_PROVIDER, logLevel);
+ if (mInsetsStateController != null) {
+ for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
+ final InsetsSourceProvider provider = mInsetsStateController.peekSourceProvider(
+ type);
+ if (provider != null) {
+ provider.dumpDebug(proto, type == ITYPE_IME ? IME_INSETS_SOURCE_PROVIDER :
+ INSETS_SOURCE_PROVIDERS, logLevel);
+ }
+ }
}
proto.write(IME_POLICY, getImePolicy());
proto.end(token);
@@ -3539,7 +3546,7 @@
// focused one starts firing events.
// TODO(b/151179149) investigate what info accessibility service needs before input can
// dispatch focus to clients.
- if (mWmService.mAccessibilityController != null) {
+ if (mWmService.mAccessibilityController.hasCallbacks()) {
mWmService.mH.sendMessage(PooledLambda.obtainMessage(
this::updateAccessibilityOnWindowFocusChanged,
mWmService.mAccessibilityController));
@@ -3723,6 +3730,7 @@
final WindowState curTarget = mImeLayeringTarget;
if (!canUpdateImeTarget()) {
if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target");
+ mUpdateImeRequestedWhileDeferred = true;
return curTarget;
}
@@ -4977,6 +4985,9 @@
* Increment the deferral count to determine whether to update the IME target.
*/
void deferUpdateImeTarget() {
+ if (mDeferUpdateImeTargetCount == 0) {
+ mUpdateImeRequestedWhileDeferred = false;
+ }
mDeferUpdateImeTargetCount++;
}
@@ -4990,7 +5001,7 @@
}
mDeferUpdateImeTargetCount--;
- if (mDeferUpdateImeTargetCount == 0) {
+ if (mDeferUpdateImeTargetCount == 0 && mUpdateImeRequestedWhileDeferred) {
computeImeTarget(true /* updateImeTarget */);
}
}
@@ -5174,7 +5185,7 @@
}
if (!mLocationInParentWindow.equals(x, y)) {
mLocationInParentWindow.set(x, y);
- if (mWmService.mAccessibilityController != null) {
+ if (mWmService.mAccessibilityController.hasCallbacks()) {
mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(mDisplayId);
}
notifyLocationInParentDisplayChanged();
@@ -5704,7 +5715,7 @@
@Override
void onResize() {
super.onResize();
- if (mWmService.mAccessibilityController != null) {
+ if (mWmService.mAccessibilityController.hasCallbacks()) {
mWmService.mAccessibilityController.onDisplaySizeChanged(this);
}
}
diff --git a/services/core/java/com/android/server/wm/DockedTaskDividerController.java b/services/core/java/com/android/server/wm/DockedTaskDividerController.java
index fb9d064..925a6d8 100644
--- a/services/core/java/com/android/server/wm/DockedTaskDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedTaskDividerController.java
@@ -46,7 +46,7 @@
void setTouchRegion(Rect touchRegion) {
mTouchRegion.set(touchRegion);
// We need to report touchable region changes to accessibility.
- if (mDisplayContent.mWmService.mAccessibilityController != null) {
+ if (mDisplayContent.mWmService.mAccessibilityController.hasCallbacks()) {
mDisplayContent.mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(
mDisplayContent.getDisplayId());
}
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index 5a249a5..c18c94d 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -19,14 +19,18 @@
import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
import static android.view.SurfaceControl.HIDDEN;
+import android.content.Context;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.Process;
+import android.view.GestureDetector;
import android.view.InputChannel;
+import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.InputWindowHandle;
+import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.WindowManager;
@@ -65,6 +69,8 @@
// for overlaping an app window and letterbox surfaces.
private final LetterboxSurface mFullWindowSurface = new LetterboxSurface("fullWindow");
private final LetterboxSurface[] mSurfaces = { mLeft, mTop, mRight, mBottom };
+ // Reachability gestures.
+ private final Runnable mDoubleTapCallback;
/**
* Constructs a Letterbox.
@@ -77,7 +83,8 @@
Supplier<Color> colorSupplier,
Supplier<Boolean> hasWallpaperBackgroundSupplier,
Supplier<Integer> blurRadiusSupplier,
- Supplier<Float> darkScrimAlphaSupplier) {
+ Supplier<Float> darkScrimAlphaSupplier,
+ Runnable doubleTapCallback) {
mSurfaceControlFactory = surfaceControlFactory;
mTransactionFactory = transactionFactory;
mAreCornersRounded = areCornersRounded;
@@ -85,6 +92,7 @@
mHasWallpaperBackgroundSupplier = hasWallpaperBackgroundSupplier;
mBlurRadiusSupplier = blurRadiusSupplier;
mDarkScrimAlphaSupplier = darkScrimAlphaSupplier;
+ mDoubleTapCallback = doubleTapCallback;
}
/**
@@ -231,18 +239,48 @@
return mAreCornersRounded.get() || mHasWallpaperBackgroundSupplier.get();
}
- private static class InputInterceptor {
- final InputChannel mClientChannel;
- final InputWindowHandle mWindowHandle;
- final InputEventReceiver mInputEventReceiver;
- final WindowManagerService mWmService;
- final IBinder mToken;
+ private final class TapEventReceiver extends InputEventReceiver {
+
+ private final GestureDetector mDoubleTapDetector;
+ private final DoubleTapListener mDoubleTapListener;
+
+ TapEventReceiver(InputChannel inputChannel, Context context) {
+ super(inputChannel, UiThread.getHandler().getLooper());
+ mDoubleTapListener = new DoubleTapListener();
+ mDoubleTapDetector = new GestureDetector(context, mDoubleTapListener);
+ }
+
+ @Override
+ public void onInputEvent(InputEvent event) {
+ final MotionEvent motionEvent = (MotionEvent) event;
+ finishInputEvent(event, mDoubleTapDetector.onTouchEvent(motionEvent));
+ }
+ }
+
+ private class DoubleTapListener extends GestureDetector.SimpleOnGestureListener {
+ @Override
+ public boolean onDoubleTapEvent(MotionEvent e) {
+ if (e.getAction() == MotionEvent.ACTION_UP) {
+ mDoubleTapCallback.run();
+ return true;
+ }
+ return false;
+ }
+ }
+
+ private final class InputInterceptor {
+
+ private final InputChannel mClientChannel;
+ private final InputWindowHandle mWindowHandle;
+ private final InputEventReceiver mInputEventReceiver;
+ private final WindowManagerService mWmService;
+ private final IBinder mToken;
InputInterceptor(String namePrefix, WindowState win) {
mWmService = win.mWmService;
final String name = namePrefix + (win.mActivityRecord != null ? win.mActivityRecord : win);
mClientChannel = mWmService.mInputManager.createInputChannel(name);
- mInputEventReceiver = new SimpleInputReceiver(mClientChannel);
+ mInputEventReceiver = new TapEventReceiver(mClientChannel, mWmService.mContext);
mToken = mClientChannel.getToken();
@@ -280,12 +318,6 @@
mInputEventReceiver.dispose();
mClientChannel.dispose();
}
-
- private static class SimpleInputReceiver extends InputEventReceiver {
- SimpleInputReceiver(InputChannel inputChannel) {
- super(inputChannel, UiThread.getHandler().getLooper());
- }
- }
}
private class LetterboxSurface {
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 34b834b..76a098d 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -85,6 +85,26 @@
// side of the screen and 1.0 to the right side.
private float mLetterboxHorizontalPositionMultiplier;
+ // Default horizontal position of a center of the letterboxed app window when reachability is
+ // enabled and an app is fullscreen in landscape device orientatio. 0 corresponds to the left
+ // side of the screen and 1.0 to the right side.
+ // It is used as a starting point for mLetterboxHorizontalMultiplierForReachability.
+ private float mDefaultPositionMultiplierForReachability;
+
+ // Whether reachability repositioning is allowed for letterboxed fullscreen apps in landscape
+ // device orientation.
+ private boolean mIsReachabilityEnabled;
+
+ // Horizontal position of a center of the letterboxed app window. 0 corresponds to
+ // the left side of the screen and 1 to the right side. Keep it global to prevent
+ // "jumps" when switching between letterboxed apps. It's updated to reposition the app
+ // window in response to a double tap gesture (see LetterboxUiController#handleDoubleTap).
+ // Used in LetterboxUiController#getHorizontalPositionMultiplier which is called from
+ // ActivityRecord#updateResolvedBoundsHorizontalPosition.
+ // TODO(b/199426138): Global reachability setting causes a jump when resuming an app from
+ // Overview after changing position in another app.
+ private volatile float mLetterboxHorizontalMultiplierForReachability;
+
LetterboxConfiguration(Context systemUiContext) {
mContext = systemUiContext;
mFixedOrientationLetterboxAspectRatio = mContext.getResources().getFloat(
@@ -98,6 +118,11 @@
R.dimen.config_letterboxBackgroundWallaperDarkScrimAlpha);
mLetterboxHorizontalPositionMultiplier = mContext.getResources().getFloat(
R.dimen.config_letterboxHorizontalPositionMultiplier);
+ mIsReachabilityEnabled = mContext.getResources().getBoolean(
+ R.bool.config_letterboxIsReachabilityEnabled);
+ mDefaultPositionMultiplierForReachability = mContext.getResources().getFloat(
+ R.dimen.config_letterboxDefaultPositionMultiplierForReachability);
+ mLetterboxHorizontalMultiplierForReachability = mDefaultPositionMultiplierForReachability;
}
/**
@@ -317,12 +342,12 @@
* in {@link com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier}
* or via an ADB command. 0 corresponds to the left side of the screen and 1 to the
* right side.
- *
- * <p>This value can be outside of [0, 1] range so clients need to check and default to the
- * central position (0.5).
*/
float getLetterboxHorizontalPositionMultiplier() {
- return mLetterboxHorizontalPositionMultiplier;
+ return (mLetterboxHorizontalPositionMultiplier < 0.0f
+ || mLetterboxHorizontalPositionMultiplier > 1.0f)
+ // Default to central position if invalid value is provided.
+ ? 0.5f : mLetterboxHorizontalPositionMultiplier;
}
/**
@@ -344,4 +369,84 @@
com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier);
}
+ /*
+ * Whether reachability repositioning is allowed for letterboxed fullscreen apps in landscape
+ * device orientation.
+ */
+ boolean getIsReachabilityEnabled() {
+ return mIsReachabilityEnabled;
+ }
+
+ /**
+ * Overrides whether reachability repositioning is allowed for letterboxed fullscreen apps in
+ * landscape device orientation.
+ */
+ void setIsReachabilityEnabled(boolean enabled) {
+ mIsReachabilityEnabled = enabled;
+ }
+
+ /**
+ * Resets whether reachability repositioning is allowed for letterboxed fullscreen apps in
+ * landscape device orientation to {@link R.bool.config_letterboxIsReachabilityEnabled}.
+ */
+ void resetIsReachabilityEnabled() {
+ mIsReachabilityEnabled = mContext.getResources().getBoolean(
+ R.bool.config_letterboxIsReachabilityEnabled);
+ }
+
+ /*
+ * Gets default horizontal position of a center of the letterboxed app window when reachability
+ * is enabled specified in {@link
+ * R.dimen.config_letterboxDefaultPositionMultiplierForReachability} or via an ADB command.
+ * 0 corresponds to the left side of the screen and 1 to the right side. The returned value is
+ * >= 0.0 and <= 1.0.
+ */
+ float getDefaultPositionMultiplierForReachability() {
+ return (mDefaultPositionMultiplierForReachability < 0.0f
+ || mDefaultPositionMultiplierForReachability > 1.0f)
+ // Default to a right position if invalid value is provided.
+ ? 1.0f : mDefaultPositionMultiplierForReachability;
+ }
+
+ /**
+ * Overrides default horizontal position of a center of the letterboxed app window when
+ * reachability is enabled. If given value < 0.0 or > 1.0, then it and a value of {@link
+ * R.dimen.config_letterboxDefaultPositionMultiplierForReachability} are ignored and the right
+ * position (1.0) is used.
+ */
+ void setDefaultPositionMultiplierForReachability(float multiplier) {
+ mDefaultPositionMultiplierForReachability = multiplier;
+ }
+
+ /**
+ * Resets default horizontal position of a center of the letterboxed app window when
+ * reachability is enabled to {@link
+ * R.dimen.config_letterboxDefaultPositionMultiplierForReachability}.
+ */
+ void resetDefaultPositionMultiplierForReachability() {
+ mDefaultPositionMultiplierForReachability = mContext.getResources().getFloat(
+ R.dimen.config_letterboxDefaultPositionMultiplierForReachability);
+ }
+
+ /*
+ * Gets horizontal position of a center of the letterboxed app window when reachability
+ * is enabled specified. 0 corresponds to the left side of the screen and 1 to the right side.
+ *
+ * <p>The position multiplier is changed to a symmetrical value computed as (1 - current
+ * multiplier) after each double tap in the letterbox area.
+ */
+ float getHorizontalMultiplierForReachability() {
+ return mLetterboxHorizontalMultiplierForReachability;
+ }
+
+ /**
+ * Changes horizontal position of a center of the letterboxed app window to the opposite
+ * (1 - current multiplier) when reachability is enabled specified. 0 corresponds to the left
+ * side of the screen and 1 to the right side.
+ */
+ void flipHorizontalMultiplierForReachability() {
+ mLetterboxHorizontalMultiplierForReachability =
+ 1.0f - mLetterboxHorizontalMultiplierForReachability;
+ }
+
}
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index b6b8ad1..0d99bac 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -16,8 +16,12 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static com.android.server.wm.ActivityRecord.computeAspectRatio;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
@@ -28,6 +32,8 @@
import android.annotation.Nullable;
import android.app.ActivityManager.TaskDescription;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
@@ -36,6 +42,7 @@
import android.view.SurfaceControl.Transaction;
import android.view.WindowManager;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType;
@@ -138,7 +145,8 @@
this::getLetterboxBackgroundColor,
this::hasWallpaperBackgroudForLetterbox,
this::getLetterboxWallpaperBlurRadius,
- this::getLetterboxWallpaperDarkScrimAlpha);
+ this::getLetterboxWallpaperDarkScrimAlpha,
+ this::handleDoubleTap);
mLetterbox.attachInput(w);
}
mActivityRecord.getPosition(mTmpPoint);
@@ -158,6 +166,74 @@
}
}
+ float getHorizontalPositionMultiplier(Configuration parentConfiguration) {
+ // Don't check resolved configuration because it may not be updated yet during
+ // configuration change.
+ return isReachabilityEnabled(parentConfiguration)
+ // Using the last global dynamic position to avoid "jumps" when moving
+ // between apps or activities.
+ ? mLetterboxConfiguration.getHorizontalMultiplierForReachability()
+ : mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier();
+ }
+
+ float getFixedOrientationLetterboxAspectRatio(Configuration parentConfiguration) {
+ // Don't check resolved windowing mode because it may not be updated yet during
+ // configuration change.
+ if (!isReachabilityEnabled(parentConfiguration)) {
+ return mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
+ }
+
+ int dividerWindowWidth =
+ getResources().getDimensionPixelSize(R.dimen.docked_stack_divider_thickness);
+ int dividerInsets =
+ getResources().getDimensionPixelSize(R.dimen.docked_stack_divider_insets);
+ int dividerSize = dividerWindowWidth - dividerInsets * 2;
+
+ // Getting the same aspect ratio that apps get in split screen.
+ Rect bounds = new Rect(parentConfiguration.windowConfiguration.getAppBounds());
+ bounds.inset(dividerSize, /* dy */ 0);
+ bounds.right = bounds.centerX();
+
+ return computeAspectRatio(bounds);
+ }
+
+ Resources getResources() {
+ return mActivityRecord.mWmService.mContext.getResources();
+ }
+
+ private void handleDoubleTap() {
+ if (!isReachabilityEnabled() || mActivityRecord.isInTransition()) {
+ return;
+ }
+
+ mLetterboxConfiguration.flipHorizontalMultiplierForReachability();
+
+ // TODO(197549949): Add animation for transition.
+ mActivityRecord.recomputeConfiguration();
+ }
+
+ /**
+ * Whether reachability is enabled for an activity in the curren configuration.
+ *
+ * <p>Conditions that needs to be met:
+ * <ul>
+ * <li>Activity is portrait-only.
+ * <li>Fullscreen window in landscape device orientation.
+ * <li>Reachability is enabled.
+ * </ul>
+ */
+ private boolean isReachabilityEnabled(Configuration parentConfiguration) {
+ return mLetterboxConfiguration.getIsReachabilityEnabled()
+ && parentConfiguration.windowConfiguration.getWindowingMode()
+ == WINDOWING_MODE_FULLSCREEN
+ && parentConfiguration.orientation == ORIENTATION_LANDSCAPE
+ && mActivityRecord.getRequestedConfigurationOrientation() == ORIENTATION_PORTRAIT;
+ }
+
+ private boolean isReachabilityEnabled() {
+ return isReachabilityEnabled(mActivityRecord.getParent().getConfiguration());
+ }
+
@VisibleForTesting
boolean shouldShowLetterboxUi(WindowState mainWindow) {
return isSurfaceReadyAndVisible(mainWindow) && mainWindow.areAppWindowBoundsLetterboxed()
@@ -285,7 +361,7 @@
}
pw.println(prefix + " letterboxReason=" + getLetterboxReasonString(mainWin));
- pw.println(prefix + " letterboxAspectRatio="
+ pw.println(prefix + " activityAspectRatio="
+ mActivityRecord.computeAspectRatio(mActivityRecord.getBounds()));
boolean shouldShowLetterboxUi = shouldShowLetterboxUi(mainWin);
@@ -308,8 +384,13 @@
pw.println(prefix + " letterboxBackgroundWallpaperBlurRadius="
+ getLetterboxWallpaperBlurRadius());
}
+
+ pw.println(prefix + " isReachabilityEnabled=" + isReachabilityEnabled());
pw.println(prefix + " letterboxHorizontalPositionMultiplier="
- + mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier());
+ + getHorizontalPositionMultiplier(mActivityRecord.getParent().getConfiguration()));
+ pw.println(prefix + " fixedOrientationLetterboxAspectRatio="
+ + getFixedOrientationLetterboxAspectRatio(
+ mActivityRecord.getParent().getConfiguration()));
}
/**
diff --git a/services/core/java/com/android/server/wm/LocaleOverlayHelper.java b/services/core/java/com/android/server/wm/LocaleOverlayHelper.java
new file mode 100644
index 0000000..a1a01db
--- /dev/null
+++ b/services/core/java/com/android/server/wm/LocaleOverlayHelper.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.os.LocaleList;
+
+import java.util.Locale;
+
+/**
+ * Static utilities to overlay locales on top of another localeList.
+ *
+ * <p>This is used to overlay application-specific locales in
+ * {@link com.android.server.wm.ActivityTaskManagerInternal.PackageConfigurationUpdater} on top of
+ * system locales.
+ */
+final class LocaleOverlayHelper {
+
+ /**
+ * Combines the overlay locales and base locales.
+ * @return the combined {@link LocaleList} if the overlay locales is not empty/null else
+ * returns the empty/null LocaleList.
+ */
+ static LocaleList combineLocalesIfOverlayExists(LocaleList overlayLocales,
+ LocaleList baseLocales) {
+ if (overlayLocales == null || overlayLocales.isEmpty()) {
+ return overlayLocales;
+ }
+ return combineLocales(overlayLocales, baseLocales);
+ }
+
+ /**
+ * Creates a combined {@link LocaleList} by placing overlay locales before base locales and
+ * dropping duplicates from the base locales.
+ */
+ private static LocaleList combineLocales(LocaleList overlayLocales, LocaleList baseLocales) {
+ Locale[] combinedLocales = new Locale[overlayLocales.size() + baseLocales.size()];
+ for (int i = 0; i < overlayLocales.size(); i++) {
+ combinedLocales[i] = overlayLocales.get(i);
+ }
+ for (int i = 0; i < baseLocales.size(); i++) {
+ combinedLocales[i + overlayLocales.size()] = baseLocales.get(i);
+ }
+ // Constructor of {@link LocaleList} removes duplicates
+ return new LocaleList(combinedLocales);
+ }
+
+
+}
diff --git a/services/core/java/com/android/server/wm/PackageConfigPersister.java b/services/core/java/com/android/server/wm/PackageConfigPersister.java
index 1552a96..505c4be 100644
--- a/services/core/java/com/android/server/wm/PackageConfigPersister.java
+++ b/services/core/java/com/android/server/wm/PackageConfigPersister.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.os.Environment;
+import android.os.LocaleList;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.SparseArray;
@@ -54,12 +55,14 @@
private static final String TAG_CONFIG = "config";
private static final String ATTR_PACKAGE_NAME = "package_name";
private static final String ATTR_NIGHT_MODE = "night_mode";
+ private static final String ATTR_LOCALES = "locale_list";
private static final String PACKAGE_DIRNAME = "package_configs";
private static final String SUFFIX_FILE_NAME = "_config.xml";
private final PersisterQueue mPersisterQueue;
private final Object mLock = new Object();
+ private final ActivityTaskManagerService mAtm;
@GuardedBy("mLock")
private final SparseArray<HashMap<String, PackageConfigRecord>> mPendingWrite =
@@ -72,8 +75,9 @@
return new File(Environment.getDataSystemCeDirectory(userId), PACKAGE_DIRNAME);
}
- PackageConfigPersister(PersisterQueue queue) {
+ PackageConfigPersister(PersisterQueue queue, ActivityTaskManagerService atm) {
mPersisterQueue = queue;
+ mAtm = atm;
}
@GuardedBy("mLock")
@@ -100,7 +104,8 @@
final TypedXmlPullParser in = Xml.resolvePullParser(is);
int event;
String packageName = null;
- int nightMode = MODE_NIGHT_AUTO;
+ Integer nightMode = null;
+ LocaleList locales = null;
while (((event = in.next()) != XmlPullParser.END_DOCUMENT)
&& event != XmlPullParser.END_TAG) {
final String name = in.getName();
@@ -120,6 +125,9 @@
case ATTR_NIGHT_MODE:
nightMode = Integer.parseInt(attrValue);
break;
+ case ATTR_LOCALES:
+ locales = LocaleList.forLanguageTags(attrValue);
+ break;
}
}
}
@@ -130,6 +138,7 @@
final PackageConfigRecord initRecord =
findRecordOrCreate(mModified, packageName, userId);
initRecord.mNightMode = nightMode;
+ initRecord.mLocales = locales;
if (DEBUG) {
Slog.d(TAG, "loadPackages: load one package " + initRecord);
}
@@ -155,7 +164,9 @@
"updateConfigIfNeeded record " + container + " find? " + modifiedRecord);
}
if (modifiedRecord != null) {
- container.setOverrideNightMode(modifiedRecord.mNightMode);
+ container.applyAppSpecificConfig(modifiedRecord.mNightMode,
+ LocaleOverlayHelper.combineLocalesIfOverlayExists(
+ modifiedRecord.mLocales, mAtm.getGlobalConfiguration().getLocales()));
}
}
}
@@ -165,10 +176,16 @@
ActivityTaskManagerService.PackageConfigurationUpdaterImpl impl) {
synchronized (mLock) {
PackageConfigRecord record = findRecordOrCreate(mModified, packageName, userId);
- record.mNightMode = impl.getNightMode();
-
- if (record.isResetNightMode()) {
- removePackage(record.mName, record.mUserId);
+ if (impl.getNightMode() != null) {
+ record.mNightMode = impl.getNightMode();
+ }
+ if (impl.getLocales() != null) {
+ record.mLocales = impl.getLocales();
+ }
+ if ((record.mNightMode == null || record.isResetNightMode())
+ && (record.mLocales == null || record.mLocales.isEmpty())) {
+ // if all values default to system settings, we can remove the package.
+ removePackage(packageName, userId);
} else {
final PackageConfigRecord pendingRecord =
findRecord(mPendingWrite, record.mName, record.mUserId);
@@ -179,10 +196,11 @@
} else {
writeRecord = pendingRecord;
}
- if (writeRecord.mNightMode == record.mNightMode) {
+
+ if (!updateNightMode(record, writeRecord) && !updateLocales(record, writeRecord)) {
return;
}
- writeRecord.mNightMode = record.mNightMode;
+
if (DEBUG) {
Slog.d(TAG, "PackageConfigUpdater save config " + writeRecord);
}
@@ -191,6 +209,22 @@
}
}
+ private boolean updateNightMode(PackageConfigRecord record, PackageConfigRecord writeRecord) {
+ if (record.mNightMode == null || record.mNightMode.equals(writeRecord.mNightMode)) {
+ return false;
+ }
+ writeRecord.mNightMode = record.mNightMode;
+ return true;
+ }
+
+ private boolean updateLocales(PackageConfigRecord record, PackageConfigRecord writeRecord) {
+ if (record.mLocales == null || record.mLocales.equals(writeRecord.mLocales)) {
+ return false;
+ }
+ writeRecord.mLocales = record.mLocales;
+ return true;
+ }
+
@GuardedBy("mLock")
void removeUser(int userId) {
synchronized (mLock) {
@@ -210,7 +244,7 @@
@GuardedBy("mLock")
void onPackageUninstall(String packageName) {
synchronized (mLock) {
- for (int i = mModified.size() - 1; i > 0; i--) {
+ for (int i = mModified.size() - 1; i >= 0; i--) {
final int userId = mModified.keyAt(i);
removePackage(packageName, userId);
}
@@ -242,7 +276,8 @@
static class PackageConfigRecord {
final String mName;
final int mUserId;
- int mNightMode;
+ Integer mNightMode;
+ LocaleList mLocales;
PackageConfigRecord(String name, int userId) {
mName = name;
@@ -256,7 +291,7 @@
@Override
public String toString() {
return "PackageConfigRecord package name: " + mName + " userId " + mUserId
- + " nightMode " + mNightMode;
+ + " nightMode " + mNightMode + " locales " + mLocales;
}
}
@@ -369,7 +404,13 @@
}
xmlSerializer.startTag(null, TAG_CONFIG);
xmlSerializer.attribute(null, ATTR_PACKAGE_NAME, mRecord.mName);
- xmlSerializer.attributeInt(null, ATTR_NIGHT_MODE, mRecord.mNightMode);
+ if (mRecord.mNightMode != null) {
+ xmlSerializer.attributeInt(null, ATTR_NIGHT_MODE, mRecord.mNightMode);
+ }
+ if (mRecord.mLocales != null) {
+ xmlSerializer.attribute(null, ATTR_LOCALES, mRecord.mLocales
+ .toLanguageTags());
+ }
xmlSerializer.endTag(null, TAG_CONFIG);
xmlSerializer.endDocument();
xmlSerializer.flush();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 6c2322b..c48dba4 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -3545,14 +3545,7 @@
}
void startPowerModeLaunchIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
- final boolean sendPowerModeLaunch;
-
- if (forceSend) {
- sendPowerModeLaunch = true;
- } else if (targetActivity == null || targetActivity.app == null) {
- // Set power mode if we don't know what we're launching yet.
- sendPowerModeLaunch = true;
- } else {
+ if (!forceSend && targetActivity != null && targetActivity.app != null) {
// Set power mode when the activity's process is different than the current top resumed
// activity on all display areas, or if there are no resumed activities in the system.
boolean[] noResumedActivities = {true};
@@ -3568,13 +3561,28 @@
!resumedActivityProcess.equals(targetActivity.app);
}
});
- sendPowerModeLaunch = noResumedActivities[0] || allFocusedProcessesDiffer[0];
+ if (!noResumedActivities[0] && !allFocusedProcessesDiffer[0]) {
+ // All focused activities are resumed and the process of the target activity is
+ // the same as them, e.g. delivering new intent to the current top.
+ return;
+ }
}
- if (sendPowerModeLaunch) {
- mService.startLaunchPowerMode(
- ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY);
+ int reason = ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY;
+ // If the activity is launching while keyguard is locked (including occluded), the activity
+ // may be visible until its first relayout is done (e.g. apply show-when-lock flag). To
+ // avoid power mode from being cleared before that, add a special reason to consider whether
+ // the unknown visibility is resolved. The case from SystemUI is excluded because it should
+ // rely on keyguard-going-away.
+ if (mService.mKeyguardController.isKeyguardLocked() && targetActivity != null
+ && !targetActivity.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_SYSTEMUI)) {
+ final ActivityOptions opts = targetActivity.getOptions();
+ if (opts == null || opts.getSourceInfo() == null
+ || opts.getSourceInfo().type != ActivityOptions.SourceInfo.TYPE_LOCKSCREEN) {
+ reason |= ActivityTaskManagerService.POWER_MODE_REASON_UNKNOWN_VISIBILITY;
+ }
}
+ mService.startLaunchPowerMode(reason);
}
// TODO(b/191434136): handle this properly when we add multi-window support on secondary
diff --git a/services/core/java/com/android/server/wm/ShellRoot.java b/services/core/java/com/android/server/wm/ShellRoot.java
index be6a5d2..6ed59e9 100644
--- a/services/core/java/com/android/server/wm/ShellRoot.java
+++ b/services/core/java/com/android/server/wm/ShellRoot.java
@@ -197,7 +197,7 @@
mAccessibilityWindow = null;
}
}
- if (mDisplayContent.mWmService.mAccessibilityController != null) {
+ if (mDisplayContent.mWmService.mAccessibilityController.hasCallbacks()) {
mDisplayContent.mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(
mDisplayContent.getDisplayId());
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 7bdb1a0..e6e51b8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -165,6 +165,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
@@ -570,7 +571,9 @@
mRoot = r;
// Only end search if we are ignore relinquishing identity or we are not relinquishing.
- return ignoreRelinquishIdentity || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
+ return ignoreRelinquishIdentity
+ || mNeverRelinquishIdentity
+ || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
}
}
@@ -1009,7 +1012,14 @@
private void setIntent(Intent _intent, ActivityInfo info) {
if (!isLeafTask()) return;
- mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
+ if (info.applicationInfo.uid == Process.SYSTEM_UID
+ || info.applicationInfo.isSystemApp()) {
+ // Only allow the apps that pre-installed on the system image to apply
+ // relinquishTaskIdentity
+ mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
+ } else {
+ mNeverRelinquishIdentity = true;
+ }
affinity = info.taskAffinity;
if (intent == null) {
// If this task already has an intent associated with it, don't set the root
@@ -1990,14 +2000,7 @@
taskDisplayArea.onRootTaskWindowingModeChanged(this);
}
- if (mDisplayContent == null) {
- return;
- }
-
- // Use override windowing mode to prevent extra bounds changes if inheriting the mode.
- final int overrideWindowingMode = getRequestedOverrideWindowingMode();
- if (overrideWindowingMode != WINDOWING_MODE_PINNED
- && !getRequestedOverrideBounds().isEmpty()) {
+ if (!isOrganized() && !getRequestedOverrideBounds().isEmpty() && mDisplayContent != null) {
// If the parent (display) has rotated, rotate our bounds to best-fit where their
// bounds were on the pre-rotated display.
final int newRotation = getWindowConfiguration().getRotation();
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index ca1d83e..abe95fa 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -447,7 +447,7 @@
return this;
}
- TaskFragment parentTaskFragment = getParent().asTaskFragment();
+ TaskFragment parentTaskFragment = getParent() != null ? getParent().asTaskFragment() : null;
return parentTaskFragment != null ? parentTaskFragment.getOrganizedTaskFragment() : null;
}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 6b93364..1a46d0f 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -148,6 +148,9 @@
*/
private final ArraySet<WindowToken> mVisibleAtTransitionEndTokens = new ArraySet<>();
+ /** Set of transient activities (lifecycle initially tied to this transition). */
+ private ArraySet<ActivityRecord> mTransientLaunches = null;
+
/** Custom activity-level animation options and callbacks. */
private TransitionInfo.AnimationOptions mOverrideOptions;
private IRemoteCallback mClientAnimationStartCallback = null;
@@ -174,6 +177,20 @@
mFlags |= flag;
}
+ /** Records an activity as transient-launch. This activity must be already collected. */
+ void setTransientLaunch(@NonNull ActivityRecord activity) {
+ if (mTransientLaunches == null) {
+ mTransientLaunches = new ArraySet<>();
+ }
+ mTransientLaunches.add(activity);
+ ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Transition %d: Set %s as "
+ + "transient-launch", mSyncId, activity);
+ }
+
+ boolean isTransientLaunch(@NonNull ActivityRecord activity) {
+ return mTransientLaunches != null && mTransientLaunches.contains(activity);
+ }
+
@VisibleForTesting
int getSyncId() {
return mSyncId;
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 69e6a54..c1d0f80 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
@@ -185,6 +186,20 @@
return false;
}
+ /**
+ * @return {@code true} if {@param ar} is part of a transient-launch activity in an active
+ * transition.
+ */
+ boolean isTransientLaunch(@NonNull ActivityRecord ar) {
+ if (mCollectingTransition != null && mCollectingTransition.isTransientLaunch(ar)) {
+ return true;
+ }
+ for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
+ if (mPlayingTransitions.get(i).isTransientLaunch(ar)) return true;
+ }
+ return false;
+ }
+
@WindowManager.TransitionType
int getCollectingTransitionType() {
return mCollectingTransition != null ? mCollectingTransition.mType : TRANSIT_NONE;
@@ -331,13 +346,18 @@
}
/**
- * Explicitly mark the collectingTransition as being part of recents gesture. Used for legacy
- * behaviors.
- * TODO(b/188669821): Remove once legacy recents behavior is moved to shell.
+ * Record that the launch of {@param activity} is transient (meaning its lifecycle is currently
+ * tied to the transition).
*/
- void setIsLegacyRecents() {
+ void setTransientLaunch(@NonNull ActivityRecord activity) {
if (mCollectingTransition == null) return;
- mCollectingTransition.addFlag(TRANSIT_FLAG_IS_RECENTS);
+ mCollectingTransition.setTransientLaunch(activity);
+
+ // TODO(b/188669821): Remove once legacy recents behavior is moved to shell.
+ // Also interpret HOME transient launch as recents
+ if (activity.getActivityType() == ACTIVITY_TYPE_HOME) {
+ mCollectingTransition.addFlag(TRANSIT_FLAG_IS_RECENTS);
+ }
}
void legacyDetachNavigationBarFromApp(@NonNull IBinder token) {
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index eb32486..4a43f4f 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -164,7 +164,7 @@
final DisplayContent dc = root.getDisplayContent(displayId);
dc.checkAppWindowsReadyToShow();
- if (accessibilityController != null) {
+ if (accessibilityController.hasCallbacks()) {
accessibilityController.drawMagnifiedRegionBorderIfNeeded(displayId,
mTransaction);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9458511..5ef7428 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -46,6 +46,8 @@
import static android.provider.Settings.Global.DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_270;
import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
@@ -153,6 +155,7 @@
import android.app.IAssistDataReceiver;
import android.app.WindowConfiguration;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -162,6 +165,7 @@
import android.content.pm.PackageManagerInternal;
import android.content.pm.TestUtilityService;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.Bitmap;
@@ -323,11 +327,13 @@
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
+import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -630,7 +636,7 @@
/** List of window currently causing non-system overlay windows to be hidden. */
private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();
- AccessibilityController mAccessibilityController;
+ final AccessibilityController mAccessibilityController;
private RecentsAnimationController mRecentsAnimationController;
Watermark mWatermark;
@@ -1376,6 +1382,7 @@
mStartingSurfaceController = new StartingSurfaceController(this);
mBlurController = new BlurController(mContext, mPowerManager);
+ mAccessibilityController = new AccessibilityController(this);
}
DisplayAreaPolicy.Provider getDisplayAreaPolicyProvider() {
@@ -2155,7 +2162,7 @@
mWindowPlacerLocked.performSurfacePlacement();
// We need to report touchable region changes to accessibility.
- if (mAccessibilityController != null) {
+ if (mAccessibilityController.hasCallbacks()) {
mAccessibilityController.onSomeWindowResizedOrMovedWithCallingUid(
uid, w.getDisplayContent().getDisplayId());
}
@@ -2168,7 +2175,7 @@
public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
synchronized (mGlobalLock) {
- if (mAccessibilityController != null) {
+ if (mAccessibilityController.hasCallbacks()) {
WindowState window = mWindowMap.get(token);
if (window != null) {
mAccessibilityController.onRectangleOnScreenRequested(
@@ -2258,7 +2265,7 @@
win.mActivityRecord.checkKeyguardFlagsChanged();
}
if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0)
- && (mAccessibilityController != null)) {
+ && (mAccessibilityController.hasCallbacks())) {
// No move or resize, but the controller checks for title changes as well
mAccessibilityController.onSomeWindowResizedOrMovedWithCallingUid(
uid, win.getDisplayContent().getDisplayId());
@@ -2580,7 +2587,7 @@
win.mDestroying = true;
win.destroySurface(false, stopped);
}
- if (mAccessibilityController != null) {
+ if (mAccessibilityController.hasCallbacks()) {
mAccessibilityController.onWindowTransition(win, transit);
}
@@ -6370,7 +6377,7 @@
mInputManagerCallback.dump(pw, " ");
mTaskSnapshotController.dump(pw, " ");
- if (mAccessibilityController != null) {
+ if (mAccessibilityController.hasCallbacks()) {
mAccessibilityController.dump(pw, " ");
}
@@ -7390,7 +7397,7 @@
@Override
public void setMagnificationSpec(int displayId, MagnificationSpec spec) {
synchronized (mGlobalLock) {
- if (mAccessibilityController != null) {
+ if (mAccessibilityController.hasCallbacks()) {
mAccessibilityController.setMagnificationSpec(displayId, spec);
} else {
throw new IllegalStateException("Magnification callbacks not set!");
@@ -7401,7 +7408,7 @@
@Override
public void setForceShowMagnifiableBounds(int displayId, boolean show) {
synchronized (mGlobalLock) {
- if (mAccessibilityController != null) {
+ if (mAccessibilityController.hasCallbacks()) {
mAccessibilityController.setForceShowMagnifiableBounds(displayId, show);
} else {
throw new IllegalStateException("Magnification callbacks not set!");
@@ -7412,7 +7419,7 @@
@Override
public void getMagnificationRegion(int displayId, @NonNull Region magnificationRegion) {
synchronized (mGlobalLock) {
- if (mAccessibilityController != null) {
+ if (mAccessibilityController.hasCallbacks()) {
mAccessibilityController.getMagnificationRegion(displayId, magnificationRegion);
} else {
throw new IllegalStateException("Magnification callbacks not set!");
@@ -7428,7 +7435,7 @@
return null;
}
MagnificationSpec spec = null;
- if (mAccessibilityController != null) {
+ if (mAccessibilityController.hasCallbacks()) {
spec = mAccessibilityController.getMagnificationSpecForWindow(windowState);
}
if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
@@ -7447,16 +7454,7 @@
public boolean setMagnificationCallbacks(int displayId,
@Nullable MagnificationCallbacks callbacks) {
synchronized (mGlobalLock) {
- if (mAccessibilityController == null) {
- mAccessibilityController = new AccessibilityController(
- WindowManagerService.this);
- }
- boolean result = mAccessibilityController.setMagnificationCallbacks(
- displayId, callbacks);
- if (!mAccessibilityController.hasCallbacks()) {
- mAccessibilityController = null;
- }
- return result;
+ return mAccessibilityController.setMagnificationCallbacks(displayId, callbacks);
}
}
@@ -7464,15 +7462,7 @@
public void setWindowsForAccessibilityCallback(int displayId,
WindowsForAccessibilityCallback callback) {
synchronized (mGlobalLock) {
- if (mAccessibilityController == null) {
- mAccessibilityController = new AccessibilityController(
- WindowManagerService.this);
- }
- mAccessibilityController.setWindowsForAccessibilityCallback(
- displayId, callback);
- if (!mAccessibilityController.hasCallbacks()) {
- mAccessibilityController = null;
- }
+ mAccessibilityController.setWindowsForAccessibilityCallback(displayId, callback);
}
}
@@ -7645,13 +7635,7 @@
@Override
public void computeWindowsForAccessibility(int displayId) {
- final AccessibilityController accessibilityController;
- synchronized (mGlobalLock) {
- accessibilityController = mAccessibilityController;
- }
- if (accessibilityController != null) {
- accessibilityController.performComputeChangedWindowsNot(displayId, true);
- }
+ mAccessibilityController.performComputeChangedWindowsNot(displayId, true);
}
@Override
@@ -7725,7 +7709,7 @@
final WindowState currentFocus = displayContent.mCurrentFocus;
if (currentFocus != null && currentFocus.mSession.mUid == uid
&& currentFocus.mSession.mPid == pid) {
- return true;
+ return currentFocus.canBeImeTarget();
}
}
return false;
@@ -8454,6 +8438,65 @@
}
}
+ @Override
+ public List<DisplayInfo> getPossibleDisplayInfo(int displayId, String packageName) {
+ final int callingUid = Binder.getCallingUid();
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ if (packageName == null || !isRecentsComponent(packageName, callingUid)) {
+ Slog.e(TAG, "Unable to verify uid for package " + packageName
+ + " for getPossibleMaximumWindowMetrics");
+ return new ArrayList<>();
+ }
+ // TODO(181127261) DisplayInfo should be pushed from DisplayManager.
+ final DisplayContent dc = mRoot.getDisplayContent(displayId);
+ if (dc == null) {
+ Slog.e(TAG, "Invalid displayId " + displayId
+ + " for getPossibleMaximumWindowMetrics");
+ return new ArrayList<>();
+ }
+
+ // TODO(181127261) DisplayManager should provide a DisplayInfo for each rotation
+ DisplayInfo currentDisplayInfo = dc.getDisplayInfo();
+ Set<DisplayInfo> displayInfoSet = new HashSet<>();
+ for (int rotation = ROTATION_0; rotation <= ROTATION_270; rotation++) {
+ currentDisplayInfo.rotation = rotation;
+ // TODO(181127261) Retrieve the device state from display stack.
+ displayInfoSet.add(new DisplayInfo(currentDisplayInfo));
+ }
+ return new ArrayList<DisplayInfo>(displayInfoSet);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ /**
+ * Returns {@code true} when the calling package is the recents component.
+ */
+ boolean isRecentsComponent(@NonNull String callingPackageName, int callingUid) {
+ String recentsPackage;
+ try {
+ String recentsComponent = mContext.getResources().getString(
+ R.string.config_recentsComponentName);
+ if (recentsComponent == null) {
+ return false;
+ }
+ recentsPackage = ComponentName.unflattenFromString(recentsComponent).getPackageName();
+ } catch (Resources.NotFoundException e) {
+ Slog.e(TAG, "Unable to verify if recents component", e);
+ return false;
+ }
+ try {
+ return callingUid == mContext.getPackageManager().getPackageUid(callingPackageName, 0)
+ && callingPackageName.equals(recentsPackage);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.e(TAG, "Unable to verify if recents component", e);
+ return false;
+ }
+ }
+
void grantEmbeddedWindowFocus(Session session, IBinder inputToken, boolean grantFocus) {
synchronized (mGlobalLock) {
final EmbeddedWindowController.EmbeddedWindow embeddedWindow =
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 1d1cb70..47d7f03 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -745,7 +745,7 @@
return 0;
}
- private int runSeLetterboxHorizontalPositionMultiplier(PrintWriter pw) throws RemoteException {
+ private int runSetLetterboxHorizontalPositionMultiplier(PrintWriter pw) throws RemoteException {
final float multiplier;
try {
String arg = getNextArgRequired();
@@ -764,6 +764,49 @@
return 0;
}
+ private int runSetLetterboxIsReachabilityEnabled(PrintWriter pw) throws RemoteException {
+ String arg = getNextArg();
+ final boolean enabled;
+ switch (arg) {
+ case "true":
+ case "1":
+ enabled = true;
+ break;
+ case "false":
+ case "0":
+ enabled = false;
+ break;
+ default:
+ getErrPrintWriter().println("Error: expected true, 1, false, 0, but got " + arg);
+ return -1;
+ }
+
+ synchronized (mInternal.mGlobalLock) {
+ mLetterboxConfiguration.setIsReachabilityEnabled(enabled);
+ }
+ return 0;
+ }
+
+ private int runSetLetterboxDefaultPositionMultiplierForReachability(PrintWriter pw)
+ throws RemoteException {
+ final float multiplier;
+ try {
+ String arg = getNextArgRequired();
+ multiplier = Float.parseFloat(arg);
+ } catch (NumberFormatException e) {
+ getErrPrintWriter().println("Error: bad multiplier format " + e);
+ return -1;
+ } catch (IllegalArgumentException e) {
+ getErrPrintWriter().println(
+ "Error: multiplier should be provided as an argument " + e);
+ return -1;
+ }
+ synchronized (mInternal.mGlobalLock) {
+ mLetterboxConfiguration.setDefaultPositionMultiplierForReachability(multiplier);
+ }
+ return 0;
+ }
+
private int runSetLetterboxStyle(PrintWriter pw) throws RemoteException {
if (peekNextArg() == null) {
getErrPrintWriter().println("Error: No arguments provided.");
@@ -793,7 +836,13 @@
runSetLetterboxBackgroundWallpaperDarkScrimAlpha(pw);
break;
case "--horizontalPositionMultiplier":
- runSeLetterboxHorizontalPositionMultiplier(pw);
+ runSetLetterboxHorizontalPositionMultiplier(pw);
+ break;
+ case "--isReachabilityEnabled":
+ runSetLetterboxIsReachabilityEnabled(pw);
+ break;
+ case "--defaultPositionMultiplierReachability":
+ runSetLetterboxDefaultPositionMultiplierForReachability(pw);
break;
default:
getErrPrintWriter().println(
@@ -833,6 +882,12 @@
case "horizontalPositionMultiplier":
mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier();
break;
+ case "isReachabilityEnabled":
+ mLetterboxConfiguration.getIsReachabilityEnabled();
+ break;
+ case "defaultPositionMultiplierForReachability":
+ mLetterboxConfiguration.getDefaultPositionMultiplierForReachability();
+ break;
default:
getErrPrintWriter().println(
"Error: Unrecognized letterbox style option: " + arg);
@@ -926,6 +981,8 @@
mLetterboxConfiguration.resetLetterboxBackgroundWallpaperBlurRadius();
mLetterboxConfiguration.resetLetterboxBackgroundWallpaperDarkScrimAlpha();
mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier();
+ mLetterboxConfiguration.resetIsReachabilityEnabled();
+ mLetterboxConfiguration.resetDefaultPositionMultiplierForReachability();
}
}
@@ -937,6 +994,10 @@
+ mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier());
pw.println("Aspect ratio: "
+ mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio());
+ pw.println("Is reachability enabled: "
+ + mLetterboxConfiguration.getIsReachabilityEnabled());
+ pw.println("Default position multiplier for reachability: "
+ + mLetterboxConfiguration.getDefaultPositionMultiplierForReachability());
pw.println("Background type: "
+ LetterboxConfiguration.letterboxBackgroundTypeToString(
@@ -1071,9 +1132,18 @@
pw.println(" Horizontal position of app window center. If multiplier < 0 or > 1,");
pw.println(" both it and R.dimen.config_letterboxHorizontalPositionMultiplier");
pw.println(" are ignored and central position (0.5) is used.");
+ pw.println(" --isReachabilityEnabled [true|1|false|0]");
+ pw.println(" Whether reachability repositioning is allowed for letterboxed");
+ pw.println(" fullscreen apps in landscape device orientation.");
+ pw.println(" --defaultPositionMultiplierReachability multiplier");
+ pw.println(" Default horizontal position of app window center when reachability is");
+ pw.println(" enabled. If multiplier < 0.0 or > 1, both it and ");
+ pw.println(" R.dimen.config_letterboxDefaultPositionMultiplierForReachability");
+ pw.println(" are ignored and right position (1.0) is used.");
pw.println(" reset-letterbox-style [aspectRatio|cornerRadius|backgroundType");
pw.println(" |backgroundColor|wallpaperBlurRadius|wallpaperDarkScrimAlpha");
- pw.println(" |horizontalPositionMultiplier]");
+ pw.println(" |horizontalPositionMultiplier|isReachabilityEnabled");
+ pw.println(" |defaultPositionMultiplierForReachability]");
pw.println(" Resets overrides to default values for specified properties separated");
pw.println(" by space, e.g. 'reset-letterbox-style aspectRatio cornerRadius'.");
pw.println(" If no arguments provided, all values will be reset.");
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 8bcd62d..834b6e6 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -733,18 +733,18 @@
tf1.setAdjacentTaskFragment(tf2);
final Bundle bundle = hop.getLaunchOptions();
- final WindowContainerTransaction.TaskFragmentAdjacentOptions adjacentOptions =
- bundle != null ? new WindowContainerTransaction.TaskFragmentAdjacentOptions(
+ final WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams =
+ bundle != null ? new WindowContainerTransaction.TaskFragmentAdjacentParams(
bundle) : null;
- if (adjacentOptions == null) {
+ if (adjacentParams == null) {
break;
}
tf1.setDelayLastActivityRemoval(
- adjacentOptions.isDelayPrimaryLastActivityRemoval());
+ adjacentParams.shouldDelayPrimaryLastActivityRemoval());
if (tf2 != null) {
tf2.setDelayLastActivityRemoval(
- adjacentOptions.isDelaySecondaryLastActivityRemoval());
+ adjacentParams.shouldDelaySecondaryLastActivityRemoval());
}
break;
}
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 056e17d9..5b73de7 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -57,6 +57,7 @@
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
+import android.os.LocaleList;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
@@ -817,10 +818,13 @@
return false;
}
- void updateNightModeForAllActivities(int nightMode) {
+ // TODO(b/199277065): Re-assess how app-specific locales are applied based on UXR
+ // TODO(b/199277729): Consider whether we need to add special casing for edge cases like
+ // activity-embeddings etc.
+ void updateAppSpecificSettingsForAllActivities(Integer nightMode, LocaleList localesOverride) {
for (int i = mActivities.size() - 1; i >= 0; --i) {
final ActivityRecord r = mActivities.get(i);
- if (r.setOverrideNightMode(nightMode) && r.mVisibleRequested) {
+ if (r.applyAppSpecificConfig(nightMode, localesOverride) && r.mVisibleRequested) {
r.ensureActivityConfiguration(0 /* globalChanges */, true /* preserveWindow */);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 22db297..6c93f81 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1980,7 +1980,7 @@
final ActivityRecord atoken = mActivityRecord;
return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
&& isVisibleByPolicy() && !isParentWindowHidden()
- && (atoken == null || atoken.mVisibleRequested)
+ && (atoken == null || atoken.isVisible())
&& !mAnimatingExit && !mDestroying;
}
@@ -2212,7 +2212,7 @@
mWmService.mAccessibilityController;
final int winTransit = TRANSIT_EXIT;
mWinAnimator.applyAnimationLocked(winTransit, false /* isEntrance */);
- if (accessibilityController != null) {
+ if (accessibilityController.hasCallbacks()) {
accessibilityController.onWindowTransition(this, winTransit);
}
}
@@ -2233,7 +2233,7 @@
}
if (isVisibleNow() && animateExit) {
mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
- if (mWmService.mAccessibilityController != null) {
+ if (mWmService.mAccessibilityController.hasCallbacks()) {
mWmService.mAccessibilityController.onWindowTransition(this, TRANSIT_EXIT);
}
changed = true;
@@ -2283,7 +2283,7 @@
startMoveAnimation(left, top);
}
- if (mWmService.mAccessibilityController != null) {
+ if (mWmService.mAccessibilityController.hasCallbacks()) {
mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(getDisplayId());
}
updateLocationInParentDisplayIfNeeded();
@@ -2569,7 +2569,7 @@
setDisplayLayoutNeeded();
mWmService.requestTraversal();
}
- if (mWmService.mAccessibilityController != null) {
+ if (mWmService.mAccessibilityController.hasCallbacks()) {
mWmService.mAccessibilityController.onWindowTransition(this, transit);
}
}
@@ -2706,6 +2706,13 @@
}
}
+ // Don't allow transient-launch activities to take IME.
+ if (rootTask != null && mActivityRecord != null
+ && mWmService.mAtmService.getTransitionController().isTransientLaunch(
+ mActivityRecord)) {
+ return false;
+ }
+
if (DEBUG_INPUT_METHOD) {
Slog.i(TAG_WM, "isVisibleOrAdding " + this + ": " + isVisibleOrAdding());
if (!isVisibleOrAdding()) {
@@ -3589,7 +3596,7 @@
if (mAttrs.type >= FIRST_SYSTEM_WINDOW && mAttrs.type != TYPE_TOAST) {
mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, shown);
}
- if (mIsImWindow && mWmService.mAccessibilityController != null) {
+ if (mIsImWindow && mWmService.mAccessibilityController.hasCallbacks()) {
mWmService.mAccessibilityController.onImeSurfaceShownChanged(this, shown);
}
}
@@ -3933,7 +3940,7 @@
"Requested redraw for orientation change: %s", this);
}
- if (mWmService.mAccessibilityController != null) {
+ if (mWmService.mAccessibilityController.hasCallbacks()) {
mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(displayId);
}
updateLocationInParentDisplayIfNeeded();
@@ -5059,7 +5066,7 @@
if (isAnimating()) {
return;
}
- if (mWmService.mAccessibilityController != null) {
+ if (mWmService.mAccessibilityController.hasCallbacks()) {
mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(getDisplayId());
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index f25706a..81f06d9 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -682,7 +682,7 @@
applyAnimationLocked(transit, true);
}
- if (mService.mAccessibilityController != null) {
+ if (mService.mAccessibilityController.hasCallbacks()) {
mService.mAccessibilityController.onWindowTransition(mWin, transit);
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
index 8ea21ec..a301799 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
@@ -46,6 +46,12 @@
@GuardedBy("mLock")
private final SparseIntArray mPermissionPolicy = new SparseIntArray();
+ /** Maps to {@code ActiveAdmin.mAdminCanGrantSensorsPermissions}.
+ *
+ * <p>For users affiliated with the device, they inherit the policy from {@code DO} so
+ * it will map to the {@code DO}'s policy. Otherwise it will map to the admin of the requesting
+ * user.
+ */
@GuardedBy("mLock")
private final SparseBooleanArray mCanGrantSensorsPermissions = new SparseBooleanArray();
@@ -102,17 +108,16 @@
}
@Override
- public boolean canAdminGrantSensorsPermissionsForUser(@UserIdInt int userHandle) {
+ public boolean canAdminGrantSensorsPermissionsForUser(@UserIdInt int userId) {
synchronized (mLock) {
- return mCanGrantSensorsPermissions.get(userHandle, false);
+ return mCanGrantSensorsPermissions.get(userId, false);
}
}
/** Sets ahmin control over permission grants for user. */
- public void setAdminCanGrantSensorsPermissions(@UserIdInt int userHandle,
- boolean canGrant) {
+ public void setAdminCanGrantSensorsPermissions(@UserIdInt int userId, boolean canGrant) {
synchronized (mLock) {
- mCanGrantSensorsPermissions.put(userHandle, canGrant);
+ mCanGrantSensorsPermissions.put(userId, canGrant);
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 5b205cd..0d3de2d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -9141,9 +9141,7 @@
}
/**
- * Returns the ActiveAdmin associated wit the PO or DO on the given user.
- * @param userHandle
- * @return
+ * Returns the ActiveAdmin associated with the PO or DO on the given user.
*/
private @Nullable ActiveAdmin getDeviceOrProfileOwnerAdminLocked(int userHandle) {
ActiveAdmin admin = getProfileOwnerAdminLocked(userHandle);
@@ -14300,6 +14298,7 @@
maybePauseDeviceWideLoggingLocked();
maybeResumeDeviceWideLoggingLocked();
maybeClearLockTaskPolicyLocked();
+ updateAdminCanGrantSensorsPermissionCache(callingUserId);
}
}
@@ -17480,7 +17479,10 @@
});
}
- private void setAdminCanGrantSensorsPermissionForUserUnchecked(int userId, boolean canGrant) {
+ private void setAdminCanGrantSensorsPermissionForUserUnchecked(@UserIdInt int userId,
+ boolean canGrant) {
+ Slogf.d(LOG_TAG, "setAdminCanGrantSensorsPermissionForUserUnchecked(%d, %b)",
+ userId, canGrant);
synchronized (getLockObject()) {
ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(userId);
@@ -17494,10 +17496,18 @@
}
}
- private void updateAdminCanGrantSensorsPermissionCache(int userId) {
+ private void updateAdminCanGrantSensorsPermissionCache(@UserIdInt int userId) {
synchronized (getLockObject()) {
- ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(userId);
- final boolean canGrant = owner != null ? owner.mAdminCanGrantSensorsPermissions : false;
+
+ ActiveAdmin owner;
+ // If the user is affiliated the device (either a DO itself, or an affiliated PO),
+ // use mAdminCanGrantSensorsPermissions from the DO
+ if (isUserAffiliatedWithDeviceLocked(userId)) {
+ owner = getDeviceOwnerAdminLocked();
+ } else {
+ owner = getDeviceOrProfileOwnerAdminLocked(userId);
+ }
+ boolean canGrant = owner != null ? owner.mAdminCanGrantSensorsPermissions : false;
mPolicyCache.setAdminCanGrantSensorsPermissions(userId, canGrant);
}
}
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
index a7644ec..64c426b 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
@@ -43,12 +43,14 @@
import android.util.SparseIntArray
import com.android.internal.R
import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils
import com.android.server.pm.parsing.pkg.PackageImpl
import com.android.server.testutils.mockThrowOnUnmocked
import com.android.server.testutils.whenever
import java.security.KeyPairGenerator
import java.security.PublicKey
import kotlin.contracts.ExperimentalContracts
+import kotlin.reflect.KFunction1
@ExperimentalContracts
class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, PackageImpl::class) {
@@ -82,7 +84,6 @@
"getLongVersionCode",
// Tested through constructor
"getManifestPackageName",
- "setManifestPackageName",
// Utility methods
"getStorageUuid",
// Removal not tested, irrelevant for parcelling concerns
@@ -142,21 +143,19 @@
AndroidPackage::getOverlayCategory,
AndroidPackage::getOverlayPriority,
AndroidPackage::getOverlayTarget,
- AndroidPackage::getOverlayTargetName,
+ AndroidPackage::getOverlayTargetOverlayableName,
AndroidPackage::getPackageName,
AndroidPackage::getPath,
AndroidPackage::getPermission,
- AndroidPackage::getPrimaryCpuAbi,
+ PackageImpl::getPrimaryCpuAbi,
AndroidPackage::getProcessName,
- AndroidPackage::getRealPackage,
AndroidPackage::getRequiredAccountType,
AndroidPackage::getRequiresSmallestWidthDp,
AndroidPackage::getResizeableActivity,
AndroidPackage::getRestrictedAccountType,
AndroidPackage::getRoundIconRes,
- AndroidPackage::getSeInfo,
- AndroidPackage::getSeInfoUser,
- AndroidPackage::getSecondaryCpuAbi,
+ PackageImpl::getSeInfo,
+ PackageImpl::getSecondaryCpuAbi,
AndroidPackage::getSecondaryNativeLibraryDir,
AndroidPackage::getSharedUserId,
AndroidPackage::getSharedUserLabel,
@@ -236,8 +235,8 @@
override fun extraParams() = listOf(
getter(AndroidPackage::getVolumeUuid, "57554103-df3e-4475-ae7a-8feba49353ac"),
getter(AndroidPackage::isProfileable, true),
- getter(AndroidPackage::getVersionCode, 3),
- getter(AndroidPackage::getVersionCodeMajor, 9),
+ getter(PackageImpl::getVersionCode, 3),
+ getter(PackageImpl::getVersionCodeMajor, 9),
getter(AndroidPackage::getUpgradeKeySets, setOf("testUpgradeKeySet")),
getter(AndroidPackage::isAnyDensity, false, 0),
getter(AndroidPackage::isResizeable, false, 0),
@@ -424,7 +423,7 @@
transformSet = { ParsedUsesPermission(it, 0) }
),
getSetByValue(
- AndroidPackage::getReqFeatures,
+ AndroidPackage::getRequestedFeatures,
PackageImpl::addReqFeature,
"test.feature.INFO",
transformGet = { it.singleOrNull()?.name.orEmpty() },
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
index 886b2e0..d6d5e62 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationEnforcerTest.kt
@@ -27,7 +27,6 @@
import android.os.Build
import android.os.Process
import android.util.ArraySet
-import android.util.SparseArray
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.pm.PackageSetting
import com.android.server.pm.parsing.pkg.AndroidPackage
@@ -332,7 +331,7 @@
domainSetId
)
) {
- whenever(getName()) { packageName }
+ whenever(getPackageName()) { packageName }
whenever(getPkg()) { mockPkg(packageName) }
whenever(this.domainSetId) { domainSetId }
whenever(readUserState(0)) { PackageUserState() }
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt
index 0fe3913..d67b26a 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationManagerApiTest.kt
@@ -77,7 +77,7 @@
}
assertThat(service.queryValidVerificationPackageNames())
- .containsExactly(pkgWithDomains.getName())
+ .containsExactly(pkgWithDomains.getPackageName())
}
@Test
@@ -104,16 +104,16 @@
addPackages(pkgWithDomains, pkgWithoutDomains)
}
- val infoOne = service.getDomainVerificationInfo(pkgWithDomains.getName())
+ val infoOne = service.getDomainVerificationInfo(pkgWithDomains.getPackageName())
assertThat(infoOne).isNotNull()
assertThat(infoOne!!.identifier).isEqualTo(pkgWithDomains.domainSetId)
- assertThat(infoOne.packageName).isEqualTo(pkgWithDomains.getName())
+ assertThat(infoOne.packageName).isEqualTo(pkgWithDomains.getPackageName())
assertThat(infoOne.hostToStateMap).containsExactlyEntriesIn(mapOf(
DOMAIN_1 to DomainVerificationInfo.STATE_NO_RESPONSE,
DOMAIN_2 to DomainVerificationInfo.STATE_NO_RESPONSE
))
- assertThat(service.getDomainVerificationInfo(pkgWithoutDomains.getName())).isNull()
+ assertThat(service.getDomainVerificationInfo(pkgWithoutDomains.getPackageName())).isNull()
assertFailsWith(PackageManager.NameNotFoundException::class) {
service.getDomainVerificationInfo("invalid.pkg.name")
@@ -125,7 +125,7 @@
val pkg1 = mockPkgSetting(PKG_ONE, UUID_ONE, listOf(DOMAIN_1, DOMAIN_2))
val pkg2 = mockPkgSetting(PKG_TWO, UUID_TWO, listOf(DOMAIN_3, DOMAIN_4))
- val map = mutableMapOf(pkg1.getName() to pkg1, pkg2.getName() to pkg2)
+ val map = mutableMapOf(pkg1.getPackageName() to pkg1, pkg2.getPackageName() to pkg2)
val service = makeService(map::get).apply { addPackages(pkg1, pkg2) }
assertThat(service.setStatus(UUID_ONE, setOf(DOMAIN_2), 1100))
@@ -167,7 +167,7 @@
val pkg1 = mockPkgSetting(PKG_ONE, UUID_ONE, listOf(DOMAIN_1, DOMAIN_2))
val pkg2 = mockPkgSetting(PKG_TWO, UUID_TWO, listOf(DOMAIN_3, DOMAIN_4))
- val map = mutableMapOf(pkg1.getName() to pkg1, pkg2.getName() to pkg2)
+ val map = mutableMapOf(pkg1.getPackageName() to pkg1, pkg2.getPackageName() to pkg2)
val service = makeService(map::get).apply { addPackages(pkg1, pkg2) }
service.setDomainVerificationLinkHandlingAllowed(PKG_ONE, false, 0)
@@ -196,9 +196,9 @@
val pkg3 = mockPkgSetting(PKG_THREE, UUID_THREE, listOf(DOMAIN_1, DOMAIN_2))
val map = mutableMapOf(
- pkg1.getName() to pkg1,
- pkg2.getName() to pkg2,
- pkg3.getName() to pkg3
+ pkg1.getPackageName() to pkg1,
+ pkg2.getPackageName() to pkg2,
+ pkg3.getPackageName() to pkg3
)
val service = makeService(map::get).apply { addPackages(pkg1, pkg2, pkg3) }
@@ -248,20 +248,20 @@
addPackages(pkgWithDomains, pkgWithoutDomains)
}
- val infoOne = service.getDomainVerificationUserState(pkgWithDomains.getName(), 0)
+ val infoOne = service.getDomainVerificationUserState(pkgWithDomains.getPackageName(), 0)
assertThat(infoOne).isNotNull()
assertThat(infoOne!!.identifier).isEqualTo(pkgWithDomains.domainSetId)
- assertThat(infoOne.packageName).isEqualTo(pkgWithDomains.getName())
+ assertThat(infoOne.packageName).isEqualTo(pkgWithDomains.getPackageName())
assertThat(infoOne.isLinkHandlingAllowed).isTrue()
assertThat(infoOne.hostToStateMap).containsExactlyEntriesIn(mapOf(
DOMAIN_1 to DomainVerificationUserState.DOMAIN_STATE_NONE,
DOMAIN_2 to DomainVerificationUserState.DOMAIN_STATE_NONE
))
- val infoTwo = service.getDomainVerificationUserState(pkgWithoutDomains.getName(), 0)
+ val infoTwo = service.getDomainVerificationUserState(pkgWithoutDomains.getPackageName(), 0)
assertThat(infoTwo).isNotNull()
assertThat(infoTwo!!.identifier).isEqualTo(pkgWithoutDomains.domainSetId)
- assertThat(infoTwo.packageName).isEqualTo(pkgWithoutDomains.getName())
+ assertThat(infoTwo.packageName).isEqualTo(pkgWithoutDomains.getPackageName())
assertThat(infoOne.isLinkHandlingAllowed).isTrue()
assertThat(infoTwo.hostToStateMap).isEmpty()
@@ -323,43 +323,43 @@
service.getOwnersForDomain(DOMAIN_1, 0).let {
assertThat(it).containsExactly(
- DomainOwner(pkg1.getName(), false),
- DomainOwner(pkg2.getName(), false)
+ DomainOwner(pkg1.getPackageName(), false),
+ DomainOwner(pkg2.getPackageName(), false)
).inOrder()
}
manager0.getOwnersForDomain(DOMAIN_1).let {
assertThat(it).containsExactly(
- DomainOwner(pkg1.getName(), false),
- DomainOwner(pkg2.getName(), false)
+ DomainOwner(pkg1.getPackageName(), false),
+ DomainOwner(pkg2.getPackageName(), false)
).inOrder()
}
service.getOwnersForDomain(DOMAIN_2, 0).let {
- assertThat(it).containsExactly(DomainOwner(pkg1.getName(), true))
+ assertThat(it).containsExactly(DomainOwner(pkg1.getPackageName(), true))
}
manager0.getOwnersForDomain(DOMAIN_2).let {
- assertThat(it).containsExactly(DomainOwner(pkg1.getName(), true))
+ assertThat(it).containsExactly(DomainOwner(pkg1.getPackageName(), true))
}
assertThat(service.getOwnersForDomain(DOMAIN_2, 1)).isEmpty()
assertThat(manager1.getOwnersForDomain(DOMAIN_2)).isEmpty()
service.setUserSelection(pkg1.domainSetId, setOf(DOMAIN_2), true, 1)
service.getOwnersForDomain(DOMAIN_2, 1).let {
- assertThat(it).containsExactly(DomainOwner(pkg1.getName(), true))
+ assertThat(it).containsExactly(DomainOwner(pkg1.getPackageName(), true))
}
manager1.getOwnersForDomain(DOMAIN_2).let {
- assertThat(it).containsExactly(DomainOwner(pkg1.getName(), true))
+ assertThat(it).containsExactly(DomainOwner(pkg1.getPackageName(), true))
}
// "Uninstall" the package from user 0 and ensure it's stripped from the results
pkg1User0Enabled.set(false)
- service.clearPackageForUser(pkg1.getName(), 0)
+ service.clearPackageForUser(pkg1.getPackageName(), 0)
service.getOwnersForDomain(DOMAIN_1, 0).let {
- assertThat(it).containsExactly(DomainOwner(pkg2.getName(), false))
+ assertThat(it).containsExactly(DomainOwner(pkg2.getPackageName(), false))
}
manager0.getOwnersForDomain(DOMAIN_1).let {
- assertThat(it).containsExactly(DomainOwner(pkg2.getName(), false))
+ assertThat(it).containsExactly(DomainOwner(pkg2.getPackageName(), false))
}
// Domain 2 user selection gone for user 0
@@ -367,33 +367,33 @@
// Domain 2 user selection still around for user 1
service.getOwnersForDomain(DOMAIN_2, 1).let {
- assertThat(it).containsExactly(DomainOwner(pkg1.getName(), true))
+ assertThat(it).containsExactly(DomainOwner(pkg1.getPackageName(), true))
}
manager1.getOwnersForDomain(DOMAIN_2).let {
- assertThat(it).containsExactly(DomainOwner(pkg1.getName(), true))
+ assertThat(it).containsExactly(DomainOwner(pkg1.getPackageName(), true))
}
// Now assert for user 1 that it was unaffected by the change to user 0
service.getOwnersForDomain(DOMAIN_1, 1).let {
assertThat(it).containsExactly(
- DomainOwner(pkg1.getName(), false),
- DomainOwner(pkg2.getName(), false)
+ DomainOwner(pkg1.getPackageName(), false),
+ DomainOwner(pkg2.getPackageName(), false)
).inOrder()
}
manager1.getOwnersForDomain(DOMAIN_1).let {
assertThat(it).containsExactly(
- DomainOwner(pkg1.getName(), false),
- DomainOwner(pkg2.getName(), false)
+ DomainOwner(pkg1.getPackageName(), false),
+ DomainOwner(pkg2.getPackageName(), false)
).inOrder()
}
service.setUserSelection(pkg1.domainSetId, setOf(DOMAIN_2), true, 0)
service.getOwnersForDomain(DOMAIN_2, 1).let {
- assertThat(it).containsExactly(DomainOwner(pkg1.getName(), true))
+ assertThat(it).containsExactly(DomainOwner(pkg1.getPackageName(), true))
}
manager1.getOwnersForDomain(DOMAIN_2).let {
- assertThat(it).containsExactly(DomainOwner(pkg1.getName(), true))
+ assertThat(it).containsExactly(DomainOwner(pkg1.getPackageName(), true))
}
// "Reinstall" the package to user 0
@@ -406,10 +406,10 @@
// Other package unaffected
service.setUserSelection(pkg2.domainSetId, setOf(DOMAIN_2), true, 0)
service.getOwnersForDomain(DOMAIN_2, 0).let {
- assertThat(it).containsExactly(DomainOwner(pkg2.getName(), true))
+ assertThat(it).containsExactly(DomainOwner(pkg2.getPackageName(), true))
}
manager0.getOwnersForDomain(DOMAIN_2).let {
- assertThat(it).containsExactly(DomainOwner(pkg2.getName(), true))
+ assertThat(it).containsExactly(DomainOwner(pkg2.getPackageName(), true))
}
}
@@ -456,7 +456,7 @@
}
private fun makeService(vararg pkgSettings: PackageSetting) =
- makeService { pkgName -> pkgSettings.find { pkgName == it.getName() } }
+ makeService { pkgName -> pkgSettings.find { pkgName == it.getPackageName() } }
private fun makeService(pkgSettingFunction: (String) -> PackageSetting? = { null }) =
DomainVerificationService(mockThrowOnUnmocked {
@@ -521,7 +521,7 @@
}
whenever(getPkg()) { pkg }
- whenever(getName()) { pkgName }
+ whenever(getPackageName()) { pkgName }
whenever(this.domainSetId) { domainSetId }
whenever(getInstantApp(anyInt())) { false }
whenever(firstInstallTime) { 0L }
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
index 6c2a891..03f1124 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationPackageTest.kt
@@ -81,16 +81,16 @@
fun addPackageFirstTime() {
val service = makeService(pkg1, pkg2)
service.addPackage(pkg1)
- val info = service.getInfo(pkg1.getName())
- assertThat(info.packageName).isEqualTo(pkg1.getName())
+ val info = service.getInfo(pkg1.getPackageName())
+ assertThat(info.packageName).isEqualTo(pkg1.getPackageName())
assertThat(info.identifier).isEqualTo(pkg1.domainSetId)
assertThat(info.hostToStateMap).containsExactlyEntriesIn(mapOf(
DOMAIN_1 to STATE_NO_RESPONSE,
DOMAIN_2 to STATE_NO_RESPONSE,
))
- val userState = service.getUserState(pkg1.getName())
- assertThat(userState.packageName).isEqualTo(pkg1.getName())
+ val userState = service.getUserState(pkg1.getPackageName())
+ assertThat(userState.packageName).isEqualTo(pkg1.getPackageName())
assertThat(userState.identifier).isEqualTo(pkg1.domainSetId)
assertThat(userState.isLinkHandlingAllowed).isEqualTo(true)
assertThat(userState.user.identifier).isEqualTo(USER_ID)
@@ -100,7 +100,7 @@
))
assertThat(service.queryValidVerificationPackageNames())
- .containsExactly(pkg1.getName())
+ .containsExactly(pkg1.getPackageName())
}
@Test
@@ -109,14 +109,14 @@
val pkg2 = mockPkgSetting(PKG_TWO, UUID_TWO, SIGNATURE_TWO, isSystemApp = true)
val service = makeService(
- systemConfiguredPackageNames = ArraySet(setOf(pkg1.getName(), pkg2.getName())),
+ systemConfiguredPackageNames = ArraySet(setOf(pkg1.getPackageName(), pkg2.getPackageName())),
pkg1, pkg2
)
service.addPackage(pkg1)
service.addPackage(pkg2)
- service.getInfo(pkg1.getName()).apply {
- assertThat(packageName).isEqualTo(pkg1.getName())
+ service.getInfo(pkg1.getPackageName()).apply {
+ assertThat(packageName).isEqualTo(pkg1.getPackageName())
assertThat(identifier).isEqualTo(pkg1.domainSetId)
assertThat(hostToStateMap).containsExactlyEntriesIn(
mapOf(
@@ -126,8 +126,8 @@
)
}
- service.getUserState(pkg1.getName()).apply {
- assertThat(packageName).isEqualTo(pkg1.getName())
+ service.getUserState(pkg1.getPackageName()).apply {
+ assertThat(packageName).isEqualTo(pkg1.getPackageName())
assertThat(identifier).isEqualTo(pkg1.domainSetId)
assertThat(isLinkHandlingAllowed).isEqualTo(true)
assertThat(user.identifier).isEqualTo(USER_ID)
@@ -139,8 +139,8 @@
)
}
- service.getInfo(pkg2.getName()).apply {
- assertThat(packageName).isEqualTo(pkg2.getName())
+ service.getInfo(pkg2.getPackageName()).apply {
+ assertThat(packageName).isEqualTo(pkg2.getPackageName())
assertThat(identifier).isEqualTo(pkg2.domainSetId)
assertThat(hostToStateMap).containsExactlyEntriesIn(
mapOf(
@@ -150,8 +150,8 @@
)
}
- service.getUserState(pkg2.getName()).apply {
- assertThat(packageName).isEqualTo(pkg2.getName())
+ service.getUserState(pkg2.getPackageName()).apply {
+ assertThat(packageName).isEqualTo(pkg2.getPackageName())
assertThat(identifier).isEqualTo(pkg2.domainSetId)
assertThat(isLinkHandlingAllowed).isEqualTo(true)
assertThat(user.identifier).isEqualTo(USER_ID)
@@ -164,7 +164,7 @@
}
assertThat(service.queryValidVerificationPackageNames())
- .containsExactly(pkg1.getName(), pkg2.getName())
+ .containsExactly(pkg1.getPackageName(), pkg2.getPackageName())
}
@Test
@@ -175,7 +175,7 @@
<domain-verifications>
<active>
<package-state
- packageName="${pkg1.getName()}"
+ packageName="${pkg1.getPackageName()}"
id="${pkg1.domainSetId}"
signature="$DIGEST_ONE"
>
@@ -190,8 +190,8 @@
val service = makeService(pkg1, pkg2)
service.restoreSettings(Xml.resolvePullParser(xml.byteInputStream()))
service.addPackage(pkg1)
- val info = service.getInfo(pkg1.getName())
- assertThat(info.packageName).isEqualTo(pkg1.getName())
+ val info = service.getInfo(pkg1.getPackageName())
+ assertThat(info.packageName).isEqualTo(pkg1.getPackageName())
assertThat(info.identifier).isEqualTo(pkg1.domainSetId)
assertThat(info.hostToStateMap).containsExactlyEntriesIn(
mapOf(
@@ -200,8 +200,8 @@
)
)
- val userState = service.getUserState(pkg1.getName())
- assertThat(userState.packageName).isEqualTo(pkg1.getName())
+ val userState = service.getUserState(pkg1.getPackageName())
+ assertThat(userState.packageName).isEqualTo(pkg1.getPackageName())
assertThat(userState.identifier).isEqualTo(pkg1.domainSetId)
assertThat(userState.isLinkHandlingAllowed).isEqualTo(true)
assertThat(userState.user.identifier).isEqualTo(USER_ID)
@@ -213,7 +213,7 @@
)
assertThat(service.queryValidVerificationPackageNames())
- .containsExactly(pkg1.getName())
+ .containsExactly(pkg1.getPackageName())
}
@Test
@@ -224,7 +224,7 @@
<domain-verifications>
<active>
<package-state
- packageName="${pkg1.getName()}"
+ packageName="${pkg1.getPackageName()}"
id="${pkg1.domainSetId}"
signature="INVALID_SIGNATURE"
>
@@ -239,8 +239,8 @@
val service = makeService(pkg1, pkg2)
service.restoreSettings(Xml.resolvePullParser(xml.byteInputStream()))
service.addPackage(pkg1)
- val info = service.getInfo(pkg1.getName())
- assertThat(info.packageName).isEqualTo(pkg1.getName())
+ val info = service.getInfo(pkg1.getPackageName())
+ assertThat(info.packageName).isEqualTo(pkg1.getPackageName())
assertThat(info.identifier).isEqualTo(pkg1.domainSetId)
assertThat(info.hostToStateMap).containsExactlyEntriesIn(
mapOf(
@@ -249,8 +249,8 @@
)
)
- val userState = service.getUserState(pkg1.getName())
- assertThat(userState.packageName).isEqualTo(pkg1.getName())
+ val userState = service.getUserState(pkg1.getPackageName())
+ assertThat(userState.packageName).isEqualTo(pkg1.getPackageName())
assertThat(userState.identifier).isEqualTo(pkg1.domainSetId)
assertThat(userState.isLinkHandlingAllowed).isEqualTo(true)
assertThat(userState.user.identifier).isEqualTo(USER_ID)
@@ -262,7 +262,7 @@
)
assertThat(service.queryValidVerificationPackageNames())
- .containsExactly(pkg1.getName())
+ .containsExactly(pkg1.getPackageName())
}
@Test
@@ -273,7 +273,7 @@
<domain-verifications>
<active>
<package-state
- packageName="${pkg1.getName()}"
+ packageName="${pkg1.getPackageName()}"
id="${pkg1.domainSetId}"
>
<state>
@@ -311,8 +311,8 @@
service.addPackage(pkg1)
- val userState = service.getUserState(pkg1.getName())
- assertThat(userState.packageName).isEqualTo(pkg1.getName())
+ val userState = service.getUserState(pkg1.getPackageName())
+ assertThat(userState.packageName).isEqualTo(pkg1.getPackageName())
assertThat(userState.identifier).isEqualTo(pkg1.domainSetId)
assertThat(userState.isLinkHandlingAllowed).isEqualTo(false)
assertThat(userState.user.identifier).isEqualTo(USER_ID)
@@ -348,7 +348,7 @@
<domain-verifications>
<active>
<package-state
- packageName="${pkg1.getName()}"
+ packageName="${pkg1.getPackageName()}"
id="${pkg1.domainSetId}"
signature="$DIGEST_ONE"
>
@@ -381,8 +381,8 @@
service: DomainVerificationService,
expectRestore: Boolean = false
) {
- val info = service.getInfo(pkg1.getName())
- assertThat(info.packageName).isEqualTo(pkg1.getName())
+ val info = service.getInfo(pkg1.getPackageName())
+ assertThat(info.packageName).isEqualTo(pkg1.getPackageName())
assertThat(info.identifier).isEqualTo(pkg1.domainSetId)
assertThat(info.hostToStateMap).containsExactlyEntriesIn(mapOf(
// To share the majority of code, special case restoration to check a different int
@@ -390,8 +390,8 @@
DOMAIN_2 to STATE_NO_RESPONSE,
))
- val userState = service.getUserState(pkg1.getName())
- assertThat(userState.packageName).isEqualTo(pkg1.getName())
+ val userState = service.getUserState(pkg1.getPackageName())
+ assertThat(userState.packageName).isEqualTo(pkg1.getPackageName())
assertThat(userState.identifier).isEqualTo(pkg1.domainSetId)
assertThat(userState.isLinkHandlingAllowed).isEqualTo(false)
assertThat(userState.user.identifier).isEqualTo(USER_ID)
@@ -401,10 +401,10 @@
))
assertThat(service.queryValidVerificationPackageNames())
- .containsExactly(pkg1.getName())
+ .containsExactly(pkg1.getPackageName())
// Re-enable link handling to check that the 3/4 domains were stripped
- service.setDomainVerificationLinkHandlingAllowed(pkg1.getName(), true, USER_ID)
+ service.setDomainVerificationLinkHandlingAllowed(pkg1.getPackageName(), true, USER_ID)
assertThat(service.getOwnersForDomain(DOMAIN_1, USER_ID))
.containsExactly(DomainOwner(PKG_ONE, false))
@@ -630,7 +630,7 @@
serviceBefore.addPackage(pkg2)
serviceBefore.setStatus(pkg1.domainSetId, setOf(DOMAIN_1), STATE_SUCCESS)
- serviceBefore.setDomainVerificationLinkHandlingAllowed(pkg1.getName(), false, 10)
+ serviceBefore.setDomainVerificationLinkHandlingAllowed(pkg1.getPackageName(), false, 10)
serviceBefore.setUserSelection(pkg2.domainSetId, setOf(DOMAIN_2), true, 0)
serviceBefore.setUserSelection(pkg2.domainSetId, setOf(DOMAIN_3), true, 10)
@@ -758,11 +758,11 @@
systemConfiguredPackageNames: ArraySet<String> = ArraySet(),
vararg pkgSettings: PackageSetting
) = makeService(systemConfiguredPackageNames = systemConfiguredPackageNames) {
- pkgName -> pkgSettings.find { pkgName == it.getName() }
+ pkgName -> pkgSettings.find { pkgName == it.getPackageName() }
}
private fun makeService(vararg pkgSettings: PackageSetting) =
- makeService { pkgName -> pkgSettings.find { pkgName == it.getName() } }
+ makeService { pkgName -> pkgSettings.find { pkgName == it.getPackageName() } }
private fun makeService(
systemConfiguredPackageNames: ArraySet<String> = ArraySet(),
@@ -829,7 +829,7 @@
}
whenever(getPkg()) { pkg }
- whenever(getName()) { pkgName }
+ whenever(getPackageName()) { pkgName }
whenever(this.domainSetId) { domainSetId }
whenever(getInstantApp(anyInt())) { false }
whenever(firstInstallTime) { 0L }
@@ -845,8 +845,8 @@
linkHandingAllowed: Boolean = true,
hostToStateMap: Map<String, Int>
) {
- getUserState(pkg.getName(), userId).apply {
- assertThat(this.packageName).isEqualTo(pkg.getName())
+ getUserState(pkg.getPackageName(), userId).apply {
+ assertThat(this.packageName).isEqualTo(pkg.getPackageName())
assertThat(this.identifier).isEqualTo(pkg.domainSetId)
assertThat(this.isLinkHandlingAllowed).isEqualTo(linkHandingAllowed)
assertThat(this.user.identifier).isEqualTo(userId)
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
index 6a75795..32866ea 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
@@ -26,7 +26,6 @@
import android.os.Build
import android.os.Process
import android.util.ArraySet
-import android.util.SparseArray
import com.android.server.pm.PackageSetting
import com.android.server.pm.parsing.pkg.AndroidPackage
import com.android.server.pm.test.verify.domain.DomainVerificationTestUtils.mockPackageSettings
@@ -232,7 +231,7 @@
TEST_UUID
)
) {
- whenever(getName()) { TEST_PKG }
+ whenever(getPackageName()) { TEST_PKG }
whenever(getPkg()) { mockPkg() }
whenever(domainSetId) { TEST_UUID }
whenever(readUserState(0)) { PackageUserState() }
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt
index 3e2853c..1d5e280 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationUserSelectionOverrideTest.kt
@@ -139,7 +139,7 @@
}
whenever(getPkg()) { pkg }
- whenever(getName()) { pkgName }
+ whenever(getPackageName()) { pkgName }
whenever(this.domainSetId) { domainSetId }
whenever(getInstantApp(anyInt())) { false }
whenever(firstInstallTime) { 0L }
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index fd364ae7..51fa851 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -37,6 +37,8 @@
import android.content.ContentResolver;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.os.Bundle;
import android.os.RecoverySystem;
@@ -83,6 +85,8 @@
private static final String CALLING_PACKAGE1 = "com.package.name1";
private static final String CALLING_PACKAGE2 = "com.package.name2";
private static final String CALLING_PACKAGE3 = "com.package.name3";
+ private static final String PERSISTENT_PACKAGE = "com.persistent.package";
+ private static final String NON_PERSISTENT_PACKAGE = "com.nonpersistent.package";
private static final String NAMESPACE1 = "namespace1";
private static final String NAMESPACE2 = "namespace2";
private static final String NAMESPACE3 = "namespace3";
@@ -103,6 +107,8 @@
private PackageWatchdog mMockPackageWatchdog;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private ContentResolver mMockContentResolver;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private PackageManager mPackageManager;
@Captor
private ArgumentCaptor<RemoteCallback> mMonitorCallbackCaptor;
@@ -129,6 +135,17 @@
mNamespacesWiped = new HashSet<>();
when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
+ when(mMockContext.getPackageManager()).thenReturn(mPackageManager);
+ ApplicationInfo persistentApplicationInfo = new ApplicationInfo();
+ persistentApplicationInfo.flags |=
+ ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_PERSISTENT;
+
+ // If the package name is PERSISTENT_PACKAGE, then set the flags to be persistent and
+ // system. Don't set any flags otherwise.
+ when(mPackageManager.getApplicationInfo(eq(PERSISTENT_PACKAGE),
+ anyInt())).thenReturn(persistentApplicationInfo);
+ when(mPackageManager.getApplicationInfo(eq(NON_PERSISTENT_PACKAGE),
+ anyInt())).thenReturn(new ApplicationInfo());
// Reset observer instance to get new mock context on every run
RescuePartyObserver.reset();
@@ -241,29 +258,53 @@
@Test
public void testPersistentAppCrashDetectionWithExecutionForAllRescueLevels() {
- notePersistentAppCrash(1);
+ noteAppCrash(1, true);
verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, /*resetNamespaces=*/ null,
/*configResetVerifiedTimesMap=*/ null);
- notePersistentAppCrash(2);
+ noteAppCrash(2, true);
verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES, /*resetNamespaces=*/ null,
/*configResetVerifiedTimesMap=*/ null);
- notePersistentAppCrash(3);
+ noteAppCrash(3, true);
verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, /*resetNamespaces=*/ null,
/*configResetVerifiedTimesMap=*/ null);
- notePersistentAppCrash(4);
+ noteAppCrash(4, true);
assertTrue(RescueParty.isRebootPropertySet());
- notePersistentAppCrash(5);
+ noteAppCrash(5, true);
assertTrue(RescueParty.isFactoryResetPropertySet());
}
@Test
+ public void testNonPersistentAppOnlyPerformsFlagResets() {
+ noteAppCrash(1, false);
+
+ verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, /*resetNamespaces=*/ null,
+ /*configResetVerifiedTimesMap=*/ null);
+
+ noteAppCrash(2, false);
+
+ verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES, /*resetNamespaces=*/ null,
+ /*configResetVerifiedTimesMap=*/ null);
+
+ noteAppCrash(3, false);
+
+ verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, /*resetNamespaces=*/ null,
+ /*configResetVerifiedTimesMap=*/ null);
+
+ noteAppCrash(4, false);
+ assertFalse(RescueParty.isRebootPropertySet());
+
+ noteAppCrash(5, false);
+ assertFalse(RescueParty.isFactoryResetPropertySet());
+ }
+
+ @Test
public void testNonPersistentAppCrashDetectionWithScopedResets() {
RescueParty.onSettingsProviderPublished(mMockContext);
verify(() -> Settings.Config.registerMonitorCallback(eq(mMockContentResolver),
@@ -311,11 +352,11 @@
observer.execute(new VersionedPackage(
CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 4);
- assertTrue(RescueParty.isRebootPropertySet());
+ assertFalse(RescueParty.isRebootPropertySet());
observer.execute(new VersionedPackage(
CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 5);
- assertTrue(RescueParty.isFactoryResetPropertySet());
+ assertFalse(RescueParty.isFactoryResetPropertySet());
}
@Test
@@ -376,11 +417,11 @@
observer.execute(new VersionedPackage(
CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 4);
- assertTrue(RescueParty.isRebootPropertySet());
+ assertFalse(RescueParty.isRebootPropertySet());
observer.execute(new VersionedPackage(
CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING, 5);
- assertTrue(RescueParty.isFactoryResetPropertySet());
+ assertFalse(RescueParty.isFactoryResetPropertySet());
}
@Test
@@ -627,9 +668,10 @@
RescuePartyObserver.getInstance(mMockContext).executeBootLoopMitigation(mitigationCount);
}
- private void notePersistentAppCrash(int mitigationCount) {
+ private void noteAppCrash(int mitigationCount, boolean isPersistent) {
+ String packageName = isPersistent ? PERSISTENT_PACKAGE : NON_PERSISTENT_PACKAGE;
RescuePartyObserver.getInstance(mMockContext).execute(new VersionedPackage(
- "com.package.name", 1), PackageWatchdog.FAILURE_REASON_APP_CRASH, mitigationCount);
+ packageName, 1), PackageWatchdog.FAILURE_REASON_APP_CRASH, mitigationCount);
}
private Bundle getConfigAccessBundle(String callingPackage, String namespace) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 28cdd63..b5ad459 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -336,6 +336,62 @@
}
@Test
+ public void testAfterDisplayChange_DefaultDisplayModeIsUpdated() throws Exception {
+ SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 60f);
+ SurfaceControl.DisplayMode[] modes =
+ new SurfaceControl.DisplayMode[]{displayMode};
+ FakeDisplay display = new FakeDisplay(PORT_A, modes, 0);
+ setUpDisplay(display);
+ updateAvailableDisplays();
+ mAdapter.registerLocked();
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+
+ assertThat(mListener.addedDisplays.size()).isEqualTo(1);
+ assertThat(mListener.changedDisplays).isEmpty();
+
+ DisplayDeviceInfo displayDeviceInfo = mListener.addedDisplays.get(
+ 0).getDisplayDeviceInfoLocked();
+
+ assertThat(displayDeviceInfo.supportedModes.length).isEqualTo(modes.length);
+ assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode);
+
+ Display.Mode defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
+ assertThat(matches(defaultMode, displayMode)).isTrue();
+
+ // Set the display mode to an unsupported mode
+ SurfaceControl.DisplayMode displayMode2 = createFakeDisplayMode(1, 1920, 1080, 120f);
+ mListener.addedDisplays.get(0).setUserPreferredDisplayModeLocked(
+ new Display.Mode(displayMode2.width, displayMode2.height,
+ displayMode2.refreshRate));
+ updateAvailableDisplays();
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+ defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
+ assertThat(matches(defaultMode, displayMode2)).isFalse();
+
+ // Change the display
+ modes = new SurfaceControl.DisplayMode[]{displayMode, displayMode2};
+ display.dynamicInfo.supportedDisplayModes = modes;
+ setUpDisplay(display);
+ mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
+ waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
+
+ assertTrue(mListener.traversalRequested);
+ assertThat(mListener.addedDisplays.size()).isEqualTo(1);
+ assertThat(mListener.changedDisplays.size()).isEqualTo(1);
+
+ DisplayDevice displayDevice = mListener.changedDisplays.get(0);
+ displayDevice.applyPendingDisplayDeviceInfoChangesLocked();
+ displayDeviceInfo = mListener.addedDisplays.get(0).getDisplayDeviceInfoLocked();
+
+ assertThat(displayDeviceInfo.supportedModes.length).isEqualTo(modes.length);
+ assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode);
+ assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode2);
+
+ defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
+ assertThat(matches(defaultMode, displayMode2)).isTrue();
+ }
+
+ @Test
public void testAfterDisplayChange_DisplayModesAreUpdated() throws Exception {
SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 60f);
SurfaceControl.DisplayMode[] modes =
@@ -356,12 +412,10 @@
assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode);
Display.Mode defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
- assertThat(defaultMode.matches(displayMode.width, displayMode.height,
- displayMode.refreshRate)).isTrue();
+ assertThat(matches(defaultMode, displayMode)).isTrue();
Display.Mode activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId);
- assertThat(activeMode.matches(displayMode.width, displayMode.height,
- displayMode.refreshRate)).isTrue();
+ assertThat(matches(activeMode, displayMode)).isTrue();
// Change the display
SurfaceControl.DisplayMode addedDisplayInfo = createFakeDisplayMode(1, 3840, 2160, 60f);
@@ -385,12 +439,10 @@
assertModeIsSupported(displayDeviceInfo.supportedModes, addedDisplayInfo);
activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId);
- assertThat(activeMode.matches(addedDisplayInfo.width, addedDisplayInfo.height,
- addedDisplayInfo.refreshRate)).isTrue();
+ assertThat(matches(activeMode, addedDisplayInfo)).isTrue();
defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
- assertThat(defaultMode.matches(addedDisplayInfo.width, addedDisplayInfo.height,
- addedDisplayInfo.refreshRate)).isTrue();
+ assertThat(matches(defaultMode, addedDisplayInfo)).isTrue();
}
@Test
@@ -918,4 +970,9 @@
});
return mockArray;
}
+
+ private boolean matches(Display.Mode a, SurfaceControl.DisplayMode b) {
+ return a.getPhysicalWidth() == b.width && a.getPhysicalHeight() == b.height
+ && Float.floatToIntBits(a.getRefreshRate()) == Float.floatToIntBits(b.refreshRate);
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
index b60e0c3..6a4d69f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
@@ -87,6 +87,7 @@
@Mock private Context mContext;
@Mock private IStorageManager mStorageManager;
@Mock private ApexManager mApexManager;
+ @Mock private PackageManagerService mMockPackageManagerInternal;
private File mTmpDir;
private StagingManager mStagingManager;
@@ -826,7 +827,7 @@
PackageInstallerSession session = new PackageInstallerSession(
/* callback */ null,
/* context */ null,
- /* pm */ null,
+ /* pm */ mMockPackageManagerInternal,
/* sessionProvider */ null,
/* silentUpdatePolicy */ null,
/* looper */ BackgroundThread.getHandler().getLooper(),
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
index 53483f6..fe23c14 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
@@ -18,13 +18,18 @@
import static android.app.WallpaperManager.COMMAND_REAPPLY;
import static android.app.WallpaperManager.FLAG_SYSTEM;
+import static android.os.FileObserver.CLOSE_WRITE;
+import static android.os.UserHandle.USER_SYSTEM;
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.server.wallpaper.WallpaperManagerService.WALLPAPER;
+import static com.android.server.wallpaper.WallpaperManagerService.WALLPAPER_CROP;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertEquals;
@@ -34,6 +39,7 @@
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.reset;
@@ -41,6 +47,7 @@
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.content.ComponentName;
import android.content.Context;
@@ -49,8 +56,10 @@
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.ServiceInfo;
+import android.graphics.Color;
import android.hardware.display.DisplayManager;
-import android.os.UserHandle;
+import android.os.RemoteException;
+import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.service.wallpaper.IWallpaperConnection;
import android.service.wallpaper.IWallpaperEngine;
@@ -242,13 +251,13 @@
*/
@Test
public void testDataCorrectAfterBoot() {
- mService.switchUser(UserHandle.USER_SYSTEM, null);
+ mService.switchUser(USER_SYSTEM, null);
final WallpaperData fallbackData = mService.mFallbackWallpaper;
assertEquals("Fallback wallpaper component should be ImageWallpaper.",
sImageWallpaperComponentName, fallbackData.wallpaperComponent);
- verifyLastWallpaperData(UserHandle.USER_SYSTEM, sDefaultWallpaperComponent);
+ verifyLastWallpaperData(USER_SYSTEM, sDefaultWallpaperComponent);
verifyDisplayData();
}
@@ -261,7 +270,7 @@
assumeThat(sDefaultWallpaperComponent,
not(CoreMatchers.equalTo(sImageWallpaperComponentName)));
- final int testUserId = UserHandle.USER_SYSTEM;
+ final int testUserId = USER_SYSTEM;
mService.switchUser(testUserId, null);
verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent);
verifyCurrentSystemData(testUserId);
@@ -281,7 +290,7 @@
*/
@Test
public void testSetCurrentComponent() throws Exception {
- final int testUserId = UserHandle.USER_SYSTEM;
+ final int testUserId = USER_SYSTEM;
mService.switchUser(testUserId, null);
verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent);
verifyCurrentSystemData(testUserId);
@@ -387,6 +396,42 @@
assertEquals(systemWallpaperData.primaryColors, shouldMatchSystem.primaryColors);
}
+ @Test
+ public void testWallpaperManagerCallbackInRightOrder() throws RemoteException {
+ WallpaperData wallpaper = new WallpaperData(
+ USER_SYSTEM, mService.getWallpaperDir(USER_SYSTEM), WALLPAPER, WALLPAPER_CROP);
+ wallpaper.primaryColors = new WallpaperColors(Color.valueOf(Color.RED),
+ Color.valueOf(Color.BLUE), null);
+
+ spyOn(wallpaper);
+ doReturn(wallpaper).when(mService).getWallpaperSafeLocked(wallpaper.userId, FLAG_SYSTEM);
+ doNothing().when(mService).switchWallpaper(any(), any());
+ doReturn(true).when(mService)
+ .bindWallpaperComponentLocked(any(), anyBoolean(), anyBoolean(), any(), any());
+ doNothing().when(mService).saveSettingsLocked(wallpaper.userId);
+ doNothing().when(mService).generateCrop(wallpaper);
+
+ // timestamps of {ACTION_WALLPAPER_CHANGED, onWallpaperColorsChanged}
+ final long[] timestamps = new long[2];
+ doAnswer(invocation -> timestamps[0] = SystemClock.elapsedRealtime())
+ .when(sContext).sendBroadcastAsUser(any(), any());
+ doAnswer(invocation -> timestamps[1] = SystemClock.elapsedRealtime())
+ .when(mService).notifyWallpaperColorsChanged(wallpaper, FLAG_SYSTEM);
+
+ assertNull(wallpaper.wallpaperObserver);
+ mService.switchUser(wallpaper.userId, null);
+ assertNotNull(wallpaper.wallpaperObserver);
+ // We will call onEvent directly, so stop watching the file.
+ wallpaper.wallpaperObserver.stopWatching();
+
+ spyOn(wallpaper.wallpaperObserver);
+ doReturn(wallpaper).when(wallpaper.wallpaperObserver).dataForEvent(true, false);
+ wallpaper.wallpaperObserver.onEvent(CLOSE_WRITE, WALLPAPER);
+
+ // ACTION_WALLPAPER_CHANGED should be invoked before onWallpaperColorsChanged.
+ assertTrue(timestamps[1] > timestamps[0]);
+ }
+
// Verify that after continue switch user from userId 0 to lastUserId, the wallpaper data for
// non-current user must not bind to wallpaper service.
private void verifyNoConnectionBeforeLastUser(int lastUserId) {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
index e612d12..086e3c0 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
@@ -53,6 +53,7 @@
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
@@ -92,7 +93,7 @@
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import com.android.server.accessibility.AccessibilityWindowManager.RemoteAccessibilityConnection;
-import com.android.server.accessibility.magnification.FullScreenMagnificationController;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
import com.android.server.accessibility.test.MessageCapturingHandler;
import com.android.server.wm.WindowManagerInternal;
@@ -170,7 +171,7 @@
@Mock private IAccessibilityInteractionConnection mMockIA11yInteractionConnection;
@Mock private IAccessibilityInteractionConnectionCallback mMockCallback;
@Mock private FingerprintGestureDispatcher mMockFingerprintGestureDispatcher;
- @Mock private FullScreenMagnificationController mMockFullScreenMagnificationController;
+ @Mock private MagnificationProcessor mMockMagnificationProcessor;
@Mock private RemoteCallback.OnResultListener mMockListener;
@Before
@@ -181,8 +182,8 @@
when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mMockKeyEventDispatcher);
when(mMockSystemSupport.getFingerprintGestureDispatcher())
.thenReturn(mMockFingerprintGestureDispatcher);
- when(mMockSystemSupport.getFullScreenMagnificationController())
- .thenReturn(mMockFullScreenMagnificationController);
+ when(mMockSystemSupport.getMagnificationProcessor())
+ .thenReturn(mMockMagnificationProcessor);
PowerManager powerManager =
new PowerManager(mMockContext, mMockIPowerManager, mMockIThermalService, mHandler);
@@ -558,7 +559,7 @@
public void getMagnificationScale() {
final int displayId = 1;
final float scale = 2.0f;
- when(mMockFullScreenMagnificationController.getScale(displayId)).thenReturn(scale);
+ when(mMockMagnificationProcessor.getScale(displayId)).thenReturn(scale);
final float result = mServiceConnection.getMagnificationScale(displayId);
assertThat(result, is(scale));
@@ -568,7 +569,7 @@
public void getMagnificationScale_serviceNotBelongCurrentUser_returnNoScale() {
final int displayId = 1;
final float scale = 2.0f;
- when(mMockFullScreenMagnificationController.getScale(displayId)).thenReturn(scale);
+ when(mMockMagnificationProcessor.getScale(displayId)).thenReturn(scale);
when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
final float result = mServiceConnection.getMagnificationScale(displayId);
@@ -576,31 +577,14 @@
}
@Test
- public void getMagnificationRegion_notRegistered_shouldRegisterThenUnregister() {
- final int displayId = 1;
- final Region region = new Region(10, 20, 100, 200);
- doAnswer((invocation) -> {
- ((Region) invocation.getArguments()[1]).set(region);
- return null;
- }).when(mMockFullScreenMagnificationController).getMagnificationRegion(eq(displayId),
- any());
- when(mMockFullScreenMagnificationController.isRegistered(displayId)).thenReturn(false);
-
- final Region result = mServiceConnection.getMagnificationRegion(displayId);
- assertThat(result, is(region));
- verify(mMockFullScreenMagnificationController).register(displayId);
- verify(mMockFullScreenMagnificationController).unregister(displayId);
- }
-
- @Test
public void getMagnificationRegion_serviceNotBelongCurrentUser_returnEmptyRegion() {
final int displayId = 1;
final Region region = new Region(10, 20, 100, 200);
doAnswer((invocation) -> {
((Region) invocation.getArguments()[1]).set(region);
return null;
- }).when(mMockFullScreenMagnificationController).getMagnificationRegion(eq(displayId),
- any());
+ }).when(mMockMagnificationProcessor).getMagnificationRegion(eq(displayId),
+ any(), anyBoolean());
when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
final Region result = mServiceConnection.getMagnificationRegion(displayId);
@@ -608,23 +592,11 @@
}
@Test
- public void getMagnificationCenterX_notRegistered_shouldRegisterThenUnregister() {
- final int displayId = 1;
- final float centerX = 480.0f;
- when(mMockFullScreenMagnificationController.getCenterX(displayId)).thenReturn(centerX);
- when(mMockFullScreenMagnificationController.isRegistered(displayId)).thenReturn(false);
-
- final float result = mServiceConnection.getMagnificationCenterX(displayId);
- assertThat(result, is(centerX));
- verify(mMockFullScreenMagnificationController).register(displayId);
- verify(mMockFullScreenMagnificationController).unregister(displayId);
- }
-
- @Test
public void getMagnificationCenterX_serviceNotBelongCurrentUser_returnZero() {
final int displayId = 1;
final float centerX = 480.0f;
- when(mMockFullScreenMagnificationController.getCenterX(displayId)).thenReturn(centerX);
+ when(mMockMagnificationProcessor.getCenterX(displayId, /* canControlMagnification= */
+ true)).thenReturn(centerX);
when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
final float result = mServiceConnection.getMagnificationCenterX(displayId);
@@ -632,23 +604,11 @@
}
@Test
- public void getMagnificationCenterY_notRegistered_shouldRegisterThenUnregister() {
- final int displayId = 1;
- final float centerY = 640.0f;
- when(mMockFullScreenMagnificationController.getCenterY(displayId)).thenReturn(centerY);
- when(mMockFullScreenMagnificationController.isRegistered(displayId)).thenReturn(false);
-
- final float result = mServiceConnection.getMagnificationCenterY(displayId);
- assertThat(result, is(centerY));
- verify(mMockFullScreenMagnificationController).register(displayId);
- verify(mMockFullScreenMagnificationController).unregister(displayId);
- }
-
- @Test
public void getMagnificationCenterY_serviceNotBelongCurrentUser_returnZero() {
final int displayId = 1;
final float centerY = 640.0f;
- when(mMockFullScreenMagnificationController.getCenterY(displayId)).thenReturn(centerY);
+ when(mMockMagnificationProcessor.getCenterY(displayId, /* canControlMagnification= */
+ true)).thenReturn(centerY);
when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
final float result = mServiceConnection.getMagnificationCenterY(displayId);
@@ -658,7 +618,7 @@
@Test
public void resetMagnification() {
final int displayId = 1;
- when(mMockFullScreenMagnificationController.reset(displayId, true)).thenReturn(true);
+ when(mMockMagnificationProcessor.reset(displayId, true)).thenReturn(true);
final boolean result = mServiceConnection.resetMagnification(displayId, true);
assertThat(result, is(true));
@@ -667,7 +627,7 @@
@Test
public void resetMagnification_cantControlMagnification_returnFalse() {
final int displayId = 1;
- when(mMockFullScreenMagnificationController.reset(displayId, true)).thenReturn(true);
+ when(mMockMagnificationProcessor.reset(displayId, true)).thenReturn(true);
when(mMockSecurityPolicy.canControlMagnification(mServiceConnection)).thenReturn(false);
final boolean result = mServiceConnection.resetMagnification(displayId, true);
@@ -677,7 +637,7 @@
@Test
public void resetMagnification_serviceNotBelongCurrentUser_returnFalse() {
final int displayId = 1;
- when(mMockFullScreenMagnificationController.reset(displayId, true)).thenReturn(true);
+ when(mMockMagnificationProcessor.reset(displayId, true)).thenReturn(true);
when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
final boolean result = mServiceConnection.resetMagnification(displayId, true);
@@ -685,28 +645,12 @@
}
@Test
- public void setMagnificationScaleAndCenter_notRegistered_shouldRegister() {
- final int displayId = 1;
- final float scale = 1.8f;
- final float centerX = 50.5f;
- final float centerY = 100.5f;
- when(mMockFullScreenMagnificationController.setScaleAndCenter(displayId,
- scale, centerX, centerY, true, SERVICE_ID)).thenReturn(true);
- when(mMockFullScreenMagnificationController.isRegistered(displayId)).thenReturn(false);
-
- final boolean result = mServiceConnection.setMagnificationScaleAndCenter(
- displayId, scale, centerX, centerY, true);
- assertThat(result, is(true));
- verify(mMockFullScreenMagnificationController).register(displayId);
- }
-
- @Test
public void setMagnificationScaleAndCenter_cantControlMagnification_returnFalse() {
final int displayId = 1;
final float scale = 1.8f;
final float centerX = 50.5f;
final float centerY = 100.5f;
- when(mMockFullScreenMagnificationController.setScaleAndCenter(displayId,
+ when(mMockMagnificationProcessor.setScaleAndCenter(displayId,
scale, centerX, centerY, true, SERVICE_ID)).thenReturn(true);
when(mMockSecurityPolicy.canControlMagnification(mServiceConnection)).thenReturn(false);
@@ -721,7 +665,7 @@
final float scale = 1.8f;
final float centerX = 50.5f;
final float centerY = 100.5f;
- when(mMockFullScreenMagnificationController.setScaleAndCenter(displayId,
+ when(mMockMagnificationProcessor.setScaleAndCenter(displayId,
scale, centerX, centerY, true, SERVICE_ID)).thenReturn(true);
when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterTest.java
index 554f0a4..464fee2 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterTest.java
@@ -53,9 +53,9 @@
import com.android.server.LocalServices;
import com.android.server.accessibility.gestures.TouchExplorer;
-import com.android.server.accessibility.magnification.FullScreenMagnificationController;
import com.android.server.accessibility.magnification.FullScreenMagnificationGestureHandler;
import com.android.server.accessibility.magnification.MagnificationGestureHandler;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
import com.android.server.accessibility.magnification.WindowMagnificationGestureHandler;
import com.android.server.wm.WindowManagerInternal;
@@ -96,7 +96,7 @@
@Mock private WindowManagerInternal.AccessibilityControllerInternal mMockA11yController;
@Mock private WindowManagerInternal mMockWindowManagerService;
- @Mock private FullScreenMagnificationController mMockFullScreenMagnificationController;
+ @Mock private MagnificationProcessor mMockMagnificationProcessor;
private AccessibilityManagerService mAms;
private AccessibilityInputFilter mA11yInputFilter;
private EventCaptor mCaptor1;
@@ -152,8 +152,7 @@
mA11yInputFilter.onInstalled();
doReturn(mDisplayList).when(mAms).getValidDisplayList();
- doReturn(mMockFullScreenMagnificationController).when(mAms)
- .getFullScreenMagnificationController();
+ doReturn(mMockMagnificationProcessor).when(mAms).getMagnificationProcessor();
}
@After
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
index 432a500..e93e544 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
@@ -45,7 +45,7 @@
import android.testing.DexmakerShareClassLoaderRule;
import android.view.Display;
-import com.android.server.accessibility.magnification.FullScreenMagnificationController;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
import com.android.server.accessibility.test.MessageCapturingHandler;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -91,7 +91,7 @@
@Mock SystemActionPerformer mMockSystemActionPerformer;
@Mock KeyEventDispatcher mMockKeyEventDispatcher;
@Mock
- FullScreenMagnificationController mMockFullScreenMagnificationController;
+ MagnificationProcessor mMockMagnificationProcessor;
@Mock IBinder mMockIBinder;
@Mock IAccessibilityServiceClient mMockServiceClient;
@Mock MotionEventInjector mMockMotionEventInjector;
@@ -102,8 +102,8 @@
public void setup() {
MockitoAnnotations.initMocks(this);
when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mMockKeyEventDispatcher);
- when(mMockSystemSupport.getFullScreenMagnificationController())
- .thenReturn(mMockFullScreenMagnificationController);
+ when(mMockSystemSupport.getMagnificationProcessor())
+ .thenReturn(mMockMagnificationProcessor);
when(mMockSystemSupport.getMotionEventInjectorForDisplayLocked(
Display.DEFAULT_DISPLAY)).thenReturn(mMockMotionEventInjector);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
new file mode 100644
index 0000000..c412b94
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Region;
+
+import com.android.server.accessibility.magnification.FullScreenMagnificationController;
+import com.android.server.accessibility.magnification.MagnificationController;
+import com.android.server.accessibility.magnification.MagnificationProcessor;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+
+/**
+ * Tests for the {@link MagnificationProcessor}
+ */
+public class MagnificationProcessorTest {
+
+ private static final int TEST_DISPLAY = 0;
+
+ private MagnificationProcessor mMagnificationProcessor;
+ @Mock
+ private MagnificationController mMockMagnificationController;
+ @Mock
+ private FullScreenMagnificationController mMockFullScreenMagnificationController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+
+ when(mMockMagnificationController.getFullScreenMagnificationController()).thenReturn(
+ mMockFullScreenMagnificationController);
+ mMagnificationProcessor = new MagnificationProcessor(mMockMagnificationController);
+ }
+
+ @Test
+ public void getScale() {
+ final float result = 2;
+ when(mMockFullScreenMagnificationController.getScale(TEST_DISPLAY)).thenReturn(result);
+
+ float scale = mMagnificationProcessor.getScale(TEST_DISPLAY);
+
+ assertEquals(scale, result, 0);
+ }
+
+ @Test
+ public void getCenterX_canControlMagnification_returnCenterX() {
+ final float result = 200;
+ when(mMockFullScreenMagnificationController.getCenterX(TEST_DISPLAY)).thenReturn(result);
+
+ float centerX = mMagnificationProcessor.getCenterX(
+ TEST_DISPLAY, /* canControlMagnification= */true);
+
+ assertEquals(centerX, result, 0);
+ }
+
+ @Test
+ public void getCenterY_canControlMagnification_returnCenterY() {
+ final float result = 300;
+ when(mMockFullScreenMagnificationController.getCenterY(TEST_DISPLAY)).thenReturn(result);
+
+ float centerY = mMagnificationProcessor.getCenterY(
+ TEST_DISPLAY, /* canControlMagnification= */false);
+
+ assertEquals(centerY, result, 0);
+ }
+
+ @Test
+ public void getMagnificationRegion_canControlMagnification_returnRegion() {
+ final Region region = new Region(10, 20, 100, 200);
+ mMagnificationProcessor.getMagnificationRegion(TEST_DISPLAY,
+ region, /* canControlMagnification= */true);
+
+ verify(mMockFullScreenMagnificationController).getMagnificationRegion(eq(TEST_DISPLAY),
+ eq(region));
+ }
+
+ @Test
+ public void getMagnificationRegion_notRegistered_shouldRegisterThenUnregister() {
+ final Region region = new Region(10, 20, 100, 200);
+ doAnswer((invocation) -> {
+ ((Region) invocation.getArguments()[1]).set(region);
+ return null;
+ }).when(mMockFullScreenMagnificationController).getMagnificationRegion(eq(TEST_DISPLAY),
+ any());
+ when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
+
+ final Region result = new Region();
+ mMagnificationProcessor.getMagnificationRegion(TEST_DISPLAY,
+ result, /* canControlMagnification= */true);
+ assertEquals(region, result);
+ verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
+ verify(mMockFullScreenMagnificationController).unregister(TEST_DISPLAY);
+ }
+
+ @Test
+ public void getMagnificationCenterX_notRegistered_shouldRegisterThenUnregister() {
+ final float centerX = 480.0f;
+ when(mMockFullScreenMagnificationController.getCenterX(TEST_DISPLAY)).thenReturn(centerX);
+ when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
+
+ final float result = mMagnificationProcessor.getCenterX(
+ TEST_DISPLAY, /* canControlMagnification= */ true);
+ assertEquals(centerX, result, 0);
+ verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
+ verify(mMockFullScreenMagnificationController).unregister(TEST_DISPLAY);
+ }
+
+ @Test
+ public void getMagnificationCenterY_notRegistered_shouldRegisterThenUnregister() {
+ final float centerY = 640.0f;
+ when(mMockFullScreenMagnificationController.getCenterY(TEST_DISPLAY)).thenReturn(centerY);
+ when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
+
+ final float result = mMagnificationProcessor.getCenterY(
+ TEST_DISPLAY, /* canControlMagnification= */ true);
+ assertEquals(centerY, result, 0);
+ verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
+ verify(mMockFullScreenMagnificationController).unregister(TEST_DISPLAY);
+ }
+
+ @Test
+ public void setMagnificationScaleAndCenter_notRegistered_shouldRegister() {
+ final int serviceId = 42;
+ final float scale = 1.8f;
+ final float centerX = 50.5f;
+ final float centerY = 100.5f;
+ when(mMockFullScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY,
+ scale, centerX, centerY, true, serviceId)).thenReturn(true);
+ when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
+
+ final boolean result = mMagnificationProcessor.setScaleAndCenter(
+ TEST_DISPLAY, scale, centerX, centerY, true, serviceId);
+ assertTrue(result);
+ verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
index 29ff9f4..b793482 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
@@ -338,7 +338,7 @@
when(pkg.getBaseApkPath()).thenReturn(apkPath);
when(pkg.getLongVersionCode()).thenReturn((long) versionCode);
when(pkg.getOverlayTarget()).thenReturn(targetPackageName);
- when(pkg.getOverlayTargetName()).thenReturn(targetOverlayableName);
+ when(pkg.getOverlayTargetOverlayableName()).thenReturn(targetOverlayableName);
when(pkg.getOverlayCategory()).thenReturn("Fake-category-" + targetPackageName);
return pkg;
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 9bc20a7..9f12438 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -762,7 +762,7 @@
ParsingPackage overlay = pkg("com.some.package.overlay")
.setOverlay(true)
.setOverlayTarget(target.getPackageName())
- .setOverlayTargetName("overlayableName");
+ .setOverlayTargetOverlayableName("overlayableName");
ParsingPackage actor = pkg("com.some.package.actor");
final AppsFilter appsFilter = new AppsFilter(
@@ -787,7 +787,7 @@
if (overlay.getPackageName().equals(pkg.getPackageName())) {
Map<String, Set<String>> map = new ArrayMap<>();
Set<String> set = new ArraySet<>();
- set.add(overlay.getOverlayTargetName());
+ set.add(overlay.getOverlayTargetOverlayableName());
map.put(overlay.getOverlayTarget(), set);
return map;
}
@@ -847,7 +847,7 @@
ParsingPackage overlay = pkg("com.some.package.overlay")
.setOverlay(true)
.setOverlayTarget(target.getPackageName())
- .setOverlayTargetName("overlayableName");
+ .setOverlayTargetOverlayableName("overlayableName");
ParsingPackage actorOne = pkg("com.some.package.actor.one");
ParsingPackage actorTwo = pkg("com.some.package.actor.two");
@@ -874,7 +874,7 @@
if (overlay.getPackageName().equals(pkg.getPackageName())) {
Map<String, Set<String>> map = new ArrayMap<>();
Set<String> set = new ArraySet<>();
- set.add(overlay.getOverlayTargetName());
+ set.add(overlay.getOverlayTargetOverlayableName());
map.put(overlay.getOverlayTarget(), set);
return map;
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java b/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java
index 0f1b14b..0247590 100644
--- a/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java
@@ -35,7 +35,7 @@
import android.content.pm.parsing.ParsingPackageUtils;
import android.os.Build;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
import org.junit.After;
import org.junit.Before;
@@ -44,13 +44,13 @@
public class CompatibilityModeTest {
private boolean mCompatibilityModeEnabled;;
- private AndroidPackage mMockAndroidPackage;
+ private PackageImpl mMockAndroidPackage;
private PackageUserState mMockUserState;
@Before
public void setUp() {
mCompatibilityModeEnabled = ParsingPackageUtils.sCompatibilityModeEnabled;
- mMockAndroidPackage = mock(AndroidPackage.class);
+ mMockAndroidPackage = mock(PackageImpl.class);
mMockUserState = mock(PackageUserState.class);
mMockUserState.installed = true;
when(mMockUserState.isAvailable(anyInt())).thenReturn(true);
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 45e2ab4..76741c4 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -955,7 +955,6 @@
assertSame(origPkgSetting.signatures, testPkgSetting.signatures);
assertThat(origPkgSetting.signatures, is(testPkgSetting.signatures));
assertThat(origPkgSetting.timeStamp, is(testPkgSetting.timeStamp));
- assertThat(origPkgSetting.uidError, is(testPkgSetting.uidError));
assertNotSame(origPkgSetting.getUserState(), is(testPkgSetting.getUserState()));
// No equals() method for SparseArray object
// assertThat(origPkgSetting.getUserState(), is(testPkgSetting.getUserState()));
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 38b98ca..0cbac87 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -56,6 +56,7 @@
import android.content.pm.parsing.component.ParsedUsesPermission;
import android.os.Bundle;
import android.os.Parcel;
+import android.os.Parcelable;
import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
@@ -71,6 +72,7 @@
import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.TestPackageParser2;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
@@ -174,7 +176,7 @@
true /* useCaches */).hideAsFinal();
Parcel p = Parcel.obtain();
- pkg.writeToParcel(p, 0 /* flags */);
+ ((Parcelable) pkg).writeToParcel(p, 0 /* flags */);
p.setDataPosition(0);
ParsedPackage deserialized = new PackageImpl(p);
@@ -191,7 +193,7 @@
setKnownFields(pkg);
Parcel p = Parcel.obtain();
- pkg.writeToParcel(p, 0 /* flags */);
+ ((Parcelable) pkg).writeToParcel(p, 0 /* flags */);
p.setDataPosition(0);
ParsedPackage deserialized = new PackageImpl(p);
@@ -204,7 +206,7 @@
setKnownFields(pkg);
Parcel p = Parcel.obtain();
- pkg.writeToParcel(p, 0 /* flags */);
+ ((Parcelable) pkg).writeToParcel(p, 0 /* flags */);
p.setDataPosition(0);
ParsingPackage deserialized = new PackageImpl(p);
@@ -609,10 +611,10 @@
private static PackageSetting mockPkgSetting(AndroidPackage pkg) {
return new PackageSettingBuilder()
.setName(pkg.getPackageName())
- .setRealName(pkg.getRealPackage())
+ .setRealName(pkg.getManifestPackageName())
.setCodePath(pkg.getPath())
- .setPrimaryCpuAbiString(pkg.getPrimaryCpuAbi())
- .setSecondaryCpuAbiString(pkg.getSecondaryCpuAbi())
+ .setPrimaryCpuAbiString(AndroidPackageUtils.getRawPrimaryCpuAbi(pkg))
+ .setSecondaryCpuAbiString(AndroidPackageUtils.getRawSecondaryCpuAbi(pkg))
.setPVersionCode(pkg.getLongVersionCode())
.setPkgFlags(PackageInfoUtils.appInfoFlags(pkg, null))
.setPrivateFlags(PackageInfoUtils.appInfoPrivateFlags(pkg, null))
@@ -625,7 +627,7 @@
public static void assertPackagesEqual(AndroidPackage a, AndroidPackage b) {
assertEquals(a.getBaseRevisionCode(), b.getBaseRevisionCode());
assertEquals(a.isBaseHardwareAccelerated(), b.isBaseHardwareAccelerated());
- assertEquals(a.getVersionCode(), b.getVersionCode());
+ assertEquals(a.getLongVersionCode(), b.getLongVersionCode());
assertEquals(a.getSharedUserLabel(), b.getSharedUserLabel());
assertEquals(a.getInstallLocation(), b.getInstallLocation());
assertEquals(a.isCoreApp(), b.isCoreApp());
@@ -700,7 +702,7 @@
assertEquals(a.getUsesLibraries(), b.getUsesLibraries());
assertEquals(a.getUsesOptionalLibraries(), b.getUsesOptionalLibraries());
assertEquals(a.getOriginalPackages(), b.getOriginalPackages());
- assertEquals(a.getRealPackage(), b.getRealPackage());
+ assertEquals(a.getManifestPackageName(), b.getManifestPackageName());
assertEquals(a.getAdoptPermissions(), b.getAdoptPermissions());
assertBundleApproximateEquals(a.getMetaData(), b.getMetaData());
assertEquals(a.getVersionName(), b.getVersionName());
@@ -710,7 +712,7 @@
assertEquals(a.getRestrictedAccountType(), b.getRestrictedAccountType());
assertEquals(a.getRequiredAccountType(), b.getRequiredAccountType());
assertEquals(a.getOverlayTarget(), b.getOverlayTarget());
- assertEquals(a.getOverlayTargetName(), b.getOverlayTargetName());
+ assertEquals(a.getOverlayTargetOverlayableName(), b.getOverlayTargetOverlayableName());
assertEquals(a.getOverlayCategory(), b.getOverlayCategory());
assertEquals(a.getOverlayPriority(), b.getOverlayPriority());
assertEquals(a.isOverlayIsStatic(), b.isOverlayIsStatic());
@@ -928,7 +930,6 @@
.addUsesLibrary("foo11")
.addUsesOptionalLibrary("foo12")
.addOriginalPackage("foo14")
- .setRealPackage("foo15")
.addAdoptPermission("foo16")
.setMetaData(bundle)
.setVersionName("foo17")
@@ -953,7 +954,7 @@
.setCompileSdkVersion(100)
.setOverlayCategory("foo24")
.setOverlayIsStatic(true)
- .setOverlayTargetName("foo26")
+ .setOverlayTargetOverlayableName("foo26")
.setVisibleToInstantApps(true)
.setSplitHasCode(0, true)
.hideAsParsed())
diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
index 77b9fd3..5de0c2b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
@@ -176,7 +176,7 @@
final ScanRequest scanRequestNoRealPkg =
createBasicScanRequestBuilder(
createBasicPackage(DUMMY_PACKAGE_NAME)
- .setRealPackage("com.package.real"))
+ .addOriginalPackage("com.package.real"))
.build();
final ScanResult scanResultNoReal = executeScan(scanRequestNoRealPkg);
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
index e021d2a..2a7a2ff 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
@@ -140,7 +140,7 @@
Collection<String> apkToDexMetadataList =
AndroidPackageUtils.getPackageDexMetadata(pkg).values();
String packageName = pkg.getPackageName();
- long versionCode = pkg.toAppInfoWithoutState().longVersionCode;
+ long versionCode = pkg.getLongVersionCode();
final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
for (String dexMetadata : apkToDexMetadataList) {
final ParseResult result = DexMetadataHelper.validateDexMetadataFile(
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt
index fb82b1d..51c268e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt
@@ -105,7 +105,6 @@
lateinit var param: Param<Any>
@Test
- @Ignore("b/155935153")
fun fieldPresence() {
oldPackages.asSequence().zip(newPackages.asSequence())
.forEach { (old, new) ->
@@ -128,7 +127,6 @@
}
@Test
- @Ignore("b/155935153")
fun fieldAbsence() {
newPackages.forEach {
val newWithoutFlag = param.newPkgFunction(it, 0)
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
index b7eddb3..ae07f8e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
@@ -183,6 +183,7 @@
this.appId = aPkg.uid
whenever(pkgState) { PackageStateUnserialized() }
whenever(readUserState(anyInt())) { dummyUserState }
+ whenever(categoryOverride) { ApplicationInfo.CATEGORY_UNDEFINED }
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index b95d56b..764f63d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -43,13 +43,17 @@
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.IApplicationThread;
import android.app.PictureInPictureParams;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.EnterPipRequestedItem;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.Binder;
import android.os.IBinder;
+import android.os.LocaleList;
import android.os.PowerManager;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
@@ -61,6 +65,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
import org.mockito.MockitoSession;
import java.util.ArrayList;
@@ -80,6 +85,9 @@
private final ArgumentCaptor<ClientTransaction> mClientTransactionCaptor =
ArgumentCaptor.forClass(ClientTransaction.class);
+ private static final String DEFAULT_PACKAGE_NAME = "my.application.package";
+ private static final int DEFAULT_USER_ID = 100;
+
@Before
public void setUp() throws Exception {
setBooted(mAtm);
@@ -301,6 +309,15 @@
// The top app should not change while sleeping.
assertEquals(topActivity.app, mAtm.mInternal.getTopApp());
+ mAtm.startLaunchPowerMode(ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY
+ | ActivityTaskManagerService.POWER_MODE_REASON_UNKNOWN_VISIBILITY);
+ assertEquals(ActivityManager.PROCESS_STATE_TOP, mAtm.mInternal.getTopProcessState());
+ // Because there is no unknown visibility record, the state will be restored if other
+ // reasons are all done.
+ mAtm.endLaunchPowerMode(ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY);
+ assertEquals(ActivityManager.PROCESS_STATE_TOP_SLEEPING,
+ mAtm.mInternal.getTopProcessState());
+
// If all activities are stopped, the sleep wake lock must be released.
final Task topRootTask = topActivity.getRootTask();
doReturn(true).when(rootHomeTask).goToSleepIfPossible(anyBoolean());
@@ -480,5 +497,269 @@
assertTrue(activity.supportsMultiWindow());
assertTrue(task.supportsMultiWindow());
}
+
+ @Test
+ public void testPackageConfigUpdate_locales_successfullyApplied() {
+ Configuration config = mAtm.getGlobalConfiguration();
+ config.setLocales(LocaleList.forLanguageTags("en-XC"));
+ mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
+ mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
+
+ ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
+ mAtm.mInternal.createPackageConfigurationUpdater();
+ packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB")).commit();
+
+ WindowProcessController wpcAfterConfigChange = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+
+ assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
+ wpcAfterConfigChange.getConfiguration().getLocales());
+ assertFalse(wpcAfterConfigChange.getConfiguration().isNightModeActive());
+ }
+
+ @Test
+ public void testPackageConfigUpdate_nightMode_successfullyApplied() {
+ Configuration config = mAtm.getGlobalConfiguration();
+ config.setLocales(LocaleList.forLanguageTags("en-XC"));
+ mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
+ mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
+ ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
+ mAtm.mInternal.createPackageConfigurationUpdater();
+
+ packageConfigUpdater.setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
+
+ WindowProcessController wpcAfterConfigChange = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ assertTrue(wpcAfterConfigChange.getConfiguration().isNightModeActive());
+ assertEquals(LocaleList.forLanguageTags("en-XC"),
+ wpcAfterConfigChange.getConfiguration().getLocales());
+ }
+
+ @Test
+ public void testPackageConfigUpdate_multipleLocaleUpdates_successfullyApplied() {
+ Configuration config = mAtm.getGlobalConfiguration();
+ config.setLocales(LocaleList.forLanguageTags("en-XC"));
+ mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
+ WindowProcessController wpc = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ mAtm.mProcessMap.put(Binder.getCallingPid(), wpc);
+ ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
+ mAtm.mInternal.createPackageConfigurationUpdater();
+
+ packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
+ .setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
+
+ WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
+ wpcAfterConfigChange1.getConfiguration().getLocales());
+ assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
+ assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
+ wpc.getConfiguration().getLocales());
+
+ packageConfigUpdater.setLocales(LocaleList.forLanguageTags("ja-XC,en-XC")).commit();
+
+ WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+
+ assertEquals(LocaleList.forLanguageTags("ja-XC,en-XC"),
+ wpcAfterConfigChange2.getConfiguration().getLocales());
+ assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
+ assertEquals(LocaleList.forLanguageTags("ja-XC,en-XC"),
+ wpc.getConfiguration().getLocales());
+ }
+
+ @Test
+ public void testPackageConfigUpdate_multipleNightModeUpdates_successfullyApplied() {
+ Configuration config = mAtm.getGlobalConfiguration();
+ config.setLocales(LocaleList.forLanguageTags("en-XC"));
+ mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
+ mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
+ ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
+ mAtm.mInternal.createPackageConfigurationUpdater();
+
+ packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
+ .setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
+
+ WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
+ wpcAfterConfigChange1.getConfiguration().getLocales());
+ assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
+
+ packageConfigUpdater.setNightMode(Configuration.UI_MODE_NIGHT_NO).commit();
+
+ WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
+ wpcAfterConfigChange2.getConfiguration().getLocales());
+ assertFalse(wpcAfterConfigChange2.getConfiguration().isNightModeActive());
+ }
+
+ @Test
+ public void testPackageConfigUpdate_onPackageUninstall_configShouldNotApply() {
+ Configuration config = mAtm.getGlobalConfiguration();
+ config.setLocales(LocaleList.forLanguageTags("en-XC"));
+ mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
+ mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
+ ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
+ mAtm.mInternal.createPackageConfigurationUpdater();
+
+ packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
+ .setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
+
+ WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
+ wpcAfterConfigChange1.getConfiguration().getLocales());
+ assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
+
+ mAtm.mInternal.onPackageUninstalled(DEFAULT_PACKAGE_NAME);
+
+ WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ assertEquals(LocaleList.forLanguageTags("en-XC"),
+ wpcAfterConfigChange2.getConfiguration().getLocales());
+ assertFalse(wpcAfterConfigChange2.getConfiguration().isNightModeActive());
+ }
+
+ @Test
+ public void testPackageConfigUpdate_LocalesEmptyAndNightModeUndefined_configShouldNotApply() {
+ Configuration config = mAtm.getGlobalConfiguration();
+ config.setLocales(LocaleList.forLanguageTags("en-XC"));
+ mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
+ WindowProcessController wpc = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ mAtm.mProcessMap.put(Binder.getCallingPid(), wpc);
+ ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
+ mAtm.mInternal.createPackageConfigurationUpdater();
+
+ packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
+ .setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
+ WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+
+ assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
+ wpcAfterConfigChange1.getConfiguration().getLocales());
+ assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
+ assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
+ wpc.getConfiguration().getLocales());
+
+ packageConfigUpdater.setLocales(LocaleList.getEmptyLocaleList())
+ .setNightMode(Configuration.UI_MODE_NIGHT_UNDEFINED).commit();
+
+ WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ assertEquals(LocaleList.forLanguageTags("en-XC"),
+ wpcAfterConfigChange2.getConfiguration().getLocales());
+ assertFalse(wpcAfterConfigChange2.getConfiguration().isNightModeActive());
+ assertEquals(LocaleList.forLanguageTags("en-XC"),
+ wpc.getConfiguration().getLocales());
+ }
+
+ @Test
+ public void testPackageConfigUpdate_WhenUserRemoved_configShouldNotApply() {
+ Configuration config = mAtm.getGlobalConfiguration();
+ config.setLocales(LocaleList.forLanguageTags("en-XC"));
+ mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
+ mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
+
+ ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
+ mAtm.mInternal.createPackageConfigurationUpdater();
+
+ packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
+ .setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
+
+ WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
+ wpcAfterConfigChange1.getConfiguration().getLocales());
+ assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
+
+ mAtm.mInternal.removeUser(DEFAULT_USER_ID);
+
+ WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ assertEquals(LocaleList.forLanguageTags("en-XC"),
+ wpcAfterConfigChange2.getConfiguration().getLocales());
+ assertFalse(wpcAfterConfigChange2.getConfiguration().isNightModeActive());
+ }
+
+ @Test
+ public void testPackageConfigUpdate_setLocaleListToEmpty_doesNotOverlayLocaleListInWpc() {
+ Configuration config = mAtm.getGlobalConfiguration();
+ config.setLocales(LocaleList.forLanguageTags("en-XC"));
+ mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
+ mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
+
+ ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
+ mAtm.mInternal.createPackageConfigurationUpdater();
+
+ packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
+ .setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
+
+ WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
+ wpcAfterConfigChange1.getConfiguration().getLocales());
+ assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
+
+ packageConfigUpdater.setLocales(LocaleList.getEmptyLocaleList()).commit();
+
+ WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ assertEquals(LocaleList.forLanguageTags("en-XC"),
+ wpcAfterConfigChange2.getConfiguration().getLocales());
+ assertTrue(wpcAfterConfigChange2.getConfiguration().isNightModeActive());
+ }
+
+ @Test
+ public void testPackageConfigUpdate_resetNightMode_doesNotOverrideNightModeInWpc() {
+ Configuration config = mAtm.getGlobalConfiguration();
+ config.setLocales(LocaleList.forLanguageTags("en-XC"));
+ mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
+ mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
+
+ ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
+ mAtm.mInternal.createPackageConfigurationUpdater();
+
+ packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
+ .setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
+
+ WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
+ wpcAfterConfigChange1.getConfiguration().getLocales());
+ assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
+
+ packageConfigUpdater.setNightMode(Configuration.UI_MODE_NIGHT_UNDEFINED).commit();
+
+ WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
+ DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+ assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
+ wpcAfterConfigChange2.getConfiguration().getLocales());
+ assertFalse(wpcAfterConfigChange2.getConfiguration().isNightModeActive());
+ }
+
+ private WindowProcessController createWindowProcessController(String packageName,
+ int userId) {
+ WindowProcessListener mMockListener = Mockito.mock(WindowProcessListener.class);
+ ApplicationInfo info = mock(ApplicationInfo.class);
+ info.packageName = packageName;
+ WindowProcessController wpc = new WindowProcessController(
+ mAtm, info, packageName, 0, userId, null, mMockListener);
+ wpc.setThread(mock(IApplicationThread.class));
+ return wpc;
+ }
+
}
+
+
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
index 609d159..78946fc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
@@ -62,7 +62,8 @@
mSurfaces = new SurfaceControlMocker();
mLetterbox = new Letterbox(mSurfaces, StubTransaction::new,
() -> mAreCornersRounded, () -> Color.valueOf(mColor),
- () -> mHasWallpaperBackground, () -> mBlurRadius, () -> mDarkScrimAlpha);
+ () -> mHasWallpaperBackground, () -> mBlurRadius, () -> mDarkScrimAlpha,
+ /* doubleTapCallback= */ () -> {});
mTransaction = spy(StubTransaction.class);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 6407c92..348472a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -1171,6 +1171,7 @@
final WindowState w = addWindowToActivity(mActivity);
// Compute the frames of the window and invoke {@link ActivityRecord#layoutLetterbox}.
mActivity.mRootWindowContainer.performSurfacePlacement();
+ mActivity.layoutLetterbox(null);
// The letterbox insets should be [450, 0 - 250, 0].
assertEquals(new Rect(mActivity.getBounds().left, 0, dh - mActivity.getBounds().right, 0),
mActivity.getLetterboxInsets());
@@ -1832,6 +1833,9 @@
}
private void assertLetterboxSurfacesDrawnBetweenActivityAndParentBounds(Rect parentBounds) {
+ // Ensure Letterbox is updated.
+ mActivity.layoutLetterbox(null);
+
// Letterbox should fill the gap between the parent bounds and the letterboxed activity.
final Rect letterboxedBounds = new Rect(mActivity.getBounds());
assertTrue(parentBounds.contains(letterboxedBounds));
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 67e8c87..ce568f1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -898,7 +898,8 @@
/**
* Test that root activity index is reported correctly when looking for the 'effective root' in
- * case when bottom activities are relinquishing task identity or finishing.
+ * case when bottom activity is finishing. Ignore the relinquishing task identity if it's not a
+ * system activity even with the FLAG_RELINQUISH_TASK_IDENTITY.
*/
@Test
public void testFindRootIndex_effectiveRoot_finishingAndRelinquishing() {
@@ -912,7 +913,7 @@
new ActivityBuilder(mAtm).setTask(task).build();
assertEquals("The first non-finishing activity and non-relinquishing task identity "
- + "must be reported.", task.getChildAt(2), task.getRootActivity(
+ + "must be reported.", task.getChildAt(0), task.getRootActivity(
false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
}
@@ -932,8 +933,8 @@
}
/**
- * Test that the topmost activity index is reported correctly when looking for the
- * 'effective root' for the case when all activities have relinquishTaskIdentity set.
+ * Test that the root activity index is reported correctly when looking for the
+ * 'effective root' for the case when all non-system activities have relinquishTaskIdentity set.
*/
@Test
public void testFindRootIndex_effectiveRoot_relinquishingMultipleActivities() {
@@ -944,9 +945,9 @@
final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build();
activity1.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
- assertEquals("The topmost activity in the task must be reported.",
- task.getChildAt(task.getChildCount() - 1), task.getRootActivity(
- false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
+ assertEquals("The topmost activity in the task must be reported.", task.getChildAt(0),
+ task.getRootActivity(false /*ignoreRelinquishIdentity*/,
+ true /*setToBottomIfNone*/));
}
/** Test that bottom-most activity is reported in {@link Task#getRootActivity()}. */
@@ -1084,8 +1085,8 @@
}
/**
- * Test {@link ActivityRecord#getTaskForActivityLocked(IBinder, boolean)} with activity that
- * relinquishes task identity.
+ * Test {@link ActivityRecord#getTaskForActivityLocked(IBinder, boolean)} with non-system
+ * activity that relinquishes task identity.
*/
@Test
public void testGetTaskForActivity_onlyRoot_relinquishTaskIdentity() {
@@ -1100,7 +1101,7 @@
assertEquals(task.mTaskId,
ActivityRecord.getTaskForActivityLocked(activity0.appToken, true /* onlyRoot */));
- assertEquals(task.mTaskId,
+ assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID,
ActivityRecord.getTaskForActivityLocked(activity1.appToken, true /* onlyRoot */));
assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID,
ActivityRecord.getTaskForActivityLocked(activity2.appToken, true /* onlyRoot */));
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index d3f2d14..c56b614 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -34,6 +34,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -49,6 +50,7 @@
import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.LocaleList;
import android.platform.test.annotations.Presubmit;
import org.junit.Before;
@@ -371,8 +373,9 @@
public void testTopActivityUiModeChangeScheduleConfigChange() {
final ActivityRecord activity = createActivityRecord(mWpc);
activity.mVisibleRequested = true;
- doReturn(true).when(activity).setOverrideNightMode(anyInt());
- mWpc.updateNightModeForAllActivities(Configuration.UI_MODE_NIGHT_YES);
+ doReturn(true).when(activity).applyAppSpecificConfig(anyInt(), any());
+ mWpc.updateAppSpecificSettingsForAllActivities(Configuration.UI_MODE_NIGHT_YES,
+ LocaleList.forLanguageTags("en-XA"));
verify(activity).ensureActivityConfiguration(anyInt(), anyBoolean());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 454ecd7..1f6065f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -223,6 +223,10 @@
// {@link com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier},
// may be set on some device form factors.
mAtm.mWindowManager.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(0.5f);
+ // Ensure letterbox reachability treatment isn't overridden on any device target.
+ // {@link com.android.internal.R.bool.config_letterboxIsReachabilityEnabled},
+ // may be set on some device form factors.
+ mAtm.mWindowManager.mLetterboxConfiguration.setIsReachabilityEnabled(false);
checkDeviceSpecificOverridesNotApplied();
}
@@ -230,12 +234,9 @@
@After
public void tearDown() throws Exception {
// Revert back to device overrides.
- mAtm.mWindowManager.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(
- mContext.getResources().getFloat(
- com.android.internal.R.dimen.config_fixedOrientationLetterboxAspectRatio));
- mAtm.mWindowManager.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(
- mContext.getResources().getFloat(
- com.android.internal.R.dimen.config_letterboxHorizontalPositionMultiplier));
+ mAtm.mWindowManager.mLetterboxConfiguration.resetFixedOrientationLetterboxAspectRatio();
+ mAtm.mWindowManager.mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier();
+ mAtm.mWindowManager.mLetterboxConfiguration.resetIsReachabilityEnabled();
}
/**
diff --git a/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
index 49ea9df..0c65cc4 100644
--- a/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
+++ b/services/usb/java/com/android/server/usb/UsbUserPermissionManager.java
@@ -45,6 +45,7 @@
import android.service.usb.UsbUserPermissionsManagerProto;
import android.util.ArrayMap;
import android.util.AtomicFile;
+import android.util.EventLog;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.TypedXmlPullParser;
@@ -74,6 +75,8 @@
private static final String TAG = UsbUserPermissionManager.class.getSimpleName();
private static final boolean DEBUG = false;
+ private static final int SNET_EVENT_LOG_ID = 0x534e4554;
+
@GuardedBy("mLock")
/** Mapping of USB device name to list of UIDs with permissions for the device
* Each entry lasts until device is disconnected*/
@@ -691,6 +694,7 @@
if (aInfo.uid != uid) {
Slog.w(TAG, "package " + packageName
+ " does not match caller's uid " + uid);
+ EventLog.writeEvent(SNET_EVENT_LOG_ID, "180104273", -1, "");
throw new IllegalArgumentException("package " + packageName
+ " not found");
}
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 4df8a4b..f248fd5 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -8,10 +8,10 @@
tgunn@google.com
jminjie@google.com
shuoq@google.com
-nazaninb@google.com
sarahchin@google.com
xiaotonj@google.com
huiwang@google.com
jayachandranc@google.com
chinmayd@google.com
amruthr@google.com
+sasindran@google.com
diff --git a/tests/componentalias/AndroidManifest_service_aliases.xml b/tests/componentalias/AndroidManifest_service_aliases.xml
index 28ac2a5..8c1ced6c 100644
--- a/tests/componentalias/AndroidManifest_service_aliases.xml
+++ b/tests/componentalias/AndroidManifest_service_aliases.xml
@@ -46,5 +46,36 @@
<intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
<intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_04" /></intent-filter>
</service>
+
+ <receiver android:name=".b.Alias00" android:exported="true" android:enabled="true" >
+ <meta-data android:name="alias_target" android:value="android.content.componentalias.tests/android.content.componentalias.tests.b.Target00" />
+ <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+ <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_00" /></intent-filter>
+ <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+ </receiver>
+ <receiver android:name=".b.Alias01" android:exported="true" android:enabled="true" >
+ <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.sub1/android.content.componentalias.tests.b.Target01" />
+ <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+ <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_01" /></intent-filter>
+ <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+ </receiver>
+ <receiver android:name=".b.Alias02" android:exported="true" android:enabled="true" >
+ <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.sub2/android.content.componentalias.tests.b.Target02" />
+ <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+ <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_02" /></intent-filter>
+ <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+ </receiver>
+ <receiver android:name=".b.Alias03" android:exported="true" android:enabled="true" >
+ <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.sub1/android.content.componentalias.tests.b.Target03" />
+ <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+ <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_03" /></intent-filter>
+ <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+ </receiver>
+ <receiver android:name=".b.Alias04" android:exported="true" android:enabled="true" >
+ <meta-data android:name="alias_target" android:value="android.content.componentalias.tests.sub2/android.content.componentalias.tests.b.Target04" />
+ <intent-filter><action android:name="android.intent.action.EXPERIMENTAL_IS_ALIAS" /></intent-filter>
+ <intent-filter><action android:name="android.content.componentalias.tests.IS_ALIAS_04" /></intent-filter>
+ <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+ </receiver>
</application>
</manifest>
diff --git a/tests/componentalias/AndroidManifest_service_targets.xml b/tests/componentalias/AndroidManifest_service_targets.xml
index 6e7228c..c4bcd78 100644
--- a/tests/componentalias/AndroidManifest_service_targets.xml
+++ b/tests/componentalias/AndroidManifest_service_targets.xml
@@ -27,5 +27,21 @@
</service>
<service android:name=".s.Target04" android:exported="true" android:enabled="true" >
</service>
+
+ <receiver android:name=".b.Target00" android:exported="true" android:enabled="true" >
+ <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+ </receiver>
+ <receiver android:name=".b.Target01" android:exported="true" android:enabled="true" >
+ <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+ </receiver>
+ <receiver android:name=".b.Target02" android:exported="true" android:enabled="true" >
+ <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+ </receiver>
+ <receiver android:name=".b.Target03" android:exported="true" android:enabled="true" >
+ <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+ </receiver>
+ <receiver android:name=".b.Target04" android:exported="true" android:enabled="true" >
+ <intent-filter><action android:name="ACTION_BROADCAST" /></intent-filter>
+ </receiver>
</application>
</manifest>
diff --git a/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java b/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java
new file mode 100644
index 0000000..a62d9eb
--- /dev/null
+++ b/tests/componentalias/src/android/content/componentalias/tests/BaseComponentAliasTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.componentalias.tests;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.provider.DeviceConfig;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.DeviceConfigStateHelper;
+import com.android.compatibility.common.util.ShellUtils;
+import com.android.compatibility.common.util.TestUtils;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+
+import java.util.function.Consumer;
+
+public class BaseComponentAliasTest {
+ protected static final Context sContext = InstrumentationRegistry.getTargetContext();
+
+ protected static final DeviceConfigStateHelper sDeviceConfig = new DeviceConfigStateHelper(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER);
+ @Before
+ public void enableComponentAlias() throws Exception {
+ sDeviceConfig.set("component_alias_overrides", "");
+ sDeviceConfig.set("enable_experimental_component_alias", "true");
+
+ // Device config propagation happens on a handler, so we need to wait for AM to
+ // actually set it.
+ TestUtils.waitUntil("Wait until component alias is actually enabled", () -> {
+ return ShellUtils.runShellCommand("dumpsys activity component-alias")
+ .indexOf("Enabled: true") > 0;
+ });
+ }
+
+ @AfterClass
+ public static void restoreDeviceConfig() throws Exception {
+ sDeviceConfig.close();
+ }
+
+ protected static void log(String message) {
+ Log.i(ComponentAliasTestCommon.TAG, "[" + sContext.getPackageName() + "] " + message);
+ }
+
+ /**
+ * Defines a test target.
+ */
+ public static class Combo {
+ public final ComponentName alias;
+ public final ComponentName target;
+ public final String action;
+
+ public Combo(ComponentName alias, ComponentName target, String action) {
+ this.alias = alias;
+ this.target = target;
+ this.action = action;
+ }
+
+ @Override
+ public String toString() {
+ return "Combo{"
+ + "alias=" + toString(alias)
+ + ", target=" + toString(target)
+ + ", action='" + action + '\''
+ + '}';
+ }
+
+ private static String toString(ComponentName cn) {
+ return cn == null ? "[null]" : cn.flattenToShortString();
+ }
+
+ public void apply(Consumer<Combo> callback) {
+ log("Testing for: " + this);
+ callback.accept(this);
+ }
+ }
+}
diff --git a/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasBroadcastTest.java b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasBroadcastTest.java
new file mode 100644
index 0000000..eab0a6c
--- /dev/null
+++ b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasBroadcastTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.componentalias.tests;
+
+import static android.content.componentalias.tests.ComponentAliasTestCommon.MAIN_PACKAGE;
+import static android.content.componentalias.tests.ComponentAliasTestCommon.TAG;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ComponentName;
+import android.content.Intent;
+
+import com.android.compatibility.common.util.BroadcastMessenger.Receiver;
+
+import org.junit.Test;
+
+import java.util.function.Consumer;
+
+public class ComponentAliasBroadcastTest extends BaseComponentAliasTest {
+ private void forEachCombo(Consumer<Combo> callback) {
+ new Combo(
+ new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".b.Alias00"),
+ new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".b.Target00"),
+ MAIN_PACKAGE + ".IS_ALIAS_00").apply(callback);
+
+ // TODO: This still don't pass -- fix it. But there seems to be an issue with
+ // `am instrument`, so need to fix that first...
+// new Combo(
+// new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".b.Alias01"),
+// new ComponentName(SUB1_PACKAGE, MAIN_PACKAGE + ".b.Target01"),
+// MAIN_PACKAGE + ".IS_ALIAS_01").apply(callback);
+// new Combo(
+// new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".b.Alias02"),
+// new ComponentName(SUB2_PACKAGE, MAIN_PACKAGE + ".b.Target02"),
+// MAIN_PACKAGE + ".IS_ALIAS_02").apply(callback);
+ }
+
+ @Test
+ public void testBroadcast_explicitComponentName() {
+ forEachCombo((c) -> {
+ Intent i = new Intent().setComponent(c.alias);
+ i.setAction("ACTION_BROADCAST");
+ ComponentAliasMessage m;
+
+ try (Receiver<ComponentAliasMessage> receiver = new Receiver<>(sContext, TAG)) {
+ log("Sending: " + i);
+ sContext.sendBroadcast(i);
+
+ m = receiver.waitForNextMessage();
+
+ assertThat(m.getMethodName()).isEqualTo("onReceive");
+ assertThat(m.getSenderIdentity()).isEqualTo(c.target.flattenToShortString());
+
+ // The broadcast intent will always have the receiving component name set.
+ assertThat(m.getIntent().getComponent()).isEqualTo(c.target);
+
+ receiver.ensureNoMoreMessages();
+ }
+ });
+ }
+
+ @Test
+ public void testBroadcast_explicitPackageName() {
+ forEachCombo((c) -> {
+ Intent i = new Intent().setPackage(c.alias.getPackageName());
+ i.setAction(c.action);
+ ComponentAliasMessage m;
+
+ try (Receiver<ComponentAliasMessage> receiver = new Receiver<>(sContext, TAG)) {
+ log("Sending broadcast: " + i);
+ sContext.sendBroadcast(i);
+
+ m = receiver.waitForNextMessage();
+
+ assertThat(m.getMethodName()).isEqualTo("onReceive");
+ assertThat(m.getSenderIdentity()).isEqualTo(c.target.flattenToShortString());
+
+ // The broadcast intent will always have the receiving component name set.
+ assertThat(m.getIntent().getComponent()).isEqualTo(c.target);
+
+ receiver.ensureNoMoreMessages();
+ }
+ });
+ }
+}
diff --git a/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasServiceTest.java b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasServiceTest.java
index af51c32..f0ff088 100644
--- a/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasServiceTest.java
+++ b/tests/componentalias/src/android/content/componentalias/tests/ComponentAliasServiceTest.java
@@ -27,24 +27,16 @@
import static org.hamcrest.core.IsNot.not;
import android.content.ComponentName;
-import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
-import android.provider.DeviceConfig;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
import com.android.compatibility.common.util.BroadcastMessenger;
import com.android.compatibility.common.util.BroadcastMessenger.Receiver;
-import com.android.compatibility.common.util.DeviceConfigStateHelper;
import com.android.compatibility.common.util.ShellUtils;
import com.android.compatibility.common.util.TestUtils;
-import org.junit.AfterClass;
import org.junit.Assume;
-import org.junit.Before;
import org.junit.Test;
import java.util.function.Consumer;
@@ -58,30 +50,7 @@
* Note all the helper APKs are battery-exempted (via AndroidTest.xml), so they can run
* BG services.
*/
-public class ComponentAliasServiceTest {
-
- private static final Context sContext = InstrumentationRegistry.getTargetContext();
-
- private static final DeviceConfigStateHelper sDeviceConfig = new DeviceConfigStateHelper(
- DeviceConfig.NAMESPACE_ACTIVITY_MANAGER);
- @Before
- public void enableComponentAlias() throws Exception {
- sDeviceConfig.set("component_alias_overrides", "");
- sDeviceConfig.set("enable_experimental_component_alias", "true");
-
- // Device config propagation happens on a handler, so we need to wait for AM to
- // actually set it.
- TestUtils.waitUntil("Wait until component alias is actually enabled", () -> {
- return ShellUtils.runShellCommand("dumpsys activity component-alias")
- .indexOf("Enabled: true") > 0;
- });
- }
-
- @AfterClass
- public static void restoreDeviceConfig() throws Exception {
- sDeviceConfig.close();
- }
-
+public class ComponentAliasServiceTest extends BaseComponentAliasTest {
/**
* Service connection used throughout the tests. It sends a message for each callback via
* the messenger.
@@ -89,7 +58,7 @@
private static final ServiceConnection sServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
- Log.w(TAG, "onServiceConnected: " + name);
+ log("onServiceConnected: " + name);
ComponentAliasMessage m = new ComponentAliasMessage()
.setSenderIdentity("sServiceConnection")
@@ -101,7 +70,7 @@
@Override
public void onServiceDisconnected(ComponentName name) {
- Log.w(TAG, "onServiceDisconnected: " + name);
+ log("onServiceDisconnected: " + name);
ComponentAliasMessage m = new ComponentAliasMessage()
.setSenderIdentity("sServiceConnection")
@@ -113,7 +82,7 @@
@Override
public void onBindingDied(ComponentName name) {
- Log.w(TAG, "onBindingDied: " + name);
+ log("onBindingDied: " + name);
ComponentAliasMessage m = new ComponentAliasMessage()
.setSenderIdentity("sServiceConnection")
@@ -124,7 +93,7 @@
@Override
public void onNullBinding(ComponentName name) {
- Log.w(TAG, "onNullBinding: " + name);
+ log("onNullBinding: " + name);
ComponentAliasMessage m = new ComponentAliasMessage()
.setSenderIdentity("sServiceConnection")
@@ -171,36 +140,23 @@
}
}
- private static class Combo {
- public final ComponentName alias;
- public final ComponentName target;
- public final String action;
-
- private Combo(ComponentName alias, ComponentName target, String action) {
- this.alias = alias;
- this.target = target;
- this.action = action;
- }
- }
-
private void forEachCombo(Consumer<Combo> callback) {
- callback.accept(new Combo(
+ new Combo(
new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".s.Alias00"),
new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".s.Target00"),
- MAIN_PACKAGE + ".IS_ALIAS_00"));
- callback.accept(new Combo(
+ MAIN_PACKAGE + ".IS_ALIAS_00").apply(callback);
+ new Combo(
new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".s.Alias01"),
new ComponentName(SUB1_PACKAGE, MAIN_PACKAGE + ".s.Target01"),
- MAIN_PACKAGE + ".IS_ALIAS_01"));
- callback.accept(new Combo(
+ MAIN_PACKAGE + ".IS_ALIAS_01").apply(callback);
+ new Combo(
new ComponentName(MAIN_PACKAGE, MAIN_PACKAGE + ".s.Alias02"),
new ComponentName(SUB2_PACKAGE, MAIN_PACKAGE + ".s.Target02"),
- MAIN_PACKAGE + ".IS_ALIAS_02"));
+ MAIN_PACKAGE + ".IS_ALIAS_02").apply(callback);
}
-
@Test
- public void testStartAndStopService_explicitComponentName() throws Exception {
+ public void testStartAndStopService_explicitComponentName() {
forEachCombo((c) -> {
Intent i = new Intent().setComponent(c.alias);
testStartAndStopService_common(i, c.alias, c.target);
@@ -208,7 +164,7 @@
}
@Test
- public void testStartAndStopService_explicitPackageName() throws Exception {
+ public void testStartAndStopService_explicitPackageName() {
forEachCombo((c) -> {
Intent i = new Intent().setPackage(c.alias.getPackageName());
i.setAction(c.action);
@@ -290,7 +246,7 @@
}
@Test
- public void testBindService_explicitComponentName() throws Exception {
+ public void testBindService_explicitComponentName() {
forEachCombo((c) -> {
Intent i = new Intent().setComponent(c.alias);
@@ -300,7 +256,7 @@
}
@Test
- public void testBindService_explicitPackageName() throws Exception {
+ public void testBindService_explicitPackageName() {
forEachCombo((c) -> {
Intent i = new Intent().setPackage(c.alias.getPackageName());
i.setAction(c.action);
@@ -314,7 +270,7 @@
* right component name.
*/
@Test
- public void testBindService_serviceKilled() throws Exception {
+ public void testBindService_serviceKilled() {
// We need to kill SUB2_PACKAGE, don't run it for this package.
Assume.assumeThat(sContext.getPackageName(), not(SUB2_PACKAGE));
diff --git a/tests/componentalias/src/android/content/componentalias/tests/b/BaseReceiver.java b/tests/componentalias/src/android/content/componentalias/tests/b/BaseReceiver.java
new file mode 100644
index 0000000..1d05e72
--- /dev/null
+++ b/tests/componentalias/src/android/content/componentalias/tests/b/BaseReceiver.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.componentalias.tests.b;
+
+import static android.content.componentalias.tests.ComponentAliasTestCommon.TAG;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.componentalias.tests.ComponentAliasMessage;
+import android.util.Log;
+
+import com.android.compatibility.common.util.BroadcastMessenger;
+
+public class BaseReceiver extends BroadcastReceiver {
+ private String getMyIdentity(Context context) {
+ return (new ComponentName(context.getPackageName(), this.getClass().getCanonicalName()))
+ .flattenToShortString();
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(TAG, "onReceive: on " + getMyIdentity(context) + " intent=" + intent);
+ ComponentAliasMessage m = new ComponentAliasMessage()
+ .setSenderIdentity(getMyIdentity(context))
+ .setMethodName("onReceive")
+ .setIntent(intent);
+ BroadcastMessenger.send(context, TAG, m);
+ }
+}
diff --git a/tests/componentalias/src/android/content/componentalias/tests/b/Target00.java b/tests/componentalias/src/android/content/componentalias/tests/b/Target00.java
new file mode 100644
index 0000000..8fb4e91
--- /dev/null
+++ b/tests/componentalias/src/android/content/componentalias/tests/b/Target00.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.componentalias.tests.b;
+
+import android.content.componentalias.tests.s.BaseService;
+
+public class Target00 extends BaseReceiver {
+}
diff --git a/tests/componentalias/src/android/content/componentalias/tests/b/Target01.java b/tests/componentalias/src/android/content/componentalias/tests/b/Target01.java
new file mode 100644
index 0000000..06f7a13
--- /dev/null
+++ b/tests/componentalias/src/android/content/componentalias/tests/b/Target01.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.componentalias.tests.b;
+
+public class Target01 extends BaseReceiver {
+}
diff --git a/tests/componentalias/src/android/content/componentalias/tests/b/Target02.java b/tests/componentalias/src/android/content/componentalias/tests/b/Target02.java
new file mode 100644
index 0000000..df7579d
--- /dev/null
+++ b/tests/componentalias/src/android/content/componentalias/tests/b/Target02.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.componentalias.tests.b;
+
+public class Target02 extends BaseReceiver {
+}
diff --git a/tests/componentalias/src/android/content/componentalias/tests/b/Target03.java b/tests/componentalias/src/android/content/componentalias/tests/b/Target03.java
new file mode 100644
index 0000000..5ae5521
--- /dev/null
+++ b/tests/componentalias/src/android/content/componentalias/tests/b/Target03.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.componentalias.tests.b;
+
+public class Target03 extends BaseReceiver {
+}
diff --git a/tests/componentalias/src/android/content/componentalias/tests/b/Target04.java b/tests/componentalias/src/android/content/componentalias/tests/b/Target04.java
new file mode 100644
index 0000000..f9b9886
--- /dev/null
+++ b/tests/componentalias/src/android/content/componentalias/tests/b/Target04.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.componentalias.tests.b;
+
+public class Target04 extends BaseReceiver {
+}
diff --git a/tests/componentalias/src/com/android/compatibility/common/util/BroadcastMessenger.java b/tests/componentalias/src/com/android/compatibility/common/util/BroadcastMessenger.java
index e01c2ef..a3a2abe 100644
--- a/tests/componentalias/src/com/android/compatibility/common/util/BroadcastMessenger.java
+++ b/tests/componentalias/src/com/android/compatibility/common/util/BroadcastMessenger.java
@@ -57,6 +57,8 @@
private static final String EXTRA_SENT_TIME =
"com.android.compatibility.common.util.BroadcastMessenger.EXTRA_SENT_TIME";
+ public static final int DEFAULT_TIMEOUT_MS = 10_000;
+
private static long getCurrentTime() {
return SystemClock.uptimeMillis();
}
@@ -161,7 +163,7 @@
*/
@NonNull
public T waitForNextMessage() {
- return waitForNextMessage(60_000);
+ return waitForNextMessage(DEFAULT_TIMEOUT_MS);
}
/**
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index 0f84f6e..c9a8947a 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -322,6 +322,7 @@
triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
verify(mSafeModeTimeoutAlarm).cancel();
assertFalse(mGatewayConnection.isInSafeMode());
+ verifySafeModeStateAndCallbackFired(1 /* invocationCount */, false /* isInSafeMode */);
}
@Test
@@ -391,6 +392,7 @@
triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
+ verifySafeModeStateAndCallbackFired(2 /* invocationCount */, false /* isInSafeMode */);
assertFalse(mGatewayConnection.isInSafeMode());
}
@@ -400,7 +402,7 @@
mTestLooper.dispatchAll();
triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
- assertFalse(mGatewayConnection.isInSafeMode());
+ verifySafeModeStateAndCallbackFired(1 /* invocationCount */, false /* isInSafeMode */);
// Trigger a failed validation, and the subsequent safemode timeout.
triggerValidation(NetworkAgent.VALIDATION_STATUS_NOT_VALID);
@@ -416,7 +418,7 @@
runnableCaptor.getValue().run();
mTestLooper.dispatchAll();
- assertTrue(mGatewayConnection.isInSafeMode());
+ verifySafeModeStateAndCallbackFired(2 /* invocationCount */, true /* isInSafeMode */);
}
private Consumer<VcnNetworkAgent> setupNetworkAndGetUnwantedCallback() {
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index a696b3a..64d0bca 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -23,7 +23,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
@@ -301,6 +300,11 @@
expectCanceled);
}
+ protected void verifySafeModeStateAndCallbackFired(int invocationCount, boolean isInSafeMode) {
+ verify(mGatewayStatusCallback, times(invocationCount)).onSafeModeStatusChanged();
+ assertEquals(isInSafeMode, mGatewayConnection.isInSafeMode());
+ }
+
protected void verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
@NonNull State expectedState) {
// Set a VcnNetworkAgent, and expect it to be unregistered and cleared
@@ -314,9 +318,8 @@
delayedEvent.run();
mTestLooper.dispatchAll();
- verify(mGatewayStatusCallback).onSafeModeStatusChanged();
assertEquals(expectedState, mGatewayConnection.getCurrentState());
- assertTrue(mGatewayConnection.isInSafeMode());
+ verifySafeModeStateAndCallbackFired(1, true);
verify(mockNetworkAgent).unregister();
assertNull(mGatewayConnection.getNetworkAgent());
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/CallingIdentityTokenDetector.kt b/tools/lint/checks/src/main/java/com/google/android/lint/CallingIdentityTokenDetector.kt
index c133226..930378b 100644
--- a/tools/lint/checks/src/main/java/com/google/android/lint/CallingIdentityTokenDetector.kt
+++ b/tools/lint/checks/src/main/java/com/google/android/lint/CallingIdentityTokenDetector.kt
@@ -39,6 +39,8 @@
import org.jetbrains.uast.getParentOfType
import org.jetbrains.uast.getQualifiedParentOrThis
import org.jetbrains.uast.getUCallExpression
+import org.jetbrains.uast.skipParenthesizedExprDown
+import org.jetbrains.uast.skipParenthesizedExprUp
/**
* Lint Detector that finds issues with improper usages of the token returned by
@@ -87,7 +89,8 @@
* - Stores token variable name, scope in the file, location and finally block in tokensMap
*/
override fun visitLocalVariable(node: ULocalVariable) {
- val rhsExpression = node.uastInitializer?.getUCallExpression() ?: return
+ val initializer = node.uastInitializer?.skipParenthesizedExprDown()
+ val rhsExpression = initializer?.getUCallExpression() ?: return
if (!isMethodCall(rhsExpression, Method.BINDER_CLEAR_CALLING_IDENTITY)) return
val location = context.getLocation(node as UElement)
val variableName = node.getName()
@@ -162,7 +165,8 @@
return
}
if (!isMethodCall(node, Method.BINDER_RESTORE_CALLING_IDENTITY)) return
- val arg = node.valueArguments[0] as? USimpleNameReferenceExpression ?: return
+ val first = node.valueArguments[0].skipParenthesizedExprDown()
+ val arg = first as? USimpleNameReferenceExpression ?: return
val variableName = arg.identifier
val originalScope = tokensMap[variableName]?.scope ?: return
val psi = arg.sourcePsi ?: return
@@ -177,7 +181,7 @@
// receiver.selector, so to get the call's immediate parent we need to get the topmost
// parent qualified reference expression and access its parent
if (tokensMap[variableName]?.finallyBlock != null &&
- node.getQualifiedParentOrThis().uastParent !=
+ skipParenthesizedExprUp(node.getQualifiedParentOrThis().uastParent) !=
tokensMap[variableName]?.finallyBlock) {
context.report(
ISSUE_RESTORE_IDENTITY_CALL_NOT_IN_FINALLY_BLOCK,