Merge "Handle the client volume mute events"
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index 2da00c7..6d5c160 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -274,24 +274,19 @@
public void onBootPhase(int phase) {
mBootPhase = phase;
- if (PHASE_SYSTEM_SERVICES_READY == phase) {
- mConfigObserver.start();
- mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
- ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
- setupEverything();
- } else if (PHASE_BOOT_COMPLETED == phase) {
- if (!mExemptListLoaded) {
- synchronized (mLock) {
- try {
- mExemptedApps =
- new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist());
- } catch (RemoteException e) {
- // Shouldn't happen.
- Slog.wtf(TAG, e);
- }
- mExemptListLoaded = true;
- }
- }
+ switch (phase) {
+ case PHASE_SYSTEM_SERVICES_READY:
+ mConfigObserver.start();
+ mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+ onBootPhaseSystemServicesReady();
+ break;
+ case PHASE_THIRD_PARTY_APPS_CAN_START:
+ onBootPhaseThirdPartyAppsCanStart();
+ break;
+ case PHASE_BOOT_COMPLETED:
+ onBootPhaseBootCompleted();
+ break;
}
}
@@ -403,10 +398,9 @@
final ArraySet<String> added = new ArraySet<>();
try {
mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist());
+ mExemptListLoaded = true;
} catch (RemoteException e) {
// Shouldn't happen.
- Slog.wtf(TAG, e);
- return;
}
for (int i = mExemptedApps.size() - 1; i >= 0; --i) {
@@ -695,17 +689,11 @@
/** Perform long-running and/or heavy setup work. This should be called off the main thread. */
private void setupHeavyWork() {
+ if (mBootPhase < PHASE_THIRD_PARTY_APPS_CAN_START || !mIsEnabled) {
+ return;
+ }
synchronized (mLock) {
loadInstalledPackageListLocked();
- if (mBootPhase >= PHASE_BOOT_COMPLETED && !mExemptListLoaded) {
- try {
- mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist());
- } catch (RemoteException e) {
- // Shouldn't happen.
- Slog.wtf(TAG, e);
- }
- mExemptListLoaded = true;
- }
final boolean isFirstSetup = !mScribe.recordExists();
if (isFirstSetup) {
mAgent.grantBirthrightsLocked();
@@ -726,18 +714,57 @@
}
}
- private void setupEverything() {
+ private void onBootPhaseSystemServicesReady() {
if (mBootPhase < PHASE_SYSTEM_SERVICES_READY || !mIsEnabled) {
return;
}
synchronized (mLock) {
registerListeners();
mCurrentBatteryLevel = getCurrentBatteryLevel();
+ }
+ }
+
+ private void onBootPhaseThirdPartyAppsCanStart() {
+ if (mBootPhase < PHASE_THIRD_PARTY_APPS_CAN_START || !mIsEnabled) {
+ return;
+ }
+ synchronized (mLock) {
mHandler.post(this::setupHeavyWork);
mCompleteEconomicPolicy.setup(mConfigObserver.getAllDeviceConfigProperties());
}
}
+ private void onBootPhaseBootCompleted() {
+ if (mBootPhase < PHASE_BOOT_COMPLETED || !mIsEnabled) {
+ return;
+ }
+ synchronized (mLock) {
+ if (!mExemptListLoaded) {
+ try {
+ mExemptedApps = new ArraySet<>(mDeviceIdleController.getFullPowerWhitelist());
+ mExemptListLoaded = true;
+ } catch (RemoteException e) {
+ // Shouldn't happen.
+ }
+ }
+ }
+ }
+
+ private void setupEverything() {
+ if (!mIsEnabled) {
+ return;
+ }
+ if (mBootPhase >= PHASE_SYSTEM_SERVICES_READY) {
+ onBootPhaseSystemServicesReady();
+ }
+ if (mBootPhase >= PHASE_THIRD_PARTY_APPS_CAN_START) {
+ onBootPhaseThirdPartyAppsCanStart();
+ }
+ if (mBootPhase >= PHASE_BOOT_COMPLETED) {
+ onBootPhaseBootCompleted();
+ }
+ }
+
private void tearDownEverything() {
if (mIsEnabled) {
return;
diff --git a/cmds/uinput/src/com/android/commands/uinput/Event.java b/cmds/uinput/src/com/android/commands/uinput/Event.java
index 9add310e..4b090f5 100644
--- a/cmds/uinput/src/com/android/commands/uinput/Event.java
+++ b/cmds/uinput/src/com/android/commands/uinput/Event.java
@@ -25,6 +25,7 @@
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.stream.IntStream;
import src.com.android.commands.uinput.InputAbsInfo;
@@ -338,7 +339,7 @@
mReader.beginArray();
while (mReader.hasNext()) {
int type = 0;
- int[] data = null;
+ IntStream data = null;
mReader.beginObject();
while (mReader.hasNext()) {
String name = mReader.nextName();
@@ -347,8 +348,7 @@
type = readInt();
break;
case "data":
- data = readIntList().stream()
- .mapToInt(Integer::intValue).toArray();
+ data = readIntList().stream().mapToInt(Integer::intValue);
break;
default:
consumeRemainingElements();
@@ -359,7 +359,9 @@
}
mReader.endObject();
if (data != null) {
- configuration.put(type, data);
+ final int[] existing = configuration.get(type);
+ configuration.put(type, existing == null ? data.toArray()
+ : IntStream.concat(IntStream.of(existing), data).toArray());
}
}
mReader.endArray();
diff --git a/core/api/current.txt b/core/api/current.txt
index 1cd8253..da3746d 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -11523,6 +11523,7 @@
field public static final int INSTALL_LOCATION_INTERNAL_ONLY = 1; // 0x1
field public static final int INSTALL_LOCATION_PREFER_EXTERNAL = 2; // 0x2
field public static final int REQUESTED_PERMISSION_GRANTED = 2; // 0x2
+ field public static final int REQUESTED_PERMISSION_IMPLICIT = 4; // 0x4
field public static final int REQUESTED_PERMISSION_NEVER_FOR_LOCATION = 65536; // 0x10000
field public android.content.pm.ActivityInfo[] activities;
field public android.content.pm.ApplicationInfo applicationInfo;
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 90b7828..e86d2f3 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -43,9 +43,9 @@
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.Looper;
-import android.os.Message;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -72,10 +72,7 @@
import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback;
import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
import com.android.internal.inputmethod.RemoteAccessibilityInputConnection;
-import com.android.internal.os.HandlerCaller;
-import com.android.internal.os.SomeArgs;
import com.android.internal.util.Preconditions;
-import com.android.internal.util.function.pooled.PooledLambda;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -2634,7 +2631,7 @@
*/
@Override
public final IBinder onBind(Intent intent) {
- return new IAccessibilityServiceClientWrapper(this, getMainLooper(), new Callbacks() {
+ return new IAccessibilityServiceClientWrapper(this, getMainExecutor(), new Callbacks() {
@Override
public void onServiceConnected() {
AccessibilityService.this.dispatchServiceConnected();
@@ -2751,30 +2748,12 @@
*
* @hide
*/
- public static class IAccessibilityServiceClientWrapper extends IAccessibilityServiceClient.Stub
- implements HandlerCaller.Callback {
- private static final int DO_INIT = 1;
- private static final int DO_ON_INTERRUPT = 2;
- private static final int DO_ON_ACCESSIBILITY_EVENT = 3;
- private static final int DO_ON_GESTURE = 4;
- private static final int DO_CLEAR_ACCESSIBILITY_CACHE = 5;
- private static final int DO_ON_KEY_EVENT = 6;
- private static final int DO_ON_MAGNIFICATION_CHANGED = 7;
- private static final int DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED = 8;
- private static final int DO_GESTURE_COMPLETE = 9;
- private static final int DO_ON_FINGERPRINT_ACTIVE_CHANGED = 10;
- private static final int DO_ON_FINGERPRINT_GESTURE = 11;
- private static final int DO_ACCESSIBILITY_BUTTON_CLICKED = 12;
- private static final int DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 13;
- private static final int DO_ON_SYSTEM_ACTIONS_CHANGED = 14;
- private static final int DO_CREATE_IME_SESSION = 15;
- private static final int DO_SET_IME_SESSION_ENABLED = 16;
- private static final int DO_START_INPUT = 19;
-
- private final HandlerCaller mCaller;
+ public static class IAccessibilityServiceClientWrapper extends
+ IAccessibilityServiceClient.Stub {
private final Callbacks mCallback;
private final Context mContext;
+ private final Executor mExecutor;
private int mConnectionId = AccessibilityInteractionClient.NO_ID;
@@ -2793,103 +2772,199 @@
@Nullable
CancellationGroup mCancellationGroup = null;
+ public IAccessibilityServiceClientWrapper(Context context, Executor executor,
+ Callbacks callback) {
+ mCallback = callback;
+ mContext = context;
+ mExecutor = executor;
+ }
+
public IAccessibilityServiceClientWrapper(Context context, Looper looper,
Callbacks callback) {
mCallback = callback;
mContext = context;
- mCaller = new HandlerCaller(context, looper, this, true /*asyncHandler*/);
+ mExecutor = new HandlerExecutor(new Handler(looper));
}
public void init(IAccessibilityServiceConnection connection, int connectionId,
IBinder windowToken) {
- Message message = mCaller.obtainMessageIOO(DO_INIT, connectionId,
- connection, windowToken);
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ mConnectionId = connectionId;
+ if (connection != null) {
+ AccessibilityInteractionClient.getInstance(mContext).addConnection(
+ mConnectionId, connection, /*initializeCache=*/true);
+ if (mContext != null) {
+ try {
+ connection.setAttributionTag(mContext.getAttributionTag());
+ } catch (RemoteException re) {
+ Log.w(LOG_TAG, "Error while setting attributionTag", re);
+ re.rethrowFromSystemServer();
+ }
+ }
+ mCallback.init(mConnectionId, windowToken);
+ mCallback.onServiceConnected();
+ } else {
+ AccessibilityInteractionClient.getInstance(mContext)
+ .clearCache(mConnectionId);
+ AccessibilityInteractionClient.getInstance(mContext).removeConnection(
+ mConnectionId);
+ mConnectionId = AccessibilityInteractionClient.NO_ID;
+ mCallback.init(AccessibilityInteractionClient.NO_ID, null);
+ }
+ return;
+ });
}
public void onInterrupt() {
- Message message = mCaller.obtainMessage(DO_ON_INTERRUPT);
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+ mCallback.onInterrupt();
+ }
+ });
}
public void onAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent) {
- Message message = mCaller.obtainMessageBO(
- DO_ON_ACCESSIBILITY_EVENT, serviceWantsEvent, event);
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ if (event != null) {
+ // Send the event to AccessibilityCache via AccessibilityInteractionClient
+ AccessibilityInteractionClient.getInstance(mContext).onAccessibilityEvent(
+ event, mConnectionId);
+ if (serviceWantsEvent
+ && (mConnectionId != AccessibilityInteractionClient.NO_ID)) {
+ // Send the event to AccessibilityService
+ mCallback.onAccessibilityEvent(event);
+ }
+ }
+ return;
+ });
}
@Override
public void onGesture(AccessibilityGestureEvent gestureInfo) {
- Message message = mCaller.obtainMessageO(DO_ON_GESTURE, gestureInfo);
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+ mCallback.onGesture(gestureInfo);
+ }
+ return;
+ });
}
public void clearAccessibilityCache() {
- Message message = mCaller.obtainMessage(DO_CLEAR_ACCESSIBILITY_CACHE);
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ AccessibilityInteractionClient.getInstance(mContext).clearCache(mConnectionId);
+ return;
+ });
}
@Override
public void onKeyEvent(KeyEvent event, int sequence) {
- Message message = mCaller.obtainMessageIO(DO_ON_KEY_EVENT, sequence, event);
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ try {
+ IAccessibilityServiceConnection connection = AccessibilityInteractionClient
+ .getInstance(mContext).getConnection(mConnectionId);
+ if (connection != null) {
+ final boolean result = mCallback.onKeyEvent(event);
+ try {
+ connection.setOnKeyEventResult(result, sequence);
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ }
+ } finally {
+ // Make sure the event is recycled.
+ try {
+ event.recycle();
+ } catch (IllegalStateException ise) {
+ /* ignore - best effort */
+ }
+ }
+ return;
+ });
}
/** Magnification changed callbacks for different displays */
public void onMagnificationChanged(int displayId, @NonNull Region region,
MagnificationConfig config) {
- final SomeArgs args = SomeArgs.obtain();
- args.arg1 = region;
- args.arg2 = config;
- args.argi1 = displayId;
-
- final Message message = mCaller.obtainMessageO(DO_ON_MAGNIFICATION_CHANGED, args);
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+ mCallback.onMagnificationChanged(displayId, region, config);
+ }
+ return;
+ });
}
public void onSoftKeyboardShowModeChanged(int showMode) {
- final Message message =
- mCaller.obtainMessageI(DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED, showMode);
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+ mCallback.onSoftKeyboardShowModeChanged(showMode);
+ }
+ return;
+ });
}
public void onPerformGestureResult(int sequence, boolean successfully) {
- Message message = mCaller.obtainMessageII(DO_GESTURE_COMPLETE, sequence,
- successfully ? 1 : 0);
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+ mCallback.onPerformGestureResult(sequence, successfully);
+ }
+ return;
+ });
}
public void onFingerprintCapturingGesturesChanged(boolean active) {
- mCaller.sendMessage(mCaller.obtainMessageI(
- DO_ON_FINGERPRINT_ACTIVE_CHANGED, active ? 1 : 0));
+ mExecutor.execute(() -> {
+ if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+ mCallback.onFingerprintCapturingGesturesChanged(active);
+ }
+ return;
+ });
}
public void onFingerprintGesture(int gesture) {
- mCaller.sendMessage(mCaller.obtainMessageI(DO_ON_FINGERPRINT_GESTURE, gesture));
+ mExecutor.execute(() -> {
+ if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+ mCallback.onFingerprintGesture(gesture);
+ }
+ return;
+ });
}
/** Accessibility button clicked callbacks for different displays */
public void onAccessibilityButtonClicked(int displayId) {
- final Message message = mCaller.obtainMessageI(DO_ACCESSIBILITY_BUTTON_CLICKED,
- displayId);
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+ mCallback.onAccessibilityButtonClicked(displayId);
+ }
+ return;
+ });
}
public void onAccessibilityButtonAvailabilityChanged(boolean available) {
- final Message message = mCaller.obtainMessageI(
- DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED, (available ? 1 : 0));
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+ mCallback.onAccessibilityButtonAvailabilityChanged(available);
+ }
+ return;
+ });
}
/** This is called when the system action list is changed. */
public void onSystemActionsChanged() {
- mCaller.sendMessage(mCaller.obtainMessage(DO_ON_SYSTEM_ACTIONS_CHANGED));
+ mExecutor.execute(() -> {
+ if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+ mCallback.onSystemActionsChanged();
+ }
+ return;
+ });
}
/** This is called when an app requests ime sessions or when the service is enabled. */
public void createImeSession(IAccessibilityInputMethodSessionCallback callback) {
- final Message message = mCaller.obtainMessageO(DO_CREATE_IME_SESSION, callback);
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+ mCallback.createImeSession(callback);
+ }
+ });
}
/**
@@ -2905,8 +2980,12 @@
Log.w(LOG_TAG, "Session is already finished: " + session);
return;
}
- mCaller.sendMessage(mCaller.obtainMessageIO(
- DO_SET_IME_SESSION_ENABLED, enabled ? 1 : 0, ls));
+ mExecutor.execute(() -> {
+ if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+ ls.setEnabled(enabled);
+ }
+ return;
+ });
} catch (ClassCastException e) {
Log.w(LOG_TAG, "Incoming session not of correct type: " + session, e);
}
@@ -2938,213 +3017,29 @@
Log.e(LOG_TAG, "startInput must be called after bindInput.");
mCancellationGroup = new CancellationGroup();
}
- final Message message = mCaller.obtainMessageOOOOII(DO_START_INPUT, null /* unused */,
- connection, editorInfo, mCancellationGroup, restarting ? 1 : 0,
- 0 /* unused */);
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+ final RemoteAccessibilityInputConnection ic = connection == null ? null
+ : new RemoteAccessibilityInputConnection(
+ connection, mCancellationGroup);
+ editorInfo.makeCompatible(mContext.getApplicationInfo().targetSdkVersion);
+ mCallback.startInput(ic, editorInfo, restarting);
+ }
+ });
}
@Override
public void onMotionEvent(MotionEvent event) {
- final Message message = PooledLambda.obtainMessage(
- Callbacks::onMotionEvent, mCallback, event);
- mCaller.sendMessage(message);
+ mExecutor.execute(() -> {
+ mCallback.onMotionEvent(event);
+ });
}
@Override
public void onTouchStateChanged(int displayId, int state) {
- final Message message = PooledLambda.obtainMessage(Callbacks::onTouchStateChanged,
- mCallback,
- displayId, state);
- mCaller.sendMessage(message);
- }
-
- @Override
- public void executeMessage(Message message) {
- switch (message.what) {
- case DO_ON_ACCESSIBILITY_EVENT: {
- AccessibilityEvent event = (AccessibilityEvent) message.obj;
- boolean serviceWantsEvent = message.arg1 != 0;
- if (event != null) {
- // Send the event to AccessibilityCache via AccessibilityInteractionClient
- AccessibilityInteractionClient.getInstance(mContext).onAccessibilityEvent(
- event, mConnectionId);
- if (serviceWantsEvent
- && (mConnectionId != AccessibilityInteractionClient.NO_ID)) {
- // Send the event to AccessibilityService
- mCallback.onAccessibilityEvent(event);
- }
- // Make sure the event is recycled.
- try {
- event.recycle();
- } catch (IllegalStateException ise) {
- /* ignore - best effort */
- }
- }
- return;
- }
- case DO_ON_INTERRUPT: {
- if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
- mCallback.onInterrupt();
- }
- return;
- }
- case DO_INIT: {
- mConnectionId = message.arg1;
- SomeArgs args = (SomeArgs) message.obj;
- IAccessibilityServiceConnection connection =
- (IAccessibilityServiceConnection) args.arg1;
- IBinder windowToken = (IBinder) args.arg2;
- args.recycle();
- if (connection != null) {
- AccessibilityInteractionClient.getInstance(mContext).addConnection(
- mConnectionId, connection, /*initializeCache=*/true);
- if (mContext != null) {
- try {
- connection.setAttributionTag(mContext.getAttributionTag());
- } catch (RemoteException re) {
- Log.w(LOG_TAG, "Error while setting attributionTag", re);
- re.rethrowFromSystemServer();
- }
- }
- mCallback.init(mConnectionId, windowToken);
- mCallback.onServiceConnected();
- } else {
- AccessibilityInteractionClient.getInstance(mContext)
- .clearCache(mConnectionId);
- AccessibilityInteractionClient.getInstance(mContext).removeConnection(
- mConnectionId);
- mConnectionId = AccessibilityInteractionClient.NO_ID;
- mCallback.init(AccessibilityInteractionClient.NO_ID, null);
- }
- return;
- }
- case DO_ON_GESTURE: {
- if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
- mCallback.onGesture((AccessibilityGestureEvent) message.obj);
- }
- return;
- }
- case DO_CLEAR_ACCESSIBILITY_CACHE: {
- AccessibilityInteractionClient.getInstance(mContext).clearCache(mConnectionId);
- return;
- }
- case DO_ON_KEY_EVENT: {
- KeyEvent event = (KeyEvent) message.obj;
- try {
- IAccessibilityServiceConnection connection = AccessibilityInteractionClient
- .getInstance(mContext).getConnection(mConnectionId);
- if (connection != null) {
- final boolean result = mCallback.onKeyEvent(event);
- final int sequence = message.arg1;
- try {
- connection.setOnKeyEventResult(result, sequence);
- } catch (RemoteException re) {
- /* ignore */
- }
- }
- } finally {
- // Make sure the event is recycled.
- try {
- event.recycle();
- } catch (IllegalStateException ise) {
- /* ignore - best effort */
- }
- }
- return;
- }
- case DO_ON_MAGNIFICATION_CHANGED: {
- if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
- final SomeArgs args = (SomeArgs) message.obj;
- final Region region = (Region) args.arg1;
- final MagnificationConfig config = (MagnificationConfig) args.arg2;
- final int displayId = args.argi1;
- args.recycle();
- mCallback.onMagnificationChanged(displayId, region, config);
- }
- return;
- }
- case DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED: {
- if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
- final int showMode = (int) message.arg1;
- mCallback.onSoftKeyboardShowModeChanged(showMode);
- }
- return;
- }
- case DO_GESTURE_COMPLETE: {
- if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
- final boolean successfully = message.arg2 == 1;
- mCallback.onPerformGestureResult(message.arg1, successfully);
- }
- return;
- }
- case DO_ON_FINGERPRINT_ACTIVE_CHANGED: {
- if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
- mCallback.onFingerprintCapturingGesturesChanged(message.arg1 == 1);
- }
- return;
- }
- case DO_ON_FINGERPRINT_GESTURE: {
- if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
- mCallback.onFingerprintGesture(message.arg1);
- }
- return;
- }
- case DO_ACCESSIBILITY_BUTTON_CLICKED: {
- if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
- mCallback.onAccessibilityButtonClicked(message.arg1);
- }
- return;
- }
- case DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: {
- if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
- final boolean available = (message.arg1 != 0);
- mCallback.onAccessibilityButtonAvailabilityChanged(available);
- }
- return;
- }
- case DO_ON_SYSTEM_ACTIONS_CHANGED: {
- if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
- mCallback.onSystemActionsChanged();
- }
- return;
- }
- case DO_CREATE_IME_SESSION: {
- if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
- IAccessibilityInputMethodSessionCallback callback =
- (IAccessibilityInputMethodSessionCallback) message.obj;
- mCallback.createImeSession(callback);
- }
- return;
- }
- case DO_SET_IME_SESSION_ENABLED: {
- if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
- AccessibilityInputMethodSession session =
- (AccessibilityInputMethodSession) message.obj;
- session.setEnabled(message.arg1 != 0);
- }
- return;
- }
- case DO_START_INPUT: {
- if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
- final SomeArgs args = (SomeArgs) message.obj;
- final IRemoteAccessibilityInputConnection connection =
- (IRemoteAccessibilityInputConnection) args.arg2;
- final EditorInfo info = (EditorInfo) args.arg3;
- final CancellationGroup cancellationGroup = (CancellationGroup) args.arg4;
- final boolean restarting = args.argi5 == 1;
- final RemoteAccessibilityInputConnection ic = connection == null ? null
- : new RemoteAccessibilityInputConnection(
- connection, cancellationGroup);
- info.makeCompatible(mContext.getApplicationInfo().targetSdkVersion);
- mCallback.startInput(ic, info, restarting);
- args.recycle();
- }
- return;
- }
- default:
- Log.w(LOG_TAG, "Unknown message type " + message.what);
- }
+ mExecutor.execute(() -> {
+ mCallback.onTouchStateChanged(displayId, state);
+ });
}
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index e25e374..449729e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -5124,7 +5124,7 @@
Preconditions.checkNotNull(listener);
Preconditions.checkNotNull(executor);
try {
- listener.init(mContext, executor, this);
+ listener.init(mContext, executor);
getService().registerProcessObserver(listener.mObserver);
// Notify upon first registration.
executor.execute(() ->
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b383d7d..6b3dc82 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -107,6 +107,7 @@
import android.net.Proxy;
import android.net.TrafficStats;
import android.net.Uri;
+import android.net.wifi.WifiFrameworkInitializer;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.BluetoothServiceManager;
@@ -7900,6 +7901,8 @@
BluetoothFrameworkInitializer.setBluetoothServiceManager(new BluetoothServiceManager());
BluetoothFrameworkInitializer.setBinderCallsStatsInitializer(context -> {
BinderCallsStats.startForBluetooth(context); });
+ WifiFrameworkInitializer.setBinderCallsStatsInitializer(context -> {
+ BinderCallsStats.startForWifi(context); });
}
private void purgePendingResources() {
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 57dacd0..877e7d3 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -263,11 +263,6 @@
// After orientation change, the onResume can come in before the top Activity has
// left, so if the Activity is not top, wait a second for the top Activity to exit.
if (mEnterTransitionCoordinator == null || activity.isTopOfTask()) {
- if (mEnterTransitionCoordinator != null) {
- mEnterTransitionCoordinator.runAfterTransitionsComplete(() -> {
- mEnterTransitionCoordinator = null;
- });
- }
restoreExitedViews();
restoreReenteringViews();
} else {
@@ -276,11 +271,6 @@
public void run() {
if (mEnterTransitionCoordinator == null ||
mEnterTransitionCoordinator.isWaitingForRemoteExit()) {
- if (mEnterTransitionCoordinator != null) {
- mEnterTransitionCoordinator.runAfterTransitionsComplete(() -> {
- mEnterTransitionCoordinator = null;
- });
- }
restoreExitedViews();
restoreReenteringViews();
} else if (mEnterTransitionCoordinator.isReturning()) {
diff --git a/core/java/android/app/GameManagerInternal.java b/core/java/android/app/GameManagerInternal.java
new file mode 100644
index 0000000..c8ff2a8
--- /dev/null
+++ b/core/java/android/app/GameManagerInternal.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+/**
+ * Game manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+
+public abstract class GameManagerInternal {
+ /**
+ * Used by the CompatModePackages to read game's compat scaling override.
+ */
+ public abstract float getResolutionScalingFactor(String packageName, int userId);
+}
diff --git a/core/java/android/app/HomeVisibilityListener.java b/core/java/android/app/HomeVisibilityListener.java
index 57d868b..ca20648 100644
--- a/core/java/android/app/HomeVisibilityListener.java
+++ b/core/java/android/app/HomeVisibilityListener.java
@@ -16,16 +16,17 @@
package android.app;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.content.ComponentName;
import android.content.Context;
import android.os.Binder;
-import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -39,20 +40,21 @@
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@TestApi
public abstract class HomeVisibilityListener {
- private Context mContext;
- private ActivityManager mActivityManager;
+ private ActivityTaskManager mActivityTaskManager;
private Executor mExecutor;
+ private int mMaxScanTasksForHomeVisibility;
/** @hide */
android.app.IProcessObserver.Stub mObserver;
/** @hide */
boolean mIsHomeActivityVisible;
/** @hide */
- void init(Context context, Executor executor, ActivityManager activityManager) {
- mContext = context;
- mActivityManager = activityManager;
- mIsHomeActivityVisible = isHomeActivityVisible();
+ void init(Context context, Executor executor) {
+ mActivityTaskManager = ActivityTaskManager.getInstance();
mExecutor = executor;
+ mMaxScanTasksForHomeVisibility = context.getResources().getInteger(
+ com.android.internal.R.integer.config_maxScanTasksForHomeVisibility);
+ mIsHomeActivityVisible = isHomeActivityVisible();
}
/**
@@ -91,22 +93,21 @@
}
private boolean isHomeActivityVisible() {
- List<ActivityManager.RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
- if (tasks == null || tasks.isEmpty()) {
+ List<ActivityManager.RunningTaskInfo> tasksTopToBottom = mActivityTaskManager.getTasks(
+ mMaxScanTasksForHomeVisibility, /* filterOnlyVisibleRecents= */ true,
+ /* keepIntentExtra= */ false, DEFAULT_DISPLAY);
+ if (tasksTopToBottom == null || tasksTopToBottom.isEmpty()) {
return false;
}
- String top = tasks.get(0).topActivity.getPackageName();
- if (top == null) {
- return false;
+ for (int i = 0, taskSize = tasksTopToBottom.size(); i < taskSize; ++i) {
+ ActivityManager.RunningTaskInfo task = tasksTopToBottom.get(i);
+ if (!task.isVisible()
+ || (task.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0) {
+ continue;
+ }
+ return task.getActivityType() == ACTIVITY_TYPE_HOME;
}
-
- // We can assume that the screen is idle if the home application is in the foreground.
- ComponentName defaultHomeComponent = mContext.getPackageManager()
- .getHomeActivities(new ArrayList<>());
- if (defaultHomeComponent == null) return false;
-
- String defaultHomePackage = defaultHomeComponent.getPackageName();
- return Objects.equals(top, defaultHomePackage);
+ return false;
}
}
diff --git a/core/java/android/app/IGameManagerService.aidl b/core/java/android/app/IGameManagerService.aidl
index e60a74a..481e7b0 100644
--- a/core/java/android/app/IGameManagerService.aidl
+++ b/core/java/android/app/IGameManagerService.aidl
@@ -31,4 +31,6 @@
void setGameState(String packageName, in GameState gameState, int userId);
GameModeInfo getGameModeInfo(String packageName, int userId);
void setGameServiceProvider(String packageName);
+ void updateResolutionScalingFactor(String packageName, int gameMode, float scalingFactor, int userId);
+ float getResolutionScalingFactor(String packageName, int gameMode, int userId);
}
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java
index 58ddd49..13934e5 100644
--- a/core/java/android/app/PropertyInvalidatedCache.java
+++ b/core/java/android/app/PropertyInvalidatedCache.java
@@ -310,6 +310,21 @@
public static final String MODULE_TELEPHONY = "telephony";
/**
+ * Constants that affect retries when the process is unable to write the property.
+ * The first constant is the number of times the process will attempt to set the
+ * property. The second constant is the delay between attempts.
+ */
+
+ /**
+ * Wait 200ms between retry attempts and the retry limit is 5. That gives a total possible
+ * delay of 1s, which should be less than ANR timeouts. The goal is to have the system crash
+ * because the property could not be set (which is a condition that is easily recognized) and
+ * not crash because of an ANR (which can be confusing to debug).
+ */
+ private static final int PROPERTY_FAILURE_RETRY_DELAY_MILLIS = 200;
+ private static final int PROPERTY_FAILURE_RETRY_LIMIT = 5;
+
+ /**
* Construct a system property that matches the rules described above. The module is
* one of the permitted values above. The API is a string that is a legal Java simple
* identifier. The api is modified to conform to the system property style guide by
@@ -670,7 +685,33 @@
}
}
}
- SystemProperties.set(name, Long.toString(val));
+ RuntimeException failure = null;
+ for (int attempt = 0; attempt < PROPERTY_FAILURE_RETRY_LIMIT; attempt++) {
+ try {
+ SystemProperties.set(name, Long.toString(val));
+ if (attempt > 0) {
+ // This log is not guarded. Based on known bug reports, it should
+ // occur once a week or less. The purpose of the log message is to
+ // identify the retries as a source of delay that might be otherwise
+ // be attributed to the cache itself.
+ Log.w(TAG, "Nonce set after " + attempt + " tries");
+ }
+ return;
+ } catch (RuntimeException e) {
+ if (failure == null) {
+ failure = e;
+ }
+ try {
+ Thread.sleep(PROPERTY_FAILURE_RETRY_DELAY_MILLIS);
+ } catch (InterruptedException x) {
+ // Ignore this exception. The desired delay is only approximate and
+ // there is no issue if the sleep sometimes terminates early.
+ }
+ }
+ }
+ // This point is reached only if SystemProperties.set() fails at least once.
+ // Rethrow the first exception that was received.
+ throw failure;
}
// Set the nonce in a static context. No handle is available.
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 8be2b48..e3bca9c 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -103,7 +103,6 @@
private boolean mOnLightBackground;
private SizeF mCurrentSize = null;
private RemoteViews.ColorResources mColorResources = null;
- private SparseIntArray mColorMapping = null;
// Stores the last remote views last inflated.
private RemoteViews mLastInflatedRemoteViews = null;
private long mLastInflatedRemoteViewsId = -1;
@@ -900,11 +899,19 @@
* {@link android.R.color#system_neutral1_500}.
*/
public void setColorResources(@NonNull SparseIntArray colorMapping) {
- if (mColorMapping != null && isSameColorMapping(mColorMapping, colorMapping)) {
+ if (mColorResources != null
+ && isSameColorMapping(mColorResources.getColorMapping(), colorMapping)) {
return;
}
- mColorMapping = colorMapping.clone();
- mColorResources = RemoteViews.ColorResources.create(mContext, mColorMapping);
+ setColorResources(RemoteViews.ColorResources.create(mContext, colorMapping));
+ }
+
+ /** @hide **/
+ public void setColorResources(RemoteViews.ColorResources colorResources) {
+ if (colorResources == mColorResources) {
+ return;
+ }
+ mColorResources = colorResources;
mColorMappingChanged = true;
mViewMode = VIEW_MODE_NOINIT;
reapplyLastRemoteViews();
@@ -934,7 +941,6 @@
public void resetColorResources() {
if (mColorResources != null) {
mColorResources = null;
- mColorMapping = null;
mColorMappingChanged = true;
mViewMode = VIEW_MODE_NOINIT;
reapplyLastRemoteViews();
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 0c171ad..da486ee 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -19,7 +19,7 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.os.Process.myUserHandle;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.os.Trace.TRACE_TAG_DATABASE;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -278,7 +278,7 @@
// Return an empty cursor for all columns.
return new MatrixCursor(cursor.getColumnNames(), 0);
}
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "query: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "query: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -289,7 +289,7 @@
throw e.rethrowAsRuntimeException();
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -298,13 +298,13 @@
// getCallingPackage() isn't available in getType(), as the javadoc states.
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "getType: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "getType: ", uri.getAuthority());
try {
return mInterface.getType(uri);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -336,7 +336,7 @@
setCallingAttributionSource(original);
}
}
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "insert: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "insert: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -345,7 +345,7 @@
throw e.rethrowAsRuntimeException();
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -358,7 +358,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return 0;
}
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "bulkInsert: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "bulkInsert: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -367,7 +367,7 @@
throw e.rethrowAsRuntimeException();
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -404,7 +404,7 @@
}
}
}
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "applyBatch: ", authority);
+ traceBegin(TRACE_TAG_DATABASE, "applyBatch: ", authority);
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -423,7 +423,7 @@
throw e.rethrowAsRuntimeException();
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -436,7 +436,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return 0;
}
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "delete: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "delete: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -445,7 +445,7 @@
throw e.rethrowAsRuntimeException();
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -458,7 +458,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return 0;
}
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "update: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "update: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -467,7 +467,7 @@
throw e.rethrowAsRuntimeException();
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -478,7 +478,7 @@
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
enforceFilePermission(attributionSource, uri, mode);
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openFile: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "openFile: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -488,7 +488,7 @@
throw e.rethrowAsRuntimeException();
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -499,7 +499,7 @@
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
enforceFilePermission(attributionSource, uri, mode);
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openAssetFile: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "openAssetFile: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -509,7 +509,7 @@
throw e.rethrowAsRuntimeException();
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -518,7 +518,7 @@
String method, @Nullable String arg, @Nullable Bundle extras) {
validateIncomingAuthority(authority);
Bundle.setDefusable(extras, true);
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "call: ", authority);
+ traceBegin(TRACE_TAG_DATABASE, "call: ", authority);
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -527,7 +527,7 @@
throw e.rethrowAsRuntimeException();
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -536,13 +536,13 @@
// getCallingPackage() isn't available in getType(), as the javadoc states.
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "getStreamTypes: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "getStreamTypes: ", uri.getAuthority());
try {
return mInterface.getStreamTypes(uri, mimeTypeFilter);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -554,7 +554,7 @@
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
enforceFilePermission(attributionSource, uri, "r");
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "openTypedAssetFile: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -564,7 +564,7 @@
throw e.rethrowAsRuntimeException();
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -582,7 +582,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return null;
}
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "canonicalize: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "canonicalize: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -591,7 +591,7 @@
throw e.rethrowAsRuntimeException();
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -618,7 +618,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return null;
}
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "uncanonicalize: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "uncanonicalize: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -627,7 +627,7 @@
throw e.rethrowAsRuntimeException();
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -654,7 +654,7 @@
!= PermissionChecker.PERMISSION_GRANTED) {
return false;
}
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "refresh: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "refresh: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -662,7 +662,7 @@
CancellationSignal.fromTransport(cancellationSignal));
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
@@ -671,7 +671,7 @@
int uid, int modeFlags) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "checkUriPermission: ", uri.getAuthority());
+ traceBegin(TRACE_TAG_DATABASE, "checkUriPermission: ", uri.getAuthority());
final AttributionSource original = setCallingAttributionSource(
attributionSource);
try {
@@ -680,7 +680,7 @@
throw e.rethrowAsRuntimeException();
} finally {
setCallingAttributionSource(original);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
}
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 26b2f07..0e0b2dc 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -11051,10 +11051,7 @@
if (!Objects.equals(this.mData, other.mData)) return false;
if (!Objects.equals(this.mType, other.mType)) return false;
if (!Objects.equals(this.mIdentifier, other.mIdentifier)) return false;
- if (!(this.hasPackageEquivalentComponent() && other.hasPackageEquivalentComponent())
- && !Objects.equals(this.mPackage, other.mPackage)) {
- return false;
- }
+ if (!Objects.equals(this.mPackage, other.mPackage)) return false;
if (!Objects.equals(this.mComponent, other.mComponent)) return false;
if (!Objects.equals(this.mCategories, other.mCategories)) return false;
@@ -11062,15 +11059,6 @@
}
/**
- * Return {@code true} if the component name is not null and is in the same package that this
- * intent limited to. otherwise return {@code false}.
- */
- private boolean hasPackageEquivalentComponent() {
- return mComponent != null
- && (mPackage == null || mPackage.equals(mComponent.getPackageName()));
- }
-
- /**
* Generate hash code that matches semantics of filterEquals().
*
* @return Returns the hash value of the action, data, type, class, and
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 9708493..4259600 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -252,6 +252,13 @@
public static final int REQUESTED_PERMISSION_NEVER_FOR_LOCATION = 0x00010000;
/**
+ * Flag for {@link #requestedPermissionsFlags}: the requested permission was
+ * not explicitly requested via uses-permission, but was instead implicitly
+ * requested (e.g., for version compatibility reasons).
+ */
+ public static final int REQUESTED_PERMISSION_IMPLICIT = 0x00000004;
+
+ /**
* Array of all signatures read from the package file. This is only filled
* in if the flag {@link PackageManager#GET_SIGNATURES} was set. A package
* must be signed with at least one certificate which is at position zero.
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index 0848697..6ed87fff 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -81,7 +81,7 @@
*
* @param clientProxy the proxy of the client at the service
*/
- /* package */ void setClientProxy(IContextHubClient clientProxy) {
+ /* package */ synchronized void setClientProxy(IContextHubClient clientProxy) {
Objects.requireNonNull(clientProxy, "IContextHubClient cannot be null");
if (mClientProxy != null) {
throw new IllegalStateException("Cannot change client proxy multiple times");
@@ -93,6 +93,7 @@
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
+ this.notifyAll();
}
/**
@@ -221,8 +222,15 @@
}
/** @hide */
- public void callbackFinished() {
+ public synchronized void callbackFinished() {
try {
+ while (mClientProxy == null) {
+ try {
+ this.wait();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
mClientProxy.callbackFinished();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 0418a4b..87579eb 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -29,6 +29,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
import java.io.Serializable;
import java.lang.ref.WeakReference;
@@ -113,17 +114,21 @@
*/
private boolean mParcelledByNative;
- /*
+ /**
* Flag indicating if mParcelledData is only referenced in this bundle.
- * mParcelledData could be referenced by other bundles if mMap contains lazy values,
+ * mParcelledData could be referenced elsewhere if mMap contains lazy values,
* and bundle data is copied to another bundle using putAll or the copy constructors.
*/
boolean mOwnsLazyValues = true;
- /*
+ /** Tracks how many lazy values are referenced in mMap */
+ private int mLazyValues = 0;
+
+ /**
* As mParcelledData is set to null when it is unparcelled, we keep a weak reference to
* it to aid in recycling it. Do not use this reference otherwise.
- */
+ * Is non-null iff mMap contains lazy values.
+ */
private WeakReference<Parcel> mWeakParcelledData = null;
/**
@@ -310,7 +315,8 @@
synchronized (this) {
final Parcel source = mParcelledData;
if (source != null) {
- initializeFromParcelLocked(source, /*recycleParcel=*/ true, mParcelledByNative);
+ Preconditions.checkState(mOwnsLazyValues);
+ initializeFromParcelLocked(source, /*ownsParcel*/ true, mParcelledByNative);
} else {
if (DEBUG) {
Log.d(TAG, "unparcel "
@@ -401,11 +407,23 @@
}
}
mMap.setValueAt(i, object);
+ mLazyValues--;
+ if (mOwnsLazyValues) {
+ Preconditions.checkState(mLazyValues >= 0, "Lazy values ref count below 0");
+ // No more lazy values in mMap, so we can recycle the parcel early rather than
+ // waiting for the next GC run
+ if (mLazyValues == 0) {
+ Preconditions.checkState(mWeakParcelledData.get() != null,
+ "Parcel recycled earlier than expected");
+ recycleParcel(mWeakParcelledData.get());
+ mWeakParcelledData = null;
+ }
+ }
}
return (clazz != null) ? clazz.cast(object) : (T) object;
}
- private void initializeFromParcelLocked(@NonNull Parcel parcelledData, boolean recycleParcel,
+ private void initializeFromParcelLocked(@NonNull Parcel parcelledData, boolean ownsParcel,
boolean parcelledByNative) {
if (isEmptyParcel(parcelledData)) {
if (DEBUG) {
@@ -437,9 +455,10 @@
map.erase();
map.ensureCapacity(count);
}
+ int numLazyValues = 0;
try {
- recycleParcel &= parcelledData.readArrayMap(map, count, !parcelledByNative,
- /* lazy */ true, mClassLoader);
+ numLazyValues = parcelledData.readArrayMap(map, count, !parcelledByNative,
+ /* lazy */ ownsParcel, mClassLoader);
} catch (BadParcelableException e) {
if (sShouldDefuse) {
Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
@@ -448,14 +467,19 @@
throw e;
}
} finally {
- mMap = map;
- if (recycleParcel) {
- recycleParcel(parcelledData);
- mWeakParcelledData = null;
- } else {
- mWeakParcelledData = new WeakReference<>(parcelledData);
+ mWeakParcelledData = null;
+ if (ownsParcel) {
+ if (numLazyValues == 0) {
+ recycleParcel(parcelledData);
+ } else {
+ mWeakParcelledData = new WeakReference<>(parcelledData);
+ }
}
+
+ mLazyValues = numLazyValues;
mParcelledByNative = false;
+ mMap = map;
+ // Set field last as it is volatile
mParcelledData = null;
}
if (DEBUG) {
@@ -592,13 +616,17 @@
/**
* Removes all elements from the mapping of this Bundle.
+ * Recycles the underlying parcel if it is still present.
*/
public void clear() {
unparcel();
if (mOwnsLazyValues && mWeakParcelledData != null) {
recycleParcel(mWeakParcelledData.get());
- mWeakParcelledData = null;
}
+
+ mWeakParcelledData = null;
+ mLazyValues = 0;
+ mOwnsLazyValues = true;
mMap.clear();
}
@@ -1844,8 +1872,8 @@
// had been constructed with parcel or to make sure they trigger deserialization of the
// bundle immediately; neither of which is obvious.
synchronized (this) {
- initializeFromParcelLocked(parcel, /*recycleParcel=*/ false, isNativeBundle);
- unparcel(/* itemwise */ true);
+ mOwnsLazyValues = false;
+ initializeFromParcelLocked(parcel, /*ownsParcel*/ false, isNativeBundle);
}
return;
}
@@ -1862,6 +1890,7 @@
+ ": " + length + " bundle bytes starting at " + offset);
p.setDataPosition(0);
+ mOwnsLazyValues = true;
mParcelledByNative = isNativeBundle;
mParcelledData = p;
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index d553132..80201d3 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -71,7 +71,6 @@
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.IntFunction;
-import java.util.function.Supplier;
/**
* Container for a message (data and object references) that can
@@ -5242,20 +5241,20 @@
* Reads a map into {@code map}.
*
* @param sorted Whether the keys are sorted by their hashes, if so we use an optimized path.
- * @param lazy Whether to populate the map with lazy {@link Supplier} objects for
+ * @param lazy Whether to populate the map with lazy {@link Function} objects for
* length-prefixed values. See {@link Parcel#readLazyValue(ClassLoader)} for more
* details.
- * @return whether the parcel can be recycled or not.
+ * @return a count of the lazy values in the map
* @hide
*/
- boolean readArrayMap(ArrayMap<? super String, Object> map, int size, boolean sorted,
+ int readArrayMap(ArrayMap<? super String, Object> map, int size, boolean sorted,
boolean lazy, @Nullable ClassLoader loader) {
- boolean recycle = true;
+ int lazyValues = 0;
while (size > 0) {
String key = readString();
Object value = (lazy) ? readLazyValue(loader) : readValue(loader);
if (value instanceof LazyValue) {
- recycle = false;
+ lazyValues++;
}
if (sorted) {
map.append(key, value);
@@ -5267,7 +5266,7 @@
if (sorted) {
map.validate();
}
- return recycle;
+ return lazyValues;
}
/**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 8d3509c..d14d2e4 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2838,6 +2838,26 @@
}
/**
+ * @hide
+ */
+ public static boolean isUsersOnSecondaryDisplaysEnabled() {
+ return SystemProperties.getBoolean("fw.users_on_secondary_displays",
+ Resources.getSystem()
+ .getBoolean(R.bool.config_multiuserUsersOnSecondaryDisplays));
+ }
+
+ /**
+ * Returns whether the device allows users to run (and launch activities) on secondary displays.
+ *
+ * @return {@code false} for most devices, except automotive vehicles with passenger displays.
+ *
+ * @hide
+ */
+ public boolean isUsersOnSecondaryDisplaysSupported() {
+ return isUsersOnSecondaryDisplaysEnabled();
+ }
+
+ /**
* Return whether the context user is running in an "unlocked" state.
* <p>
* On devices with direct boot, a user is unlocked only after they've
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9000899..6fc2811 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -14257,7 +14257,7 @@
*
* @hide
*/
- public static final int DEFAULT_ENABLE_TARE = 1;
+ public static final int DEFAULT_ENABLE_TARE = 0;
/**
* Whether to enable the TARE AlarmManager economic policy or not.
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index cce3e8c..a2cb1d5 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -733,7 +733,7 @@
}
for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
// Only update the server side insets here.
- if (type == ITYPE_CAPTION_BAR) continue;
+ if (!CAPTION_ON_SHELL && type == ITYPE_CAPTION_BAR) continue;
InsetsSource source = mState.peekSource(type);
if (source == null) continue;
if (newState.peekSource(type) == null) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e1966a0..84dadca 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -277,7 +277,7 @@
* @hide
*/
public static final boolean CAPTION_ON_SHELL =
- SystemProperties.getBoolean("persist.debug.caption_on_shell", false);
+ SystemProperties.getBoolean("persist.wm.debug.caption_on_shell", false);
/**
* Whether the client should compute the window frame on its own.
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 2879cd8..5eec054 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -594,8 +594,8 @@
* SUBCLASSES MUST BE IMMUTABLE SO CLONE WORKS!!!!!
*/
private abstract static class Action implements Parcelable {
- public abstract void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) throws ActionException;
+ public abstract void apply(View root, ViewGroup rootParent, ActionApplyParams params)
+ throws ActionException;
public static final int MERGE_REPLACE = 0;
public static final int MERGE_APPEND = 1;
@@ -626,7 +626,7 @@
* Override this if some of the tasks can be performed async.
*/
public Action initActionAsync(ViewTree root, ViewGroup rootParent,
- InteractionHandler handler, ColorResources colorResources) {
+ ActionApplyParams params) {
return this;
}
@@ -661,9 +661,7 @@
// Constant used during async execution. It is not parcelable.
private static final Action ACTION_NOOP = new RuntimeAction() {
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
- }
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) { }
};
/**
@@ -798,8 +796,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View view = root.findViewById(viewId);
if (!(view instanceof AdapterView<?>)) return;
@@ -834,8 +831,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, final InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -846,7 +842,7 @@
OnItemClickListener listener = (parent, view, position, id) -> {
RemoteResponse response = findRemoteResponseTag(view);
if (response != null) {
- response.handleViewInteraction(view, handler);
+ response.handleViewInteraction(view, params.handler);
}
};
av.setOnItemClickListener(listener);
@@ -910,8 +906,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -935,7 +930,7 @@
((RemoteViewsListAdapter) a).setViewsList(list);
} else {
v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list, viewTypeCount,
- colorResources));
+ params.colorResources));
}
} else if (target instanceof AdapterViewAnimator) {
AdapterViewAnimator v = (AdapterViewAnimator) target;
@@ -944,7 +939,7 @@
((RemoteViewsListAdapter) a).setViewsList(list);
} else {
v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list, viewTypeCount,
- colorResources));
+ params.colorResources));
}
}
}
@@ -1025,8 +1020,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) throws ActionException {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params)
+ throws ActionException {
View target = root.findViewById(viewId);
if (target == null) return;
@@ -1053,7 +1048,7 @@
&& adapter.getViewTypeCount() >= mItems.getViewTypeCount()) {
try {
((RemoteCollectionItemsAdapter) adapter).setData(
- mItems, handler, colorResources);
+ mItems, params.handler, params.colorResources);
} catch (Throwable throwable) {
// setData should never failed with the validation in the items builder, but if
// it does, catch and rethrow.
@@ -1063,8 +1058,8 @@
}
try {
- adapterView.setAdapter(
- new RemoteCollectionItemsAdapter(mItems, handler, colorResources));
+ adapterView.setAdapter(new RemoteCollectionItemsAdapter(mItems,
+ params.handler, params.colorResources));
} catch (Throwable throwable) {
// This could throw if the AdapterView somehow doesn't accept BaseAdapter due to
// a type error.
@@ -1095,8 +1090,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -1124,17 +1118,17 @@
if (target instanceof AbsListView) {
AbsListView v = (AbsListView) target;
v.setRemoteViewsAdapter(intent, isAsync);
- v.setRemoteViewsInteractionHandler(handler);
+ v.setRemoteViewsInteractionHandler(params.handler);
} else if (target instanceof AdapterViewAnimator) {
AdapterViewAnimator v = (AdapterViewAnimator) target;
v.setRemoteViewsAdapter(intent, isAsync);
- v.setRemoteViewsOnClickHandler(handler);
+ v.setRemoteViewsOnClickHandler(params.handler);
}
}
@Override
public Action initActionAsync(ViewTree root, ViewGroup rootParent,
- InteractionHandler handler, ColorResources colorResources) {
+ ActionApplyParams params) {
SetRemoteViewsAdapterIntent copy = new SetRemoteViewsAdapterIntent(viewId, intent);
copy.isAsync = true;
return copy;
@@ -1173,8 +1167,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, final InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -1215,7 +1208,7 @@
target.setTagInternal(com.android.internal.R.id.fillInIntent, null);
return;
}
- target.setOnClickListener(v -> mResponse.handleViewInteraction(v, handler));
+ target.setOnClickListener(v -> mResponse.handleViewInteraction(v, params.handler));
}
@Override
@@ -1253,8 +1246,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, final InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View target = root.findViewById(viewId);
if (target == null) return;
if (!(target instanceof CompoundButton)) {
@@ -1287,7 +1279,7 @@
}
OnCheckedChangeListener onCheckedChangeListener =
- (v, isChecked) -> mResponse.handleViewInteraction(v, handler);
+ (v, isChecked) -> mResponse.handleViewInteraction(v, params.handler);
button.setTagInternal(R.id.remote_checked_change_listener_tag, onCheckedChangeListener);
button.setOnCheckedChangeListener(onCheckedChangeListener);
}
@@ -1459,8 +1451,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -1517,8 +1508,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -1561,8 +1551,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View view = root.findViewById(viewId);
if (view == null) return;
@@ -1675,12 +1664,12 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) throws ActionException {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params)
+ throws ActionException {
ReflectionAction ra = new ReflectionAction(viewId, methodName,
BaseReflectionAction.BITMAP,
bitmap);
- ra.apply(root, rootParent, handler, colorResources);
+ ra.apply(root, rootParent, params);
}
@Override
@@ -1756,8 +1745,7 @@
protected abstract Object getParameterValue(@Nullable View view) throws ActionException;
@Override
- public final void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public final void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View view = root.findViewById(viewId);
if (view == null) return;
@@ -1775,7 +1763,7 @@
@Override
public final Action initActionAsync(ViewTree root, ViewGroup rootParent,
- InteractionHandler handler, ColorResources colorResources) {
+ ActionApplyParams params) {
final View view = root.findViewById(viewId);
if (view == null) return ACTION_NOOP;
@@ -2307,8 +2295,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
mRunnable.run();
}
}
@@ -2421,8 +2408,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final Context context = root.getContext();
final ViewGroup target = root.findViewById(viewId);
@@ -2451,8 +2437,7 @@
target.removeViews(nextChild, recycledViewIndex - nextChild);
}
setNextRecyclableChild(target, nextChild + 1, target.getChildCount());
- rvToApply.reapplyNestedViews(context, child, rootParent, handler,
- null /* size */, colorResources);
+ rvToApply.reapplyNestedViews(context, child, rootParent, params);
return;
}
// If we cannot recycle the views, we still remove all views in between to
@@ -2463,8 +2448,7 @@
// If we cannot recycle, insert the new view before the next recyclable child.
// Inflate nested views and add as children
- View nestedView = rvToApply.applyNestedViews(context, target, rootParent, handler,
- null /* size */, colorResources);
+ View nestedView = rvToApply.apply(context, target, rootParent, null /* size */, params);
if (mStableId != NO_ID) {
setStableId(nestedView, mStableId);
}
@@ -2477,7 +2461,7 @@
@Override
public Action initActionAsync(ViewTree root, ViewGroup rootParent,
- InteractionHandler handler, ColorResources colorResources) {
+ ActionApplyParams params) {
// In the async implementation, update the view tree so that subsequent calls to
// findViewById return the current view.
root.createTree();
@@ -2511,8 +2495,7 @@
setNextRecyclableChild(targetVg, nextChild + 1, target.mChildren.size());
final AsyncApplyTask reapplyTask = rvToApply.getInternalAsyncApplyTask(
context,
- targetVg, null /* listener */, handler, null /* size */,
- colorResources,
+ targetVg, null /* listener */, params, null /* size */,
recycled.mRoot);
final ViewTree tree = reapplyTask.doInBackground();
if (tree == null) {
@@ -2521,8 +2504,7 @@
return new RuntimeAction() {
@Override
public void apply(View root, ViewGroup rootParent,
- InteractionHandler handler, ColorResources colorResources)
- throws ActionException {
+ ActionApplyParams params) throws ActionException {
reapplyTask.onPostExecute(tree);
if (recycledViewIndex > nextChild) {
targetVg.removeViews(nextChild, recycledViewIndex - nextChild);
@@ -2533,23 +2515,22 @@
// If the layout id is different, still remove the children as if we recycled
// the view, to insert at the same place.
target.removeChildren(nextChild, recycledViewIndex - nextChild + 1);
- return insertNewView(context, target, handler, colorResources,
+ return insertNewView(context, target, params,
() -> targetVg.removeViews(nextChild,
recycledViewIndex - nextChild + 1));
}
}
// If we cannot recycle, simply add the view at the same available slot.
- return insertNewView(context, target, handler, colorResources, () -> {});
+ return insertNewView(context, target, params, () -> {});
}
- private Action insertNewView(Context context, ViewTree target, InteractionHandler handler,
- ColorResources colorResources, Runnable finalizeAction) {
+ private Action insertNewView(Context context, ViewTree target,
+ ActionApplyParams params, Runnable finalizeAction) {
ViewGroup targetVg = (ViewGroup) target.mRoot;
int nextChild = getNextRecyclableChild(targetVg);
final AsyncApplyTask task = mNestedViews.getInternalAsyncApplyTask(context, targetVg,
- null /* listener */, handler, null /* size */, colorResources,
- null /* result */);
+ null /* listener */, params, null /* size */, null /* result */);
final ViewTree tree = task.doInBackground();
if (tree == null) {
@@ -2569,8 +2550,7 @@
return new RuntimeAction() {
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) throws ActionException {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
task.onPostExecute(tree);
finalizeAction.run();
targetVg.addView(task.mResult, insertIndex);
@@ -2627,8 +2607,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final ViewGroup target = root.findViewById(viewId);
if (target == null) {
@@ -2652,7 +2631,7 @@
@Override
public Action initActionAsync(ViewTree root, ViewGroup rootParent,
- InteractionHandler handler, ColorResources colorResources) {
+ ActionApplyParams params) {
// In the async implementation, update the view tree so that subsequent calls to
// findViewById return the current view.
root.createTree();
@@ -2676,8 +2655,7 @@
}
return new RuntimeAction() {
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) throws ActionException {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
if (mViewIdToKeep == REMOVE_ALL_VIEWS_ID) {
for (int i = targetVg.getChildCount() - 1; i >= 0; i--) {
if (!hasStableId(targetVg.getChildAt(i))) {
@@ -2736,8 +2714,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View target = root.findViewById(viewId);
if (target == null || target == root) {
@@ -2752,7 +2729,7 @@
@Override
public Action initActionAsync(ViewTree root, ViewGroup rootParent,
- InteractionHandler handler, ColorResources colorResources) {
+ ActionApplyParams params) {
// In the async implementation, update the view tree so that subsequent calls to
// findViewById return the correct view.
root.createTree();
@@ -2771,8 +2748,7 @@
parent.mChildren.remove(target);
return new RuntimeAction() {
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) throws ActionException {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
parentVg.removeView(target.mRoot);
}
};
@@ -2851,8 +2827,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final TextView target = root.findViewById(viewId);
if (target == null) return;
if (drawablesLoaded) {
@@ -2883,7 +2858,7 @@
@Override
public Action initActionAsync(ViewTree root, ViewGroup rootParent,
- InteractionHandler handler, ColorResources colorResources) {
+ ActionApplyParams params) {
final TextView target = root.findViewById(viewId);
if (target == null) return ACTION_NOOP;
@@ -2961,8 +2936,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final TextView target = root.findViewById(viewId);
if (target == null) return;
target.setTextSize(units, size);
@@ -3007,8 +2981,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View target = root.findViewById(viewId);
if (target == null) return;
target.setPadding(left, top, right, bottom);
@@ -3084,8 +3057,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View target = root.findViewById(viewId);
if (target == null) {
return;
@@ -3230,8 +3202,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -3266,8 +3237,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
// Let's traverse the viewtree and override all textColors!
Stack<View> viewsToProcess = new Stack<>();
viewsToProcess.add(root);
@@ -3317,8 +3287,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params) {
final View target = root.findViewById(mViewId);
if (target == null) return;
@@ -3352,8 +3321,7 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources)
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params)
throws ActionException {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -3404,8 +3372,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) throws ActionException {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params)
+ throws ActionException {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -3483,8 +3451,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
- ColorResources colorResources) throws ActionException {
+ public void apply(View root, ViewGroup rootParent, ActionApplyParams params)
+ throws ActionException {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -5578,52 +5546,39 @@
/** @hide */
public View apply(@NonNull Context context, @NonNull ViewGroup parent,
@Nullable InteractionHandler handler, @Nullable SizeF size) {
- RemoteViews rvToApply = getRemoteViewsToApply(context, size);
-
- View result = inflateView(context, rvToApply, parent);
- rvToApply.performApply(result, parent, handler, null);
- return result;
+ return apply(context, parent, size, new ActionApplyParams()
+ .withInteractionHandler(handler));
}
/** @hide */
public View applyWithTheme(@NonNull Context context, @NonNull ViewGroup parent,
@Nullable InteractionHandler handler, @StyleRes int applyThemeResId) {
- return applyWithTheme(context, parent, handler, applyThemeResId, null);
- }
-
- /** @hide */
- public View applyWithTheme(@NonNull Context context, @NonNull ViewGroup parent,
- @Nullable InteractionHandler handler, @StyleRes int applyThemeResId,
- @Nullable SizeF size) {
- RemoteViews rvToApply = getRemoteViewsToApply(context, size);
-
- View result = inflateView(context, rvToApply, parent, applyThemeResId, null);
- rvToApply.performApply(result, parent, handler, null);
- return result;
+ return apply(context, parent, null, new ActionApplyParams()
+ .withInteractionHandler(handler)
+ .withThemeResId(applyThemeResId));
}
/** @hide */
public View apply(Context context, ViewGroup parent, InteractionHandler handler,
@Nullable SizeF size, @Nullable ColorResources colorResources) {
- RemoteViews rvToApply = getRemoteViewsToApply(context, size);
-
- View result = inflateView(context, rvToApply, parent, 0, colorResources);
- rvToApply.performApply(result, parent, handler, colorResources);
- return result;
+ return apply(context, parent, size, new ActionApplyParams()
+ .withInteractionHandler(handler)
+ .withColorResources(colorResources));
}
- private View applyNestedViews(Context context, ViewGroup directParent,
- ViewGroup rootParent, InteractionHandler handler, SizeF size,
- ColorResources colorResources) {
- RemoteViews rvToApply = getRemoteViewsToApply(context, size);
-
- View result = inflateView(context, rvToApply, directParent, 0, colorResources);
- rvToApply.performApply(result, rootParent, handler, colorResources);
- return result;
+ /** @hide **/
+ public View apply(Context context, ViewGroup parent, @Nullable SizeF size,
+ ActionApplyParams params) {
+ return apply(context, parent, parent, size, params);
}
- private View inflateView(Context context, RemoteViews rv, ViewGroup parent) {
- return inflateView(context, rv, parent, 0, null);
+ private View apply(Context context, ViewGroup directParent, ViewGroup rootParent,
+ @Nullable SizeF size, ActionApplyParams params) {
+ RemoteViews rvToApply = getRemoteViewsToApply(context, size);
+ View result = inflateView(context, rvToApply, directParent,
+ params.applyThemeResId, params.colorResources);
+ rvToApply.performApply(result, rootParent, params);
+ return result;
}
private View inflateView(Context context, RemoteViews rv, @Nullable ViewGroup parent,
@@ -5704,7 +5659,6 @@
return applyAsync(context, parent, executor, listener, null /* handler */);
}
-
/** @hide */
public CancellationSignal applyAsync(Context context, ViewGroup parent,
Executor executor, OnViewAppliedListener listener, InteractionHandler handler) {
@@ -5723,16 +5677,19 @@
public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor,
OnViewAppliedListener listener, InteractionHandler handler, SizeF size,
ColorResources colorResources) {
+
+ ActionApplyParams params = new ActionApplyParams()
+ .withInteractionHandler(handler)
+ .withColorResources(colorResources)
+ .withExecutor(executor);
return new AsyncApplyTask(getRemoteViewsToApply(context, size), parent, context, listener,
- handler, colorResources, null /* result */,
- true /* topLevel */).startTaskOnExecutor(executor);
+ params, null /* result */, true /* topLevel */).startTaskOnExecutor(executor);
}
private AsyncApplyTask getInternalAsyncApplyTask(Context context, ViewGroup parent,
- OnViewAppliedListener listener, InteractionHandler handler, SizeF size,
- ColorResources colorResources, View result) {
+ OnViewAppliedListener listener, ActionApplyParams params, SizeF size, View result) {
return new AsyncApplyTask(getRemoteViewsToApply(context, size), parent, context, listener,
- handler, colorResources, result, false /* topLevel */);
+ params, result, false /* topLevel */);
}
private class AsyncApplyTask extends AsyncTask<Void, Void, ViewTree>
@@ -5742,8 +5699,8 @@
final ViewGroup mParent;
final Context mContext;
final OnViewAppliedListener mListener;
- final InteractionHandler mHandler;
- final ColorResources mColorResources;
+ final ActionApplyParams mApplyParams;
+
/**
* Whether the remote view is the top-level one (i.e. not within an action).
*
@@ -5758,16 +5715,13 @@
private AsyncApplyTask(
RemoteViews rv, ViewGroup parent, Context context, OnViewAppliedListener listener,
- InteractionHandler handler, ColorResources colorResources,
- View result, boolean topLevel) {
+ ActionApplyParams applyParams, View result, boolean topLevel) {
mRV = rv;
mParent = parent;
mContext = context;
mListener = listener;
- mColorResources = colorResources;
- mHandler = handler;
mTopLevel = topLevel;
-
+ mApplyParams = applyParams;
mResult = result;
}
@@ -5776,17 +5730,18 @@
protected ViewTree doInBackground(Void... params) {
try {
if (mResult == null) {
- mResult = inflateView(mContext, mRV, mParent, 0, mColorResources);
+ mResult = inflateView(mContext, mRV, mParent, 0, mApplyParams.colorResources);
}
mTree = new ViewTree(mResult);
+
if (mRV.mActions != null) {
int count = mRV.mActions.size();
mActions = new Action[count];
for (int i = 0; i < count && !isCancelled(); i++) {
// TODO: check if isCancelled in nested views.
- mActions[i] = mRV.mActions.get(i).initActionAsync(mTree, mParent, mHandler,
- mColorResources);
+ mActions[i] = mRV.mActions.get(i)
+ .initActionAsync(mTree, mParent, mApplyParams);
}
} else {
mActions = null;
@@ -5808,10 +5763,13 @@
try {
if (mActions != null) {
- InteractionHandler handler = mHandler == null
- ? DEFAULT_INTERACTION_HANDLER : mHandler;
+
+ ActionApplyParams applyParams = mApplyParams.clone();
+ if (applyParams.handler == null) {
+ applyParams.handler = DEFAULT_INTERACTION_HANDLER;
+ }
for (Action a : mActions) {
- a.apply(viewTree.mRoot, mParent, handler, mColorResources);
+ a.apply(viewTree.mRoot, mParent, applyParams);
}
}
// If the parent of the view is has is a root, resolve the recycling.
@@ -5859,18 +5817,43 @@
* the {@link #apply(Context,ViewGroup)} call.
*/
public void reapply(Context context, View v) {
- reapply(context, v, null /* handler */);
+ reapply(context, v, null /* size */, new ActionApplyParams());
}
/** @hide */
public void reapply(Context context, View v, InteractionHandler handler) {
- reapply(context, v, handler, null /* size */, null /* colorResources */);
+ reapply(context, v, null /* size */,
+ new ActionApplyParams().withInteractionHandler(handler));
}
/** @hide */
public void reapply(Context context, View v, InteractionHandler handler, SizeF size,
ColorResources colorResources) {
- reapply(context, v, handler, size, colorResources, true);
+ reapply(context, v, size, new ActionApplyParams()
+ .withInteractionHandler(handler).withColorResources(colorResources));
+ }
+
+ /** @hide */
+ public void reapply(Context context, View v, @Nullable SizeF size, ActionApplyParams params) {
+ reapply(context, v, (ViewGroup) v.getParent(), size, params, true);
+ }
+
+ private void reapplyNestedViews(Context context, View v, ViewGroup rootParent,
+ ActionApplyParams params) {
+ reapply(context, v, rootParent, null, params, false);
+ }
+
+ // Note: topLevel should be true only for calls on the topLevel RemoteViews, internal calls
+ // should set it to false.
+ private void reapply(Context context, View v, ViewGroup rootParent,
+ @Nullable SizeF size, ActionApplyParams params, boolean topLevel) {
+ RemoteViews rvToApply = getRemoteViewsToReapply(context, v, size);
+ rvToApply.performApply(v, rootParent, params);
+
+ // If the parent of the view is has is a root, resolve the recycling.
+ if (topLevel && v instanceof ViewGroup) {
+ finalizeViewRecycling((ViewGroup) v);
+ }
}
/** @hide */
@@ -5922,27 +5905,6 @@
return rvToApply;
}
- // Note: topLevel should be true only for calls on the topLevel RemoteViews, internal calls
- // should set it to false.
- private void reapply(Context context, View v, InteractionHandler handler, SizeF size,
- ColorResources colorResources, boolean topLevel) {
-
- RemoteViews rvToApply = getRemoteViewsToReapply(context, v, size);
-
- rvToApply.performApply(v, (ViewGroup) v.getParent(), handler, colorResources);
-
- // If the parent of the view is has is a root, resolve the recycling.
- if (topLevel && v instanceof ViewGroup) {
- finalizeViewRecycling((ViewGroup) v);
- }
- }
-
- private void reapplyNestedViews(Context context, View v, ViewGroup rootParent,
- InteractionHandler handler, SizeF size, ColorResources colorResources) {
- RemoteViews rvToApply = getRemoteViewsToReapply(context, v, size);
- rvToApply.performApply(v, rootParent, handler, colorResources);
- }
-
/**
* Applies all the actions to the provided view, moving as much of the task on the background
* thread as possible.
@@ -5973,19 +5935,25 @@
ColorResources colorResources) {
RemoteViews rvToApply = getRemoteViewsToReapply(context, v, size);
+ ActionApplyParams params = new ActionApplyParams()
+ .withColorResources(colorResources)
+ .withInteractionHandler(handler)
+ .withExecutor(executor);
+
return new AsyncApplyTask(rvToApply, (ViewGroup) v.getParent(),
- context, listener, handler, colorResources, v, true /* topLevel */)
+ context, listener, params, v, true /* topLevel */)
.startTaskOnExecutor(executor);
}
- private void performApply(View v, ViewGroup parent, InteractionHandler handler,
- ColorResources colorResources) {
+ private void performApply(View v, ViewGroup parent, ActionApplyParams params) {
+ params = params.clone();
+ if (params.handler == null) {
+ params.handler = DEFAULT_INTERACTION_HANDLER;
+ }
if (mActions != null) {
- handler = handler == null ? DEFAULT_INTERACTION_HANDLER : handler;
final int count = mActions.size();
for (int i = 0; i < count; i++) {
- Action a = mActions.get(i);
- a.apply(v, parent, handler, colorResources);
+ mActions.get(i).apply(v, parent, params);
}
}
}
@@ -6043,6 +6011,47 @@
}
/**
+ * Utility class to hold all the options when applying the remote views
+ * @hide
+ */
+ public class ActionApplyParams {
+
+ public InteractionHandler handler;
+ public ColorResources colorResources;
+ public Executor executor;
+ @StyleRes public int applyThemeResId;
+
+ @Override
+ public ActionApplyParams clone() {
+ return new ActionApplyParams()
+ .withInteractionHandler(handler)
+ .withColorResources(colorResources)
+ .withExecutor(executor)
+ .withThemeResId(applyThemeResId);
+ }
+
+ public ActionApplyParams withInteractionHandler(InteractionHandler handler) {
+ this.handler = handler;
+ return this;
+ }
+
+ public ActionApplyParams withColorResources(ColorResources colorResources) {
+ this.colorResources = colorResources;
+ return this;
+ }
+
+ public ActionApplyParams withThemeResId(@StyleRes int themeResId) {
+ this.applyThemeResId = themeResId;
+ return this;
+ }
+
+ public ActionApplyParams withExecutor(Executor executor) {
+ this.executor = executor;
+ return this;
+ }
+ }
+
+ /**
* Object allowing the modification of a context to overload the system's dynamic colors.
*
* Only colors from {@link android.R.color#system_accent1_0} to
@@ -6056,10 +6065,12 @@
// Size, in bytes, of an entry in the array of colors in an ARSC file.
private static final int ARSC_ENTRY_SIZE = 16;
- private ResourcesLoader mLoader;
+ private final ResourcesLoader mLoader;
+ private final SparseIntArray mColorMapping;
- private ColorResources(ResourcesLoader loader) {
+ private ColorResources(ResourcesLoader loader, SparseIntArray colorMapping) {
mLoader = loader;
+ mColorMapping = colorMapping;
}
/**
@@ -6071,6 +6082,10 @@
context.getResources().addLoaders(mLoader);
}
+ public SparseIntArray getColorMapping() {
+ return mColorMapping;
+ }
+
private static ByteArrayOutputStream readFileContent(InputStream input) throws IOException {
ByteArrayOutputStream content = new ByteArrayOutputStream(2048);
byte[] buffer = new byte[4096];
@@ -6145,7 +6160,7 @@
ResourcesLoader colorsLoader = new ResourcesLoader();
colorsLoader.addProvider(ResourcesProvider
.loadFromTable(pfd, null /* assetsProvider */));
- return new ColorResources(colorsLoader);
+ return new ColorResources(colorsLoader, colorMapping.clone());
}
}
} finally {
diff --git a/core/java/android/window/TaskFragmentOrganizer.java b/core/java/android/window/TaskFragmentOrganizer.java
index cc90aaf..e567ced 100644
--- a/core/java/android/window/TaskFragmentOrganizer.java
+++ b/core/java/android/window/TaskFragmentOrganizer.java
@@ -32,8 +32,10 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.SparseArray;
import android.view.RemoteAnimationDefinition;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
@@ -72,6 +74,12 @@
*/
private final Executor mExecutor;
+ // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next release.
+ /** Map from Task id to client tokens of TaskFragments in the Task. */
+ private final SparseArray<List<IBinder>> mTaskIdToFragmentTokens = new SparseArray<>();
+ /** Map from Task id to Task configuration. */
+ private final SparseArray<Configuration> mTaskIdToConfigurations = new SparseArray<>();
+
public TaskFragmentOrganizer(@NonNull Executor executor) {
mExecutor = executor;
}
@@ -161,6 +169,27 @@
@NonNull IBinder fragmentToken, @NonNull Configuration parentConfig) {}
/**
+ * Called when the parent leaf Task of organized TaskFragments is changed.
+ * When the leaf Task is changed, the organizer may want to update the TaskFragments in one
+ * transaction.
+ *
+ * For case like screen size change, it will trigger onTaskFragmentParentInfoChanged with new
+ * Task bounds, but may not trigger onTaskFragmentInfoChanged because there can be an override
+ * bounds.
+ * @hide
+ */
+ public void onTaskFragmentParentInfoChanged(int taskId, @NonNull Configuration parentConfig) {
+ // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next release.
+ final List<IBinder> tokens = mTaskIdToFragmentTokens.get(taskId);
+ if (tokens == null || tokens.isEmpty()) {
+ return;
+ }
+ for (int i = tokens.size() - 1; i >= 0; i--) {
+ onTaskFragmentParentInfoChanged(tokens.get(i), parentConfig);
+ }
+ }
+
+ /**
* Called when the {@link WindowContainerTransaction} created with
* {@link WindowContainerTransaction#setErrorCallbackToken(IBinder)} failed on the server side.
*
@@ -203,34 +232,43 @@
final List<TaskFragmentTransaction.Change> changes = transaction.getChanges();
for (TaskFragmentTransaction.Change change : changes) {
// TODO(b/240519866): apply all changes in one WCT.
+ final int taskId = change.getTaskId();
switch (change.getType()) {
case TYPE_TASK_FRAGMENT_APPEARED:
- onTaskFragmentAppeared(change.getTaskFragmentInfo());
- if (change.getTaskConfiguration() != null) {
- // TODO(b/240519866): convert to pass TaskConfiguration for all TFs in the
- // same Task
- onTaskFragmentParentInfoChanged(
- change.getTaskFragmentToken(),
- change.getTaskConfiguration());
+ // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next
+ // release.
+ if (!mTaskIdToFragmentTokens.contains(taskId)) {
+ mTaskIdToFragmentTokens.put(taskId, new ArrayList<>());
}
+ mTaskIdToFragmentTokens.get(taskId).add(change.getTaskFragmentToken());
+ onTaskFragmentParentInfoChanged(change.getTaskFragmentToken(),
+ mTaskIdToConfigurations.get(taskId));
+
+ onTaskFragmentAppeared(change.getTaskFragmentInfo());
break;
case TYPE_TASK_FRAGMENT_INFO_CHANGED:
- if (change.getTaskConfiguration() != null) {
- // TODO(b/240519866): convert to pass TaskConfiguration for all TFs in the
- // same Task
- onTaskFragmentParentInfoChanged(
- change.getTaskFragmentToken(),
- change.getTaskConfiguration());
- }
onTaskFragmentInfoChanged(change.getTaskFragmentInfo());
break;
case TYPE_TASK_FRAGMENT_VANISHED:
+ // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next
+ // release.
+ if (mTaskIdToFragmentTokens.contains(taskId)) {
+ final List<IBinder> tokens = mTaskIdToFragmentTokens.get(taskId);
+ tokens.remove(change.getTaskFragmentToken());
+ if (tokens.isEmpty()) {
+ mTaskIdToFragmentTokens.remove(taskId);
+ mTaskIdToConfigurations.remove(taskId);
+ }
+ }
+
onTaskFragmentVanished(change.getTaskFragmentInfo());
break;
case TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED:
- onTaskFragmentParentInfoChanged(
- change.getTaskFragmentToken(),
- change.getTaskConfiguration());
+ // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next
+ // release.
+ mTaskIdToConfigurations.put(taskId, change.getTaskConfiguration());
+
+ onTaskFragmentParentInfoChanged(taskId, change.getTaskConfiguration());
break;
case TYPE_TASK_FRAGMENT_ERROR:
final Bundle errorBundle = change.getErrorBundle();
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index dbfa4d3..48343803 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -66,6 +66,8 @@
private static final long INVALID_ID = -1;
public static final int NANOS_IN_MILLISECOND = 1_000_000;
+ private static final int MAX_LENGTH_EVENT_DESC = 20;
+
static final int REASON_END_UNKNOWN = -1;
static final int REASON_END_NORMAL = 0;
static final int REASON_END_SURFACE_DESTROYED = 1;
@@ -394,7 +396,18 @@
return true;
}
- private void markEvent(String desc) {
+ /**
+ * Mark the FrameTracker events in the trace.
+ *
+ * @param desc The description of the trace event,
+ * shouldn't exceed {@link #MAX_LENGTH_EVENT_DESC}.
+ */
+ private void markEvent(@NonNull String desc) {
+ if (desc.length() > MAX_LENGTH_EVENT_DESC) {
+ throw new IllegalArgumentException(TextUtils.formatSimple(
+ "The length of the trace event description <%s> exceeds %d",
+ desc, MAX_LENGTH_EVENT_DESC));
+ }
Trace.beginSection(TextUtils.formatSimple("%s#%s", mSession.getName(), desc));
Trace.endSection();
}
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index e625b31..72de78c 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -149,6 +149,10 @@
private static final int DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES = 3;
private static final int DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS = 64;
+ @VisibleForTesting
+ public static final int MAX_LENGTH_OF_CUJ_NAME = 80;
+ private static final int MAX_LENGTH_SESSION_NAME = 100;
+
public static final String ACTION_SESSION_END = ACTION_PREFIX + ".ACTION_SESSION_END";
public static final String ACTION_SESSION_CANCEL = ACTION_PREFIX + ".ACTION_SESSION_CANCEL";
@@ -732,6 +736,9 @@
* @return the name of the cuj type
*/
public static String getNameOfCuj(int cujType) {
+ // Please note:
+ // 1. The length of the returned string shouldn't exceed MAX_LENGTH_OF_CUJ_NAME.
+ // 2. The returned string should be the same with the name defined in atoms.proto.
switch (cujType) {
case CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE:
return "SHADE_EXPAND_COLLAPSE";
@@ -1106,9 +1113,27 @@
public Session(@CujType int cujType, @NonNull String postfix) {
mCujType = cujType;
mTimeStamp = System.nanoTime();
- mName = TextUtils.isEmpty(postfix)
- ? String.format("J<%s>", getNameOfCuj(mCujType))
- : String.format("J<%s::%s>", getNameOfCuj(mCujType), postfix);
+ mName = generateSessionName(getNameOfCuj(cujType), postfix);
+ }
+
+ private String generateSessionName(@NonNull String cujName, @NonNull String cujPostfix) {
+ final boolean hasPostfix = !TextUtils.isEmpty(cujPostfix);
+ // We assert that the cujName shouldn't exceed MAX_LENGTH_OF_CUJ_NAME.
+ if (cujName.length() > MAX_LENGTH_OF_CUJ_NAME) {
+ throw new IllegalArgumentException(TextUtils.formatSimple(
+ "The length of cuj name <%s> exceeds %d", cujName, MAX_LENGTH_OF_CUJ_NAME));
+ }
+ if (hasPostfix) {
+ final int remaining = MAX_LENGTH_SESSION_NAME - cujName.length();
+ if (cujPostfix.length() > remaining) {
+ cujPostfix = cujPostfix.substring(0, remaining - 3).concat("...");
+ }
+ }
+ // The max length of the whole string should be:
+ // 105 with postfix, 83 without postfix
+ return hasPostfix
+ ? TextUtils.formatSimple("J<%s::%s>", cujName, cujPostfix)
+ : TextUtils.formatSimple("J<%s>", cujName);
}
@CujType
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 0a29fc52..fa6fa55 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -1169,7 +1169,15 @@
}
+ /** @hide */
+ public static void startForWifi(Context context) {
+ new BinderCallsStats.SettingsObserver(
+ context,
+ new BinderCallsStats(
+ new BinderCallsStats.Injector(),
+ com.android.internal.os.BinderLatencyProto.Dims.WIFI));
+ }
/**
* Settings observer for other processes (not system_server).
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 578b588..2c9ef4f 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -339,6 +339,8 @@
// A map from package name of vendor APEXes that can be updated to an installer package name
// allowed to install updates for it.
private final ArrayMap<String, String> mAllowedVendorApexes = new ArrayMap<>();
+ // A set of package names that are allowed to use <install-constraints> manifest tag.
+ private final Set<String> mInstallConstraintsAllowlist = new ArraySet<>();
private String mModulesInstallerPackageName;
@@ -535,6 +537,10 @@
return mAllowedVendorApexes;
}
+ public Set<String> getInstallConstraintsAllowlist() {
+ return mInstallConstraintsAllowlist;
+ }
+
public String getModulesInstallerPackageName() {
return mModulesInstallerPackageName;
}
@@ -1455,6 +1461,20 @@
}
XmlUtils.skipCurrentTag(parser);
} break;
+ case "install-constraints-allowed": {
+ if (allowAppConfigs) {
+ String packageName = parser.getAttributeValue(null, "package");
+ if (packageName == null) {
+ Slog.w(TAG, "<" + name + "> without package in " + permFile
+ + " at " + parser.getPositionDescription());
+ } else {
+ mInstallConstraintsAllowlist.add(packageName);
+ }
+ } else {
+ logNotAllowedInPartition(name, permFile, parser);
+ }
+ XmlUtils.skipCurrentTag(parser);
+ } break;
default: {
Slog.w(TAG, "Tag " + name + " is unknown in "
+ permFile + " at " + parser.getPositionDescription());
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0acf703..062523e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -3607,4 +3607,19 @@
false, the application cannot be profiled at all. Defaults to true. -->
<attr name="enabled" format="boolean" />
</declare-styleable>
+
+ <!-- <code>install-constraints</code> tag rejects installs unless one the constraints defined by
+ its child elements is true.
+ It is possible to have multiple <code>install-constraints</code> tags in a single manifest,
+ where each tag is evaluated independently.
+ @hide -->
+ <declare-styleable name="AndroidManifestInstallConstraints" parent="AndroidManifest" />
+
+ <!-- A constraint for <code>install-constraints</code>. Checks that the device fingerprint
+ starts with the given prefix.
+ @hide -->
+ <declare-styleable name="AndroidManifestInstallConstraintsFingerprintPrefix"
+ parent="AndroidManifestInstallConstraints">
+ <attr name="value" />
+ </declare-styleable>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9d2c3d7..d176a1d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2629,6 +2629,10 @@
will be locked. -->
<bool name="config_multiuserDelayUserDataLocking">false</bool>
+ <!-- Whether the device allows users to start in background on secondary displays.
+ Should be false for most devices, except automotive vehicle with passenger displays. -->
+ <bool name="config_multiuserUsersOnSecondaryDisplays">false</bool>
+
<!-- Whether to automatically switch a non-primary user back to the primary user after a
timeout when the device is docked. -->
<bool name="config_enableTimeoutToUserZeroWhenDocked">false</bool>
@@ -5850,4 +5854,7 @@
<!-- Whether the wake screen on notifications feature is available. -->
<bool name="config_pulseOnNotificationsAvailable">true</bool>
+
+ <!-- The number of tasks to scan to get the visibility of Home -->
+ <integer name="config_maxScanTasksForHomeVisibility">10</integer>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index cb0393f..e6ae7b1 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -453,6 +453,7 @@
<java-symbol type="integer" name="config_multiuserMaximumUsers" />
<java-symbol type="integer" name="config_multiuserMaxRunningUsers" />
<java-symbol type="bool" name="config_multiuserDelayUserDataLocking" />
+ <java-symbol type="bool" name="config_multiuserUsersOnSecondaryDisplays" />
<java-symbol type="bool" name="config_enableTimeoutToUserZeroWhenDocked" />
<java-symbol type="integer" name="config_userTypePackageWhitelistMode"/>
<java-symbol type="xml" name="config_user_types" />
@@ -3977,6 +3978,8 @@
<java-symbol type="string" name="config_customCountryDetector" />
+ <java-symbol type="integer" name="config_maxScanTasksForHomeVisibility" />
+
<!-- For Foldables -->
<java-symbol type="array" name="config_foldedDeviceStates" />
<java-symbol type="array" name="config_deviceStatesOnWhichToWakeUp" />
diff --git a/core/tests/coretests/src/android/graphics/PathOffsetTest.java b/core/tests/coretests/src/android/graphics/PathOffsetTest.java
deleted file mode 100644
index 6cc42f6..0000000
--- a/core/tests/coretests/src/android/graphics/PathOffsetTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2008 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.graphics;
-
-import static org.junit.Assert.assertTrue;
-
-import android.graphics.Bitmap.Config;
-import android.graphics.Path.Direction;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class PathOffsetTest {
-
- private static final int SQUARE = 10;
- private static final int WIDTH = 100;
- private static final int HEIGHT = 100;
- private static final int START_X = 10;
- private static final int START_Y = 20;
- private static final int OFFSET_X = 30;
- private static final int OFFSET_Y = 40;
-
- @Test
- @SmallTest
- public void testPathOffset() {
- Path actualPath = new Path();
- actualPath.addRect(START_X, START_Y, START_X + SQUARE, START_Y + SQUARE, Direction.CW);
- assertTrue(actualPath.isSimplePath);
- actualPath.offset(OFFSET_X, OFFSET_Y);
- assertTrue(actualPath.isSimplePath);
-
- Path expectedPath = new Path();
- expectedPath.addRect(START_X + OFFSET_X, START_Y + OFFSET_Y, START_X + OFFSET_X + SQUARE,
- START_Y + OFFSET_Y + SQUARE, Direction.CW);
-
- assertPaths(actualPath, expectedPath);
- }
-
- @Test
- @SmallTest
- public void testPathOffsetWithDestination() {
- Path initialPath = new Path();
- initialPath.addRect(START_X, START_Y, START_X + SQUARE, START_Y + SQUARE, Direction.CW);
- Path actualPath = new Path();
- assertTrue(initialPath.isSimplePath);
- assertTrue(actualPath.isSimplePath);
- initialPath.offset(OFFSET_X, OFFSET_Y, actualPath);
- assertTrue(actualPath.isSimplePath);
-
- Path expectedPath = new Path();
- expectedPath.addRect(START_X + OFFSET_X, START_Y + OFFSET_Y, START_X + OFFSET_X + SQUARE,
- START_Y + OFFSET_Y + SQUARE, Direction.CW);
-
- assertPaths(actualPath, expectedPath);
- }
-
- private static void assertPaths(Path actual, Path expected) {
- Bitmap actualBitmap = drawAndGetBitmap(actual);
- Bitmap expectedBitmap = drawAndGetBitmap(expected);
- assertTrue(actualBitmap.sameAs(expectedBitmap));
- }
-
- private static Bitmap drawAndGetBitmap(Path path) {
- Bitmap bitmap = Bitmap.createBitmap(WIDTH, HEIGHT, Config.ARGB_8888);
- bitmap.eraseColor(Color.BLACK);
- Paint paint = new Paint();
- paint.setColor(Color.RED);
- Canvas canvas = new Canvas(bitmap);
- canvas.drawPath(path, paint);
- return bitmap;
- }
-
-}
diff --git a/core/tests/coretests/src/android/graphics/PathTest.java b/core/tests/coretests/src/android/graphics/PathTest.java
deleted file mode 100644
index b50792c..0000000
--- a/core/tests/coretests/src/android/graphics/PathTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2013 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.graphics;
-
-import androidx.test.filters.SmallTest;
-
-import junit.framework.TestCase;
-
-public class PathTest extends TestCase {
-
- @SmallTest
- public void testResetPreservesFillType() throws Exception {
- Path path = new Path();
-
- final Path.FillType defaultFillType = path.getFillType();
- final Path.FillType fillType = Path.FillType.INVERSE_EVEN_ODD;
-
- // This test is only meaningful if it changes from the default.
- assertFalse(fillType.equals(defaultFillType));
-
- path.setFillType(fillType);
- path.reset();
- assertEquals(path.getFillType(), fillType);
- }
-}
diff --git a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
index d96f041..1519e48 100644
--- a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
@@ -16,10 +16,26 @@
package com.android.internal.jank;
+import static android.text.TextUtils.formatSimple;
+
import static com.android.internal.jank.FrameTracker.REASON_CANCEL_TIMEOUT;
import static com.android.internal.jank.FrameTracker.REASON_END_NORMAL;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_LAUNCH_CAMERA;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_ADD;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_APP_START;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_HEADS_UP_APPEAR;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_REMOVE;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_ROW_EXPAND;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_ROW_SWIPE;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_SPLIT_SCREEN_RESIZE;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_TO_STATSD_INTERACTION_TYPE;
+import static com.android.internal.jank.InteractionJankMonitor.MAX_LENGTH_OF_CUJ_NAME;
+import static com.android.internal.jank.InteractionJankMonitor.getNameOfCuj;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -38,6 +54,7 @@
import android.os.HandlerThread;
import android.os.SystemClock;
import android.provider.DeviceConfig;
+import android.util.SparseArray;
import android.view.View;
import android.view.ViewAttachTestActivity;
@@ -52,8 +69,12 @@
import com.android.internal.jank.FrameTracker.ViewRootWrapper;
import com.android.internal.jank.InteractionJankMonitor.Configuration;
import com.android.internal.jank.InteractionJankMonitor.Session;
+import com.android.internal.util.FrameworkStatsLog;
+
+import com.google.common.truth.Expect;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -64,11 +85,17 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
@SmallTest
public class InteractionJankMonitorTest {
private static final String CUJ_POSTFIX = "";
+ private static final SparseArray<String> ENUM_NAME_EXCEPTION_MAP = new SparseArray<>();
+ private static final SparseArray<String> CUJ_NAME_EXCEPTION_MAP = new SparseArray<>();
+ private static final String ENUM_NAME_PREFIX =
+ "UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__";
+
private ViewAttachTestActivity mActivity;
private View mView;
private HandlerThread mWorker;
@@ -77,6 +104,53 @@
public ActivityTestRule<ViewAttachTestActivity> mRule =
new ActivityTestRule<>(ViewAttachTestActivity.class);
+ @Rule
+ public final Expect mExpect = Expect.create();
+
+ @BeforeClass
+ public static void initialize() {
+ ENUM_NAME_EXCEPTION_MAP.put(CUJ_NOTIFICATION_ADD, getEnumName("SHADE_NOTIFICATION_ADD"));
+ ENUM_NAME_EXCEPTION_MAP.put(CUJ_NOTIFICATION_APP_START, getEnumName("SHADE_APP_LAUNCH"));
+ ENUM_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_HEADS_UP_APPEAR, getEnumName("SHADE_HEADS_UP_APPEAR"));
+ ENUM_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_HEADS_UP_DISAPPEAR, getEnumName("SHADE_HEADS_UP_DISAPPEAR"));
+ ENUM_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_REMOVE, getEnumName("SHADE_NOTIFICATION_REMOVE"));
+ ENUM_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, getEnumName("NOTIFICATION_SHADE_SWIPE"));
+ ENUM_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE, getEnumName("SHADE_QS_EXPAND_COLLAPSE"));
+ ENUM_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE, getEnumName("SHADE_QS_SCROLL_SWIPE"));
+ ENUM_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_SHADE_ROW_EXPAND, getEnumName("SHADE_ROW_EXPAND"));
+ ENUM_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_SHADE_ROW_SWIPE, getEnumName("SHADE_ROW_SWIPE"));
+ ENUM_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_SHADE_SCROLL_FLING, getEnumName("SHADE_SCROLL_FLING"));
+
+ CUJ_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE, "CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE");
+ CUJ_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE,
+ "CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE");
+ CUJ_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE, "CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE");
+ CUJ_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_SHADE_ROW_EXPAND, "CUJ_NOTIFICATION_SHADE_ROW_EXPAND");
+ CUJ_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_SHADE_ROW_SWIPE, "CUJ_NOTIFICATION_SHADE_ROW_SWIPE");
+ CUJ_NAME_EXCEPTION_MAP.put(
+ CUJ_NOTIFICATION_SHADE_SCROLL_FLING, "CUJ_NOTIFICATION_SHADE_SCROLL_FLING");
+ CUJ_NAME_EXCEPTION_MAP.put(CUJ_LOCKSCREEN_LAUNCH_CAMERA, "CUJ_LOCKSCREEN_LAUNCH_CAMERA");
+ CUJ_NAME_EXCEPTION_MAP.put(CUJ_SPLIT_SCREEN_RESIZE, "CUJ_SPLIT_SCREEN_RESIZE");
+ }
+
+ private static String getEnumName(String name) {
+ return formatSimple("%s%s", ENUM_NAME_PREFIX, name);
+ }
+
@Before
public void setup() {
// Prepare an activity for getting ThreadedRenderer later.
@@ -174,6 +248,82 @@
}
}
+ @Test
+ public void testCujsMapToEnumsCorrectly() {
+ List<Field> cujs = Arrays.stream(InteractionJankMonitor.class.getDeclaredFields())
+ .filter(f -> f.getName().startsWith("CUJ_")
+ && Modifier.isStatic(f.getModifiers())
+ && f.getType() == int.class)
+ .collect(Collectors.toList());
+
+ Map<Integer, String> enumsMap = Arrays.stream(FrameworkStatsLog.class.getDeclaredFields())
+ .filter(f -> f.getName().startsWith(ENUM_NAME_PREFIX)
+ && Modifier.isStatic(f.getModifiers())
+ && f.getType() == int.class)
+ .collect(Collectors.toMap(this::getIntFieldChecked, Field::getName));
+
+ cujs.forEach(f -> {
+ final int cuj = getIntFieldChecked(f);
+ final String cujName = f.getName();
+ final String expectedEnumName = ENUM_NAME_EXCEPTION_MAP.contains(cuj)
+ ? ENUM_NAME_EXCEPTION_MAP.get(cuj)
+ : formatSimple("%s%s", ENUM_NAME_PREFIX, cujName.substring(4));
+ final int enumKey = CUJ_TO_STATSD_INTERACTION_TYPE[cuj];
+ final String enumName = enumsMap.get(enumKey);
+ final String expectedNameOfCuj = CUJ_NAME_EXCEPTION_MAP.contains(cuj)
+ ? CUJ_NAME_EXCEPTION_MAP.get(cuj)
+ : formatSimple("CUJ_%s", getNameOfCuj(cuj));
+ mExpect
+ .withMessage(formatSimple(
+ "%s (%d) not matches %s (%d)", cujName, cuj, enumName, enumKey))
+ .that(expectedEnumName.equals(enumName))
+ .isTrue();
+ mExpect
+ .withMessage(formatSimple("getNameOfCuj(%d) not matches %s", cuj, cujName))
+ .that(cujName.equals(expectedNameOfCuj))
+ .isTrue();
+ });
+ }
+
+ @Test
+ public void testCujNameLimit() {
+ Arrays.stream(InteractionJankMonitor.class.getDeclaredFields())
+ .filter(f -> f.getName().startsWith("CUJ_")
+ && Modifier.isStatic(f.getModifiers())
+ && f.getType() == int.class)
+ .forEach(f -> {
+ final int cuj = getIntFieldChecked(f);
+ mExpect
+ .withMessage(formatSimple(
+ "Too long CUJ(%d) name: %s", cuj, getNameOfCuj(cuj)))
+ .that(getNameOfCuj(cuj).length())
+ .isAtMost(MAX_LENGTH_OF_CUJ_NAME);
+ });
+ }
+
+ @Test
+ public void testSessionNameLengthLimit() {
+ final int cujType = CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE;
+ final String cujName = getNameOfCuj(cujType);
+ final String cujTag = "ThisIsTheCujTag";
+ final String tooLongTag = cujTag.repeat(10);
+
+ // Normal case, no postfix.
+ Session noPostfix = new Session(cujType, "");
+ assertThat(noPostfix.getName()).isEqualTo(formatSimple("J<%s>", cujName));
+
+ // Normal case, with postfix.
+ Session withPostfix = new Session(cujType, cujTag);
+ assertThat(withPostfix.getName()).isEqualTo(formatSimple("J<%s::%s>", cujName, cujTag));
+
+ // Since the length of the cuj name is tested in another test, no need to test it here.
+ // Too long postfix case, should trim the postfix and keep the cuj name completed.
+ final String expectedTrimmedName = formatSimple("J<%s::%s>", cujName,
+ "ThisIsTheCujTagThisIsTheCujTagThisIsTheCujTagThisIsTheCujTagThisIsTheCujTagT...");
+ Session longPostfix = new Session(cujType, tooLongTag);
+ assertThat(longPostfix.getName()).isEqualTo(expectedTrimmedName);
+ }
+
private InteractionJankMonitor createMockedInteractionJankMonitor() {
InteractionJankMonitor monitor = spy(new InteractionJankMonitor(mWorker));
doReturn(true).when(monitor).shouldMonitor(anyInt());
@@ -217,4 +367,12 @@
return tracker;
}
+
+ private int getIntFieldChecked(Field field) {
+ try {
+ return field.getInt(null);
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
}
diff --git a/core/tests/mockingcoretests/src/android/os/BundleRecyclingTest.java b/core/tests/mockingcoretests/src/android/os/BundleRecyclingTest.java
index 7c76498..c88ab90 100644
--- a/core/tests/mockingcoretests/src/android/os/BundleRecyclingTest.java
+++ b/core/tests/mockingcoretests/src/android/os/BundleRecyclingTest.java
@@ -23,6 +23,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -34,7 +35,6 @@
import com.android.dx.mockito.inline.extended.StaticMockitoSession;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.quality.Strictness;
@@ -56,16 +56,11 @@
private Parcel mParcelSpy;
private Bundle mBundle;
- @Before
- public void setUp() throws Exception {
- setUpBundle(/* hasLazy */ true);
- }
-
@Test
public void bundleClear_whenUnparcelledWithoutLazy_recyclesParcelOnce() {
- setUpBundle(/* hasLazy */ false);
+ setUpBundle(/* lazy */ 0, /* nonLazy */ 1);
// Will unparcel and immediately recycle parcel
- assertNotNull(mBundle.getString("key"));
+ assertNotNull(mBundle.getString("nonLazy0"));
verify(mParcelSpy, times(1)).recycle();
assertFalse(mBundle.isDefinitelyEmpty());
@@ -77,6 +72,7 @@
@Test
public void bundleClear_whenParcelled_recyclesParcel() {
+ setUpBundle(/* lazy */ 1);
assertTrue(mBundle.isParcelled());
verify(mParcelSpy, times(0)).recycle();
@@ -90,23 +86,9 @@
}
@Test
- public void bundleClear_whenUnparcelledWithLazyValueUnwrapped_recyclesParcel() {
- // Will unparcel with a lazy value, and immediately unwrap the lazy value,
- // with no lazy values left at the end of getParcelable
- assertNotNull(mBundle.getParcelable("key", CustomParcelable.class));
- verify(mParcelSpy, times(0)).recycle();
-
- mBundle.clear();
- verify(mParcelSpy, times(1)).recycle();
- assertTrue(mBundle.isDefinitelyEmpty());
-
- // Should not recycle again
- mBundle.clear();
- verify(mParcelSpy, times(1)).recycle();
- }
-
- @Test
public void bundleClear_whenUnparcelledWithLazy_recyclesParcel() {
+ setUpBundle(/* lazy */ 1);
+
// Will unparcel but keep the CustomParcelable lazy
assertFalse(mBundle.isEmpty());
verify(mParcelSpy, times(0)).recycle();
@@ -122,6 +104,8 @@
@Test
public void bundleClear_whenClearedWithSharedParcel_doesNotRecycleParcel() {
+ setUpBundle(/* lazy */ 1);
+
Bundle copy = new Bundle();
copy.putAll(mBundle);
@@ -136,6 +120,8 @@
@Test
public void bundleClear_whenClearedWithCopiedParcel_doesNotRecycleParcel() {
+ setUpBundle(/* lazy */ 1);
+
// Will unparcel but keep the CustomParcelable lazy
assertFalse(mBundle.isEmpty());
@@ -151,7 +137,101 @@
verify(mParcelSpy, never()).recycle();
}
- private void setUpBundle(boolean hasLazy) {
+ @Test
+ public void bundleGet_whenUnparcelledWithLazyValueUnwrapped_recyclesParcel() {
+ setUpBundle(/* lazy */ 1);
+
+ // Will unparcel with a lazy value, and immediately unwrap the lazy value,
+ // with no lazy values left at the end of getParcelable
+ // Ref counting should immediately recycle
+ assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+ verify(mParcelSpy, times(1)).recycle();
+
+ // Should not recycle again
+ assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+ mBundle.clear();
+ verify(mParcelSpy, times(1)).recycle();
+ }
+
+ @Test
+ public void bundleGet_whenMultipleLazy_recyclesParcelWhenAllUnwrapped() {
+ setUpBundle(/* lazy */ 2);
+
+ assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+ verify(mParcelSpy, times(0)).recycle();
+
+ assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+ verify(mParcelSpy, times(0)).recycle();
+
+ assertNotNull(mBundle.getParcelable("lazy1", CustomParcelable.class));
+ verify(mParcelSpy, times(1)).recycle();
+
+ // Should not recycle again
+ assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+ mBundle.clear();
+ verify(mParcelSpy, times(1)).recycle();
+ assertTrue(mBundle.isDefinitelyEmpty());
+ }
+
+ @Test
+ public void bundleGet_whenLazyAndNonLazy_recyclesParcelWhenAllUnwrapped() {
+ setUpBundle(/* lazy */ 1, /* nonLazy */ 1);
+
+ assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+ verify(mParcelSpy, times(1)).recycle();
+
+ // Should not recycle again
+ assertNotNull(mBundle.getString("nonLazy0"));
+ assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+ mBundle.clear();
+ verify(mParcelSpy, times(1)).recycle();
+ }
+
+ @Test
+ public void bundleGet_whenLazyAndNonLazy_doesNotRecycleWhenOnlyNonLazyRetrieved() {
+ setUpBundle(/* lazy */ 1, /* nonLazy */ 1);
+
+ assertNotNull(mBundle.getString("nonLazy0"));
+ verify(mParcelSpy, times(0)).recycle();
+
+ assertNotNull(mBundle.getString("nonLazy0"));
+ verify(mParcelSpy, times(0)).recycle();
+
+ assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+ verify(mParcelSpy, times(1)).recycle();
+ }
+
+ @Test
+ public void bundleGet_withWithSharedParcel_doesNotRecycleParcel() {
+ setUpBundle(/* lazy */ 1);
+
+ Bundle copy = new Bundle();
+ copy.putAll(mBundle);
+
+ assertNotNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+ mBundle.clear();
+
+ assertNotNull(copy.getParcelable("lazy0", CustomParcelable.class));
+ copy.clear();
+
+ verify(mParcelSpy, never()).recycle();
+ }
+
+ @Test
+ public void bundleGet_getAfterLazyCleared_doesNotRecycleAgain() {
+ setUpBundle(/* lazy */ 1);
+ mBundle.clear();
+ verify(mParcelSpy, times(1)).recycle();
+
+ assertNull(mBundle.getParcelable("lazy0", CustomParcelable.class));
+ verify(mParcelSpy, times(1)).recycle();
+ }
+
+ private void setUpBundle(int lazy) {
+ setUpBundle(lazy, /* nonLazy */ 0);
+ }
+
+ private void setUpBundle(int lazy, int nonLazy) {
AtomicReference<Parcel> parcel = new AtomicReference<>();
StaticMockitoSession session = mockitoSession()
.strictness(Strictness.STRICT_STUBS)
@@ -166,7 +246,7 @@
Bundle bundle = new Bundle();
bundle.setClassLoader(getClass().getClassLoader());
- Parcel p = createBundle(hasLazy);
+ Parcel p = createBundle(lazy, nonLazy);
bundle.readFromParcel(p);
p.recycle();
@@ -179,13 +259,17 @@
/**
* Create a test bundle, parcel it and return the parcel.
*/
- private Parcel createBundle(boolean hasLazy) {
+ private Parcel createBundle(int lazy, int nonLazy) {
final Bundle source = new Bundle();
- if (hasLazy) {
- source.putParcelable("key", new CustomParcelable(13, "Tiramisu"));
- } else {
- source.putString("key", "tiramisu");
+
+ for (int i = 0; i < nonLazy; i++) {
+ source.putString("nonLazy" + i, "Tiramisu");
}
+
+ for (int i = 0; i < lazy; i++) {
+ source.putParcelable("lazy" + i, new CustomParcelable(13, "Tiramisu"));
+ }
+
return getParcelledBundle(source);
}
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index 425a378..a8ab6d9 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -330,11 +330,7 @@
public void drawPath(@NonNull Path path, @NonNull Paint paint) {
throwIfHasHwFeaturesInSwMode(paint);
- if (path.isSimplePath && path.rects != null) {
- nDrawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
- } else {
- nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
- }
+ nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
}
public void drawPoint(float x, float y, @NonNull Paint paint) {
diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java
index a998ba8..d06f665 100644
--- a/graphics/java/android/graphics/BaseRecordingCanvas.java
+++ b/graphics/java/android/graphics/BaseRecordingCanvas.java
@@ -286,11 +286,7 @@
@Override
public final void drawPath(@NonNull Path path, @NonNull Paint paint) {
- if (path.isSimplePath && path.rects != null) {
- nDrawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
- } else {
- nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
- }
+ nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
}
@Override
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index e5ef10d..afcaabe 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -20,8 +20,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
@@ -47,18 +45,6 @@
public final long mNativePath;
/**
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public boolean isSimplePath = true;
- /**
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public Region rects;
- private Direction mLastDirection = null;
-
- /**
* Create an empty path
*/
public Path() {
@@ -72,15 +58,7 @@
* @param src The path to copy from when initializing the new path
*/
public Path(@Nullable Path src) {
- long valNative = 0;
- if (src != null) {
- valNative = src.mNativePath;
- isSimplePath = src.isSimplePath;
- if (src.rects != null) {
- rects = new Region(src.rects);
- }
- }
- mNativePath = nInit(valNative);
+ mNativePath = nInit(src != null ? src.mNativePath : 0);
sRegistry.registerNativeAllocation(this, mNativePath);
}
@@ -89,9 +67,6 @@
* This does NOT change the fill-type setting.
*/
public void reset() {
- isSimplePath = true;
- mLastDirection = null;
- if (rects != null) rects.setEmpty();
// We promised not to change this, so preserve it around the native
// call, which does now reset fill type.
final FillType fillType = getFillType();
@@ -104,9 +79,6 @@
* keeps the internal data structure for faster reuse.
*/
public void rewind() {
- isSimplePath = true;
- mLastDirection = null;
- if (rects != null) rects.setEmpty();
nRewind(mNativePath);
}
@@ -116,19 +88,7 @@
if (this == src) {
return;
}
- isSimplePath = src.isSimplePath;
nSet(mNativePath, src.mNativePath);
- if (!isSimplePath) {
- return;
- }
-
- if (rects != null && src.rects != null) {
- rects.set(src.rects);
- } else if (rects != null && src.rects == null) {
- rects.setEmpty();
- } else if (src.rects != null) {
- rects = new Region(src.rects);
- }
}
/**
@@ -192,12 +152,7 @@
* @see #op(Path, android.graphics.Path.Op)
*/
public boolean op(@NonNull Path path1, @NonNull Path path2, @NonNull Op op) {
- if (nOp(path1.mNativePath, path2.mNativePath, op.ordinal(), this.mNativePath)) {
- isSimplePath = false;
- rects = null;
- return true;
- }
- return false;
+ return nOp(path1.mNativePath, path2.mNativePath, op.ordinal(), this.mNativePath);
}
/**
@@ -378,7 +333,6 @@
* @param y The y-coordinate of the end of a line
*/
public void lineTo(float x, float y) {
- isSimplePath = false;
nLineTo(mNativePath, x, y);
}
@@ -393,7 +347,6 @@
* this contour, to specify a line
*/
public void rLineTo(float dx, float dy) {
- isSimplePath = false;
nRLineTo(mNativePath, dx, dy);
}
@@ -408,7 +361,6 @@
* @param y2 The y-coordinate of the end point on a quadratic curve
*/
public void quadTo(float x1, float y1, float x2, float y2) {
- isSimplePath = false;
nQuadTo(mNativePath, x1, y1, x2, y2);
}
@@ -427,7 +379,6 @@
* this contour, for the end point of a quadratic curve
*/
public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
- isSimplePath = false;
nRQuadTo(mNativePath, dx1, dy1, dx2, dy2);
}
@@ -445,7 +396,6 @@
*/
public void cubicTo(float x1, float y1, float x2, float y2,
float x3, float y3) {
- isSimplePath = false;
nCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
}
@@ -456,7 +406,6 @@
*/
public void rCubicTo(float x1, float y1, float x2, float y2,
float x3, float y3) {
- isSimplePath = false;
nRCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
}
@@ -507,7 +456,6 @@
*/
public void arcTo(float left, float top, float right, float bottom, float startAngle,
float sweepAngle, boolean forceMoveTo) {
- isSimplePath = false;
nArcTo(mNativePath, left, top, right, bottom, startAngle, sweepAngle, forceMoveTo);
}
@@ -516,7 +464,6 @@
* first point of the contour, a line segment is automatically added.
*/
public void close() {
- isSimplePath = false;
nClose(mNativePath);
}
@@ -536,18 +483,6 @@
final int nativeInt;
}
- private void detectSimplePath(float left, float top, float right, float bottom, Direction dir) {
- if (mLastDirection == null) {
- mLastDirection = dir;
- }
- if (mLastDirection != dir) {
- isSimplePath = false;
- } else {
- if (rects == null) rects = new Region();
- rects.op((int) left, (int) top, (int) right, (int) bottom, Region.Op.UNION);
- }
- }
-
/**
* Add a closed rectangle contour to the path
*
@@ -568,7 +503,6 @@
* @param dir The direction to wind the rectangle's contour
*/
public void addRect(float left, float top, float right, float bottom, @NonNull Direction dir) {
- detectSimplePath(left, top, right, bottom, dir);
nAddRect(mNativePath, left, top, right, bottom, dir.nativeInt);
}
@@ -588,7 +522,6 @@
* @param dir The direction to wind the oval's contour
*/
public void addOval(float left, float top, float right, float bottom, @NonNull Direction dir) {
- isSimplePath = false;
nAddOval(mNativePath, left, top, right, bottom, dir.nativeInt);
}
@@ -601,7 +534,6 @@
* @param dir The direction to wind the circle's contour
*/
public void addCircle(float x, float y, float radius, @NonNull Direction dir) {
- isSimplePath = false;
nAddCircle(mNativePath, x, y, radius, dir.nativeInt);
}
@@ -624,7 +556,6 @@
*/
public void addArc(float left, float top, float right, float bottom, float startAngle,
float sweepAngle) {
- isSimplePath = false;
nAddArc(mNativePath, left, top, right, bottom, startAngle, sweepAngle);
}
@@ -649,7 +580,6 @@
*/
public void addRoundRect(float left, float top, float right, float bottom, float rx, float ry,
@NonNull Direction dir) {
- isSimplePath = false;
nAddRoundRect(mNativePath, left, top, right, bottom, rx, ry, dir.nativeInt);
}
@@ -682,7 +612,6 @@
if (radii.length < 8) {
throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values");
}
- isSimplePath = false;
nAddRoundRect(mNativePath, left, top, right, bottom, radii, dir.nativeInt);
}
@@ -693,7 +622,6 @@
* @param dx The amount to translate the path in X as it is added
*/
public void addPath(@NonNull Path src, float dx, float dy) {
- isSimplePath = false;
nAddPath(mNativePath, src.mNativePath, dx, dy);
}
@@ -703,7 +631,6 @@
* @param src The path that is appended to the current path
*/
public void addPath(@NonNull Path src) {
- isSimplePath = false;
nAddPath(mNativePath, src.mNativePath);
}
@@ -713,7 +640,6 @@
* @param src The path to add as a new contour
*/
public void addPath(@NonNull Path src, @NonNull Matrix matrix) {
- if (!src.isSimplePath) isSimplePath = false;
nAddPath(mNativePath, src.mNativePath, matrix.ni());
}
@@ -741,15 +667,6 @@
* @param dy The amount in the Y direction to offset the entire path
*/
public void offset(float dx, float dy) {
- if (isSimplePath && rects == null) {
- // nothing to offset
- return;
- }
- if (isSimplePath && dx == Math.rint(dx) && dy == Math.rint(dy)) {
- rects.translate((int) dx, (int) dy);
- } else {
- isSimplePath = false;
- }
nOffset(mNativePath, dx, dy);
}
@@ -760,7 +677,6 @@
* @param dy The new Y coordinate for the last point
*/
public void setLastPoint(float dx, float dy) {
- isSimplePath = false;
nSetLastPoint(mNativePath, dx, dy);
}
@@ -773,12 +689,7 @@
* then the the original path is modified
*/
public void transform(@NonNull Matrix matrix, @Nullable Path dst) {
- long dstNative = 0;
- if (dst != null) {
- dst.isSimplePath = false;
- dstNative = dst.mNativePath;
- }
- nTransform(mNativePath, matrix.ni(), dstNative);
+ nTransform(mNativePath, matrix.ni(), dst != null ? dst.mNativePath : 0);
}
/**
@@ -787,7 +698,6 @@
* @param matrix The matrix to apply to the path
*/
public void transform(@NonNull Matrix matrix) {
- isSimplePath = false;
nTransform(mNativePath, matrix.ni());
}
@@ -797,7 +707,6 @@
}
final long mutateNI() {
- isSimplePath = false;
return mNativePath;
}
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 8ae0d3d..25e1922 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1557,16 +1557,6 @@
return Arrays.binarySearch(mSupportedAxes, axis) >= 0;
}
- /** @hide */
- public List<FontFamily> getFallback() {
- ArrayList<FontFamily> families = new ArrayList<>();
- int familySize = nativeGetFamilySize(native_instance);
- for (int i = 0; i < familySize; ++i) {
- families.add(new FontFamily(nativeGetFamily(native_instance, i)));
- }
- return families;
- }
-
private static native long nativeCreateFromTypeface(long native_instance, int style);
private static native long nativeCreateFromTypefaceWithExactStyle(
long native_instance, int weight, boolean italic);
@@ -1592,13 +1582,6 @@
@CriticalNative
private static native long nativeGetReleaseFunc();
- @CriticalNative
- private static native int nativeGetFamilySize(long naitvePtr);
-
- @CriticalNative
- private static native long nativeGetFamily(long nativePtr, int index);
-
-
private static native void nativeRegisterGenericFamily(String str, long nativePtr);
private static native int nativeWriteTypefaces(
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
index 0dba6b0..d42fca2 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
@@ -51,12 +51,6 @@
@VisibleForTesting
final Map<IBinder, TaskFragmentInfo> mFragmentInfos = new ArrayMap<>();
- /**
- * Mapping from the client assigned unique token to the TaskFragment parent
- * {@link Configuration}.
- */
- final Map<IBinder, Configuration> mFragmentParentConfigs = new ArrayMap<>();
-
private final TaskFragmentCallback mCallback;
@VisibleForTesting
TaskFragmentAnimationController mAnimationController;
@@ -68,8 +62,7 @@
void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo);
void onTaskFragmentInfoChanged(@NonNull TaskFragmentInfo taskFragmentInfo);
void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo);
- void onTaskFragmentParentInfoChanged(@NonNull IBinder fragmentToken,
- @NonNull Configuration parentConfig);
+ void onTaskFragmentParentInfoChanged(int taskId, @NonNull Configuration parentConfig);
void onActivityReparentToTask(int taskId, @NonNull Intent activityIntent,
@NonNull IBinder activityToken);
void onTaskFragmentError(@Nullable TaskFragmentInfo taskFragmentInfo, int opType);
@@ -300,7 +293,6 @@
@Override
public void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo) {
mFragmentInfos.remove(taskFragmentInfo.getFragmentToken());
- mFragmentParentConfigs.remove(taskFragmentInfo.getFragmentToken());
if (mCallback != null) {
mCallback.onTaskFragmentVanished(taskFragmentInfo);
@@ -308,12 +300,9 @@
}
@Override
- public void onTaskFragmentParentInfoChanged(
- @NonNull IBinder fragmentToken, @NonNull Configuration parentConfig) {
- mFragmentParentConfigs.put(fragmentToken, parentConfig);
-
+ public void onTaskFragmentParentInfoChanged(int taskId, @NonNull Configuration parentConfig) {
if (mCallback != null) {
- mCallback.onTaskFragmentParentInfoChanged(fragmentToken, parentConfig);
+ mCallback.onTaskFragmentParentInfoChanged(taskId, parentConfig);
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index c688080..dad0739 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -155,6 +155,9 @@
container.setInfo(taskFragmentInfo);
if (container.isFinished()) {
mPresenter.cleanupContainer(container, false /* shouldFinishDependent */);
+ } else {
+ // Update with the latest Task configuration.
+ mPresenter.updateContainer(container);
}
updateCallbackIfNecessary();
}
@@ -233,19 +236,30 @@
}
@Override
- public void onTaskFragmentParentInfoChanged(@NonNull IBinder fragmentToken,
- @NonNull Configuration parentConfig) {
+ public void onTaskFragmentParentInfoChanged(int taskId, @NonNull Configuration parentConfig) {
synchronized (mLock) {
- final TaskFragmentContainer container = getContainer(fragmentToken);
- if (container != null) {
- onTaskConfigurationChanged(container.getTaskId(), parentConfig);
- if (isInPictureInPicture(parentConfig)) {
- // No need to update presentation in PIP until the Task exit PIP.
- return;
- }
- mPresenter.updateContainer(container);
- updateCallbackIfNecessary();
+ onTaskConfigurationChanged(taskId, parentConfig);
+ if (isInPictureInPicture(parentConfig)) {
+ // No need to update presentation in PIP until the Task exit PIP.
+ return;
}
+ final TaskContainer taskContainer = getTaskContainer(taskId);
+ if (taskContainer == null || taskContainer.isEmpty()) {
+ Log.e(TAG, "onTaskFragmentParentInfoChanged on empty Task id=" + taskId);
+ return;
+ }
+ // Update all TaskFragments in the Task. Make a copy of the list since some may be
+ // removed on updating.
+ final List<TaskFragmentContainer> containers =
+ new ArrayList<>(taskContainer.mContainers);
+ for (int i = containers.size() - 1; i >= 0; i--) {
+ final TaskFragmentContainer container = containers.get(i);
+ // Wait until onTaskFragmentAppeared to update new container.
+ if (!container.isFinished() && !container.isWaitingActivityAppear()) {
+ mPresenter.updateContainer(container);
+ }
+ }
+ updateCallbackIfNecessary();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 31fc6a5..2c02006 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -452,6 +452,7 @@
*/
void setEntry(@NonNull final BubbleEntry entry) {
Objects.requireNonNull(entry);
+ boolean showingDotPreviously = showDot();
mLastUpdated = entry.getStatusBarNotification().getPostTime();
mIsBubble = entry.getStatusBarNotification().getNotification().isBubbleNotification();
mPackageName = entry.getStatusBarNotification().getPackageName();
@@ -498,6 +499,10 @@
mShouldSuppressNotificationDot = entry.shouldSuppressNotificationDot();
mShouldSuppressNotificationList = entry.shouldSuppressNotificationList();
mShouldSuppressPeek = entry.shouldSuppressPeek();
+ if (showingDotPreviously != showDot()) {
+ // This will update the UI if needed
+ setShowDot(showDot());
+ }
}
@Nullable
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java
index 4eeb207..d6803e8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java
@@ -19,14 +19,14 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Paint;
+import android.graphics.Color;
import android.graphics.Path;
+import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.Drawable;
import com.android.launcher3.icons.BaseIconFactory;
import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.icons.ShadowGenerator;
import com.android.wm.shell.R;
/**
@@ -44,78 +44,77 @@
* will include the workprofile indicator on the badge if appropriate.
*/
BitmapInfo getBadgeBitmap(Drawable userBadgedAppIcon, boolean isImportantConversation) {
- ShadowGenerator shadowGenerator = new ShadowGenerator(mIconBitmapSize);
- Bitmap userBadgedBitmap = createIconBitmap(userBadgedAppIcon, 1f, mIconBitmapSize);
-
if (userBadgedAppIcon instanceof AdaptiveIconDrawable) {
- userBadgedBitmap = Bitmap.createScaledBitmap(
- getCircleBitmap((AdaptiveIconDrawable) userBadgedAppIcon, /* size */
- userBadgedAppIcon.getIntrinsicWidth()),
- mIconBitmapSize, mIconBitmapSize, /* filter */ true);
+ AdaptiveIconDrawable ad = (AdaptiveIconDrawable) userBadgedAppIcon;
+ userBadgedAppIcon = new CircularAdaptiveIcon(ad.getBackground(), ad.getForeground());
+ }
+ if (isImportantConversation) {
+ userBadgedAppIcon = new CircularRingDrawable(userBadgedAppIcon);
+ }
+ Bitmap userBadgedBitmap = createIconBitmap(
+ userBadgedAppIcon, 1, BITMAP_GENERATION_MODE_WITH_SHADOW);
+ return createIconBitmap(userBadgedBitmap);
+ }
+
+ private class CircularRingDrawable extends CircularAdaptiveIcon {
+
+ final int mImportantConversationColor;
+ final Rect mTempBounds = new Rect();
+
+ final Drawable mDr;
+
+ CircularRingDrawable(Drawable dr) {
+ super(null, null);
+ mDr = dr;
+ mImportantConversationColor = mContext.getResources().getColor(
+ R.color.important_conversation, null);
}
- if (isImportantConversation) {
- final float ringStrokeWidth = mContext.getResources().getDimensionPixelSize(
+ @Override
+ public void draw(Canvas canvas) {
+ int save = canvas.save();
+ canvas.clipPath(getIconMask());
+ canvas.drawColor(mImportantConversationColor);
+ int ringStrokeWidth = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.importance_ring_stroke_width);
- final int importantConversationColor = mContext.getResources().getColor(
- R.color.important_conversation, null);
- Bitmap badgeAndRing = Bitmap.createBitmap(userBadgedBitmap.getWidth(),
- userBadgedBitmap.getHeight(), userBadgedBitmap.getConfig());
- Canvas c = new Canvas(badgeAndRing);
-
- Paint ringPaint = new Paint();
- ringPaint.setStyle(Paint.Style.FILL);
- ringPaint.setColor(importantConversationColor);
- ringPaint.setAntiAlias(true);
- c.drawCircle(c.getWidth() / 2, c.getHeight() / 2, c.getWidth() / 2, ringPaint);
-
- final int bitmapTop = (int) ringStrokeWidth;
- final int bitmapLeft = (int) ringStrokeWidth;
- final int bitmapWidth = c.getWidth() - 2 * (int) ringStrokeWidth;
- final int bitmapHeight = c.getHeight() - 2 * (int) ringStrokeWidth;
-
- Bitmap scaledBitmap = Bitmap.createScaledBitmap(userBadgedBitmap, bitmapWidth,
- bitmapHeight, /* filter */ true);
- c.drawBitmap(scaledBitmap, bitmapTop, bitmapLeft, /* paint */null);
-
- shadowGenerator.recreateIcon(Bitmap.createBitmap(badgeAndRing), c);
- return createIconBitmap(badgeAndRing);
- } else {
- Canvas c = new Canvas();
- c.setBitmap(userBadgedBitmap);
- shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
- return createIconBitmap(userBadgedBitmap);
+ mTempBounds.set(getBounds());
+ mTempBounds.inset(ringStrokeWidth, ringStrokeWidth);
+ mDr.setBounds(mTempBounds);
+ mDr.draw(canvas);
+ canvas.restoreToCount(save);
}
}
- private Bitmap getCircleBitmap(AdaptiveIconDrawable icon, int size) {
- Drawable foreground = icon.getForeground();
- Drawable background = icon.getBackground();
- Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas();
- canvas.setBitmap(bitmap);
+ private static class CircularAdaptiveIcon extends AdaptiveIconDrawable {
- // Clip canvas to circle.
- Path circlePath = new Path();
- circlePath.addCircle(/* x */ size / 2f,
- /* y */ size / 2f,
- /* radius */ size / 2f,
- Path.Direction.CW);
- canvas.clipPath(circlePath);
+ final Path mPath = new Path();
- // Draw background.
- background.setBounds(0, 0, size, size);
- background.draw(canvas);
+ CircularAdaptiveIcon(Drawable bg, Drawable fg) {
+ super(bg, fg);
+ }
- // Draw foreground. The foreground and background drawables are derived from adaptive icons
- // Some icon shapes fill more space than others, so adaptive icons are normalized to about
- // the same size. This size is smaller than the original bounds, so we estimate
- // the difference in this offset.
- int offset = size / 5;
- foreground.setBounds(-offset, -offset, size + offset, size + offset);
- foreground.draw(canvas);
+ @Override
+ public Path getIconMask() {
+ mPath.reset();
+ Rect bounds = getBounds();
+ mPath.addOval(bounds.left, bounds.top, bounds.right, bounds.bottom, Path.Direction.CW);
+ return mPath;
+ }
- canvas.setBitmap(null);
- return bitmap;
+ @Override
+ public void draw(Canvas canvas) {
+ int save = canvas.save();
+ canvas.clipPath(getIconMask());
+
+ canvas.drawColor(Color.BLACK);
+ Drawable d;
+ if ((d = getBackground()) != null) {
+ d.draw(canvas);
+ }
+ if ((d = getForeground()) != null) {
+ d.draw(canvas);
+ }
+ canvas.restoreToCount(save);
+ }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 3982616..8771ceb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1055,18 +1055,28 @@
public void updateBubble(BubbleEntry notif, boolean suppressFlyout, boolean showInShade) {
// If this is an interruptive notif, mark that it's interrupted
mSysuiProxy.setNotificationInterruption(notif.getKey());
- if (!notif.getRanking().isTextChanged()
+ boolean isNonInterruptiveNotExpanding = !notif.getRanking().isTextChanged()
&& (notif.getBubbleMetadata() != null
- && !notif.getBubbleMetadata().getAutoExpandBubble())
+ && !notif.getBubbleMetadata().getAutoExpandBubble());
+ if (isNonInterruptiveNotExpanding
&& mBubbleData.hasOverflowBubbleWithKey(notif.getKey())) {
// Update the bubble but don't promote it out of overflow
Bubble b = mBubbleData.getOverflowBubbleWithKey(notif.getKey());
- b.setEntry(notif);
+ if (notif.isBubble()) {
+ notif.setFlagBubble(false);
+ }
+ updateNotNotifyingEntry(b, notif, showInShade);
+ } else if (mBubbleData.hasAnyBubbleWithKey(notif.getKey())
+ && isNonInterruptiveNotExpanding) {
+ Bubble b = mBubbleData.getAnyBubbleWithkey(notif.getKey());
+ if (b != null) {
+ updateNotNotifyingEntry(b, notif, showInShade);
+ }
} else if (mBubbleData.isSuppressedWithLocusId(notif.getLocusId())) {
// Update the bubble but don't promote it out of overflow
Bubble b = mBubbleData.getSuppressedBubbleWithKey(notif.getKey());
if (b != null) {
- b.setEntry(notif);
+ updateNotNotifyingEntry(b, notif, showInShade);
}
} else {
Bubble bubble = mBubbleData.getOrCreateBubble(notif, null /* persistedBubble */);
@@ -1076,13 +1086,25 @@
if (bubble.shouldAutoExpand()) {
bubble.setShouldAutoExpand(false);
}
+ mImpl.mCachedState.updateBubbleSuppressedState(bubble);
} else {
inflateAndAdd(bubble, suppressFlyout, showInShade);
}
}
}
- void inflateAndAdd(Bubble bubble, boolean suppressFlyout, boolean showInShade) {
+ void updateNotNotifyingEntry(Bubble b, BubbleEntry entry, boolean showInShade) {
+ boolean isBubbleSelected = Objects.equals(b, mBubbleData.getSelectedBubble());
+ boolean isBubbleExpandedAndSelected = isStackExpanded() && isBubbleSelected;
+ b.setEntry(entry);
+ boolean suppress = isBubbleExpandedAndSelected || !showInShade || !b.showInShade();
+ b.setSuppressNotification(suppress);
+ b.setShowDot(!isBubbleExpandedAndSelected);
+ mImpl.mCachedState.updateBubbleSuppressedState(b);
+ }
+
+ @VisibleForTesting
+ public void inflateAndAdd(Bubble bubble, boolean suppressFlyout, boolean showInShade) {
// Lazy init stack view when a bubble is created
ensureStackViewCreated();
bubble.setInflateSynchronously(mInflateSynchronously);
@@ -1111,7 +1133,10 @@
}
@VisibleForTesting
- public void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp) {
+ public void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp, boolean fromSystem) {
+ if (!fromSystem) {
+ return;
+ }
// shouldBubbleUp checks canBubble & for bubble metadata
boolean shouldBubble = shouldBubbleUp && canLaunchInTaskView(mContext, entry);
if (!shouldBubble && mBubbleData.hasAnyBubbleWithKey(entry.getKey())) {
@@ -1172,9 +1197,9 @@
// notification, so that the bubble will be re-created if shouldBubbleUp returns
// true.
mBubbleData.dismissBubbleWithKey(key, DISMISS_NO_BUBBLE_UP);
- } else if (entry != null && mTmpRanking.isBubble() && !isActive) {
+ } else if (entry != null && mTmpRanking.isBubble() && !isActiveOrInOverflow) {
entry.setFlagBubble(true);
- onEntryUpdated(entry, shouldBubbleUp);
+ onEntryUpdated(entry, shouldBubbleUp, /* fromSystem= */ true);
}
}
}
@@ -1773,9 +1798,9 @@
}
@Override
- public void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp) {
+ public void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp, boolean fromSystem) {
mMainExecutor.execute(() -> {
- BubbleController.this.onEntryUpdated(entry, shouldBubbleUp);
+ BubbleController.this.onEntryUpdated(entry, shouldBubbleUp, fromSystem);
});
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java
index 9d3bf34..5dab8a0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java
@@ -21,6 +21,7 @@
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
+import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
@@ -65,4 +66,19 @@
return null;
}
}
+
+ /**
+ * Creates the bitmap for the provided drawable and returns the scale used for
+ * drawing the actual drawable.
+ */
+ public Bitmap createIconBitmap(@NonNull Drawable icon, float[] outScale) {
+ if (outScale == null) {
+ outScale = new float[1];
+ }
+ icon = normalizeAndWrapToAdaptiveIcon(icon,
+ true /* shrinkNonAdaptiveIcons */,
+ null /* outscale */,
+ outScale);
+ return createIconBitmap(icon, outScale[0], BITMAP_GENERATION_MODE_WITH_SHADOW);
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
index 69762c9..f437553 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
@@ -195,15 +195,18 @@
b.isImportantConversation());
info.badgeBitmap = badgeBitmapInfo.icon;
// Raw badge bitmap never includes the important conversation ring
- info.mRawBadgeBitmap = badgeIconFactory.getBadgeBitmap(badgedIcon, false).icon;
- info.bubbleBitmap = iconFactory.createBadgedIconBitmap(bubbleDrawable).icon;
+ info.mRawBadgeBitmap = b.isImportantConversation()
+ ? badgeIconFactory.getBadgeBitmap(badgedIcon, false).icon
+ : badgeBitmapInfo.icon;
+
+ float[] bubbleBitmapScale = new float[1];
+ info.bubbleBitmap = iconFactory.createIconBitmap(bubbleDrawable, bubbleBitmapScale);
// Dot color & placement
Path iconPath = PathParser.createPathFromPathData(
c.getResources().getString(com.android.internal.R.string.config_icon_mask));
Matrix matrix = new Matrix();
- float scale = iconFactory.getNormalizer().getScale(bubbleDrawable,
- null /* outBounds */, null /* path */, null /* outMaskShape */);
+ float scale = bubbleBitmapScale[0];
float radius = DEFAULT_PATH_SIZE / 2f;
matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
radius /* pivot y */);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
index cf792cd..37b96ff 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
@@ -171,8 +171,9 @@
*
* @param entry the {@link BubbleEntry} by the notification.
* @param shouldBubbleUp {@code true} if this notification should bubble up.
+ * @param fromSystem {@code true} if this update is from NotificationManagerService.
*/
- void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp);
+ void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp, boolean fromSystem);
/**
* Called when new notification entry removed.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 40cf9a3..85c8ebf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -1130,16 +1130,16 @@
boolean adjusted = false;
if (mYOffsetForIme != 0) {
if (dividerLeash != null) {
- mTempRect.set(mDividerBounds);
+ getRefDividerBounds(mTempRect);
mTempRect.offset(0, mYOffsetForIme);
t.setPosition(dividerLeash, mTempRect.left, mTempRect.top);
}
- mTempRect.set(mBounds1);
+ getRefBounds1(mTempRect);
mTempRect.offset(0, mYOffsetForIme);
t.setPosition(leash1, mTempRect.left, mTempRect.top);
- mTempRect.set(mBounds2);
+ getRefBounds2(mTempRect);
mTempRect.offset(0, mYOffsetForIme);
t.setPosition(leash2, mTempRect.left, mTempRect.top);
adjusted = true;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java
index 81904e2..e22c951 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvPipModule.java
@@ -49,6 +49,7 @@
import com.android.wm.shell.pip.tv.TvPipTransition;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.sysui.ShellController;
+import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
import java.util.Optional;
@@ -138,12 +139,14 @@
@WMSingleton
@Provides
static PipTransitionController provideTvPipTransition(
- Transitions transitions, ShellTaskOrganizer shellTaskOrganizer,
+ ShellInit shellInit,
+ ShellTaskOrganizer shellTaskOrganizer,
+ Transitions transitions,
PipAnimationController pipAnimationController,
TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
TvPipBoundsState tvPipBoundsState, TvPipMenuController pipMenuController) {
- return new TvPipTransition(tvPipBoundsState, pipMenuController,
- tvPipBoundsAlgorithm, pipAnimationController, transitions, shellTaskOrganizer);
+ return new TvPipTransition(shellInit, shellTaskOrganizer, transitions, tvPipBoundsState,
+ pipMenuController, tvPipBoundsAlgorithm, pipAnimationController);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index e2bf767..d53451a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -409,15 +409,15 @@
@WMSingleton
@Provides
static PipTransitionController providePipTransitionController(Context context,
- Transitions transitions, ShellTaskOrganizer shellTaskOrganizer,
+ ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, Transitions transitions,
PipAnimationController pipAnimationController, PipBoundsAlgorithm pipBoundsAlgorithm,
PipBoundsState pipBoundsState, PipTransitionState pipTransitionState,
PhonePipMenuController pipMenuController,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
Optional<SplitScreenController> splitScreenOptional) {
- return new PipTransition(context, pipBoundsState, pipTransitionState, pipMenuController,
- pipBoundsAlgorithm, pipAnimationController, transitions, shellTaskOrganizer,
- pipSurfaceTransactionHelper, splitScreenOptional);
+ return new PipTransition(context, shellInit, shellTaskOrganizer, transitions,
+ pipBoundsState, pipTransitionState, pipMenuController, pipBoundsAlgorithm,
+ pipAnimationController, pipSurfaceTransactionHelper, splitScreenOptional);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
index 20d7725..af205ed 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
@@ -122,7 +122,6 @@
break;
case WindowManager.TRANSIT_TO_BACK:
case WindowManager.TRANSIT_TO_FRONT:
- transitionHandled = true;
break;
}
}
@@ -147,7 +146,9 @@
return false;
}
mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
- return true;
+
+ // Intercepted transition to manage the window decorations. Let other handlers animate.
+ return false;
}
private boolean startCloseTransition(
@@ -164,7 +165,8 @@
windowDecors.add(windowDecor);
}
- return true;
+ // Intercepted transition to manage the window decorations. Let other handlers animate.
+ return false;
}
private boolean startChangeTransition(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index cf2734c..81e49f8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -183,7 +183,7 @@
return mCurrentAnimator;
}
- PipTransitionAnimator getCurrentAnimator() {
+ public PipTransitionAnimator getCurrentAnimator() {
return mCurrentAnimator;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 1155ea1..f747b5e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -127,7 +127,7 @@
private final PipBoundsAlgorithm mPipBoundsAlgorithm;
private final @NonNull PipMenuController mPipMenuController;
private final PipAnimationController mPipAnimationController;
- private final PipTransitionController mPipTransitionController;
+ protected final PipTransitionController mPipTransitionController;
protected final PipParamsChangedForwarder mPipParamsChangedForwarder;
private final PipUiEventLogger mPipUiEventLoggerLogger;
private final int mEnterAnimationDuration;
@@ -196,6 +196,26 @@
}
};
+ @VisibleForTesting
+ final PipTransitionController.PipTransitionCallback mPipTransitionCallback =
+ new PipTransitionController.PipTransitionCallback() {
+ @Override
+ public void onPipTransitionStarted(int direction, Rect pipBounds) {}
+
+ @Override
+ public void onPipTransitionFinished(int direction) {
+ // Apply the deferred RunningTaskInfo if applicable after all proper callbacks
+ // are sent.
+ if (direction == TRANSITION_DIRECTION_TO_PIP && mDeferredTaskInfo != null) {
+ onTaskInfoChanged(mDeferredTaskInfo);
+ mDeferredTaskInfo = null;
+ }
+ }
+
+ @Override
+ public void onPipTransitionCanceled(int direction) {}
+ };
+
private final PipAnimationController.PipTransactionHandler mPipTransactionHandler =
new PipAnimationController.PipTransactionHandler() {
@Override
@@ -216,7 +236,7 @@
private ActivityManager.RunningTaskInfo mDeferredTaskInfo;
private WindowContainerToken mToken;
private SurfaceControl mLeash;
- private PipTransitionState mPipTransitionState;
+ protected PipTransitionState mPipTransitionState;
private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS;
private long mLastOneShotAlphaAnimationTime;
private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
@@ -296,6 +316,7 @@
mTaskOrganizer.addFocusListener(this);
mPipTransitionController.setPipOrganizer(this);
displayController.addDisplayWindowListener(this);
+ pipTransitionController.registerPipTransitionCallback(mPipTransitionCallback);
}
public PipTransitionController getTransitionController() {
@@ -773,11 +794,6 @@
mPipTransitionState.setTransitionState(PipTransitionState.ENTERED_PIP);
}
mPipTransitionController.sendOnPipTransitionFinished(direction);
- // Apply the deferred RunningTaskInfo if applicable after all proper callbacks are sent.
- if (direction == TRANSITION_DIRECTION_TO_PIP && mDeferredTaskInfo != null) {
- onTaskInfoChanged(mDeferredTaskInfo);
- mDeferredTaskInfo = null;
- }
}
private void sendOnPipTransitionCancelled(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 51be2a5..33761d2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -66,6 +66,7 @@
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreenController;
+import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.CounterRotatorHelper;
import com.android.wm.shell.transition.Transitions;
@@ -107,17 +108,18 @@
private boolean mHasFadeOut;
public PipTransition(Context context,
+ @NonNull ShellInit shellInit,
+ @NonNull ShellTaskOrganizer shellTaskOrganizer,
+ @NonNull Transitions transitions,
PipBoundsState pipBoundsState,
PipTransitionState pipTransitionState,
PipMenuController pipMenuController,
PipBoundsAlgorithm pipBoundsAlgorithm,
PipAnimationController pipAnimationController,
- Transitions transitions,
- @NonNull ShellTaskOrganizer shellTaskOrganizer,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
Optional<SplitScreenController> splitScreenOptional) {
- super(pipBoundsState, pipMenuController, pipBoundsAlgorithm,
- pipAnimationController, transitions, shellTaskOrganizer);
+ super(shellInit, shellTaskOrganizer, transitions, pipBoundsState, pipMenuController,
+ pipBoundsAlgorithm, pipAnimationController);
mContext = context;
mPipTransitionState = pipTransitionState;
mEnterExitAnimationDuration = context.getResources()
@@ -315,7 +317,8 @@
}
@Override
- public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) {
+ public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+ @Nullable SurfaceControl.Transaction finishT) {
if (transition != mExitTransition) {
return;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
index 90a2695..f51e247 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
@@ -38,6 +38,7 @@
import androidx.annotation.NonNull;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
import java.util.ArrayList;
@@ -131,10 +132,13 @@
public void onFixedRotationStarted() {
}
- public PipTransitionController(PipBoundsState pipBoundsState,
+ public PipTransitionController(
+ @NonNull ShellInit shellInit,
+ @NonNull ShellTaskOrganizer shellTaskOrganizer,
+ @NonNull Transitions transitions,
+ PipBoundsState pipBoundsState,
PipMenuController pipMenuController, PipBoundsAlgorithm pipBoundsAlgorithm,
- PipAnimationController pipAnimationController, Transitions transitions,
- @android.annotation.NonNull ShellTaskOrganizer shellTaskOrganizer) {
+ PipAnimationController pipAnimationController) {
mPipBoundsState = pipBoundsState;
mPipMenuController = pipMenuController;
mShellTaskOrganizer = shellTaskOrganizer;
@@ -142,10 +146,14 @@
mPipAnimationController = pipAnimationController;
mTransitions = transitions;
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- transitions.addHandler(this);
+ shellInit.addInitCallback(this::onInit, this);
}
}
+ private void onInit() {
+ mTransitions.addHandler(this);
+ }
+
void setPipOrganizer(PipTaskOrganizer pto) {
mPipOrganizer = pto;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java
index 5062cc4..8ebcf63 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java
@@ -32,6 +32,7 @@
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipMenuController;
import com.android.wm.shell.pip.PipTransitionController;
+import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
/**
@@ -39,14 +40,16 @@
* TODO: Implement animation once TV is using Transitions.
*/
public class TvPipTransition extends PipTransitionController {
- public TvPipTransition(PipBoundsState pipBoundsState,
+ public TvPipTransition(
+ @NonNull ShellInit shellInit,
+ @NonNull ShellTaskOrganizer shellTaskOrganizer,
+ @NonNull Transitions transitions,
+ PipBoundsState pipBoundsState,
PipMenuController pipMenuController,
TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
- PipAnimationController pipAnimationController,
- Transitions transitions,
- @NonNull ShellTaskOrganizer shellTaskOrganizer) {
- super(pipBoundsState, pipMenuController, tvPipBoundsAlgorithm, pipAnimationController,
- transitions, shellTaskOrganizer);
+ PipAnimationController pipAnimationController) {
+ super(shellInit, shellTaskOrganizer, transitions, pipBoundsState, pipMenuController,
+ tvPipBoundsAlgorithm, pipAnimationController);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index de7e7bd..8de649e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -21,6 +21,7 @@
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
@@ -90,7 +91,6 @@
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.Executor;
@@ -337,17 +337,39 @@
}
public void startTask(int taskId, @SplitPosition int position, @Nullable Bundle options) {
+ final int[] result = new int[1];
+ IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() {
+ @Override
+ public void onAnimationStart(@WindowManager.TransitionOldType int transit,
+ RemoteAnimationTarget[] apps,
+ RemoteAnimationTarget[] wallpapers,
+ RemoteAnimationTarget[] nonApps,
+ final IRemoteAnimationFinishedCallback finishedCallback) {
+ try {
+ finishedCallback.onAnimationFinished();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to invoke onAnimationFinished", e);
+ }
+ if (result[0] == START_SUCCESS || result[0] == START_TASK_TO_FRONT) {
+ final WindowContainerTransaction evictWct = new WindowContainerTransaction();
+ mStageCoordinator.prepareEvictNonOpeningChildTasks(position, apps, evictWct);
+ mSyncQueue.queue(evictWct);
+ }
+ }
+ @Override
+ public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ }
+ };
options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options,
null /* wct */);
+ RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter(wrapper,
+ 0 /* duration */, 0 /* statusBarTransitionDelay */);
+ ActivityOptions activityOptions = ActivityOptions.fromBundle(options);
+ activityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter));
try {
- final WindowContainerTransaction evictWct = new WindowContainerTransaction();
- mStageCoordinator.prepareEvictChildTasks(position, evictWct);
- final int result =
- ActivityTaskManager.getService().startActivityFromRecents(taskId, options);
- if (result == START_SUCCESS || result == START_TASK_TO_FRONT) {
- mSyncQueue.queue(evictWct);
- }
+ result[0] = ActivityTaskManager.getService().startActivityFromRecents(taskId,
+ activityOptions.toBundle());
} catch (RemoteException e) {
Slog.e(TAG, "Failed to launch task", e);
}
@@ -453,12 +475,12 @@
mStageCoordinator.prepareEvictInvisibleChildTasks(wct);
mSyncQueue.queue(wct);
}
- return reparentSplitTasksForAnimation(apps, true /*splitExpectedToBeVisible*/);
+ return reparentSplitTasksForAnimation(apps, false /* enterSplitScreen */);
}
RemoteAnimationTarget[] onStartingSplitLegacy(RemoteAnimationTarget[] apps) {
try {
- return reparentSplitTasksForAnimation(apps, false /*splitExpectedToBeVisible*/);
+ return reparentSplitTasksForAnimation(apps, true /* enterSplitScreen */);
} finally {
for (RemoteAnimationTarget appTarget : apps) {
if (appTarget.leash != null) {
@@ -469,14 +491,23 @@
}
private RemoteAnimationTarget[] reparentSplitTasksForAnimation(RemoteAnimationTarget[] apps,
- boolean splitExpectedToBeVisible) {
+ boolean enterSplitScreen) {
if (ENABLE_SHELL_TRANSITIONS) return null;
- // TODO(b/206487881): Integrate this with shell transition.
- if (splitExpectedToBeVisible && !isSplitScreenVisible()) return null;
- // Split not visible, but not enough apps to have split, also return null
- if (!splitExpectedToBeVisible && apps.length < 2) return null;
- SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+ if (enterSplitScreen) {
+ int openingApps = 0;
+ for (int i = 0; i < apps.length; ++i) {
+ if (apps[i].mode == MODE_OPENING) openingApps++;
+ }
+ if (openingApps < 2) {
+ // Not having enough apps to enter split screen
+ return null;
+ }
+ } else if (!isSplitScreenVisible()) {
+ return null;
+ }
+
+ final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
if (mSplitTasksContainerLayer != null) {
// Remove the previous layer before recreating
transaction.remove(mSplitTasksContainerLayer);
@@ -489,17 +520,14 @@
mRootTDAOrganizer.attachToDisplayArea(DEFAULT_DISPLAY, builder);
mSplitTasksContainerLayer = builder.build();
- // Ensure that we order these in the parent in the right z-order as their previous order
- Arrays.sort(apps, (a1, a2) -> a1.prefixOrderIndex - a2.prefixOrderIndex);
- int layer = 1;
- for (RemoteAnimationTarget appTarget : apps) {
+ for (int i = 0; i < apps.length; ++i) {
+ final RemoteAnimationTarget appTarget = apps[i];
transaction.reparent(appTarget.leash, mSplitTasksContainerLayer);
transaction.setPosition(appTarget.leash, appTarget.screenSpaceBounds.left,
appTarget.screenSpaceBounds.top);
- transaction.setLayer(appTarget.leash, layer++);
}
transaction.apply();
- transaction.close();
+ mTransactionPool.release(transaction);
return new RemoteAnimationTarget[]{mStageCoordinator.getDividerBarLegacyTarget()};
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
index 83bdf8b..d7ca791 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
@@ -94,6 +94,7 @@
@NonNull WindowContainerToken topRoot) {
mFinishCallback = finishCallback;
mAnimatingTransition = transition;
+ mFinishTransaction = finishTransaction;
if (mPendingRemoteHandler != null) {
mPendingRemoteHandler.startAnimation(transition, info, startTransaction,
finishTransaction, mRemoteFinishCB);
@@ -107,8 +108,6 @@
private void playInternalAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction t, @NonNull WindowContainerToken mainRoot,
@NonNull WindowContainerToken sideRoot, @NonNull WindowContainerToken topRoot) {
- mFinishTransaction = mTransactionPool.acquire();
-
// Play some place-holder fade animations
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
@@ -287,16 +286,14 @@
return true;
}
- void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) {
+ void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+ @Nullable SurfaceControl.Transaction finishT) {
if (isPendingEnter(transition)) {
if (!aborted) {
// An enter transition got merged, appends the rest operations to finish entering
// split screen.
- // TODO (b/238856352): Passed-in the proper finish transition to merge instead.
- if (mFinishTransaction == null) {
- mFinishTransaction = mTransactionPool.acquire();
- }
- mStageCoordinator.finishEnterSplitScreen(mFinishTransaction);
+ mStageCoordinator.finishEnterSplitScreen(finishT);
+ mPendingRemoteHandler = null;
}
mPendingEnter.mCallback.onTransitionConsumed(aborted);
@@ -339,11 +336,6 @@
mAnimatingTransition = null;
mOnFinish.run();
- if (mFinishTransaction != null) {
- mFinishTransaction.apply();
- mTransactionPool.release(mFinishTransaction);
- mFinishTransaction = null;
- }
if (mFinishCallback != null) {
mFinishCallback.onTransitionFinished(wct /* wct */, wctCB /* wctCB */);
mFinishCallback = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index f2340d5..8e1ae39 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -233,6 +233,7 @@
if (op.getType() == HIERARCHY_OP_TYPE_REORDER && op.getToTop()
&& (mMainStage.containsContainer(container)
|| mSideStage.containsContainer(container))) {
+ updateSurfaceBounds(mSplitLayout, finishT, false /* applyResizingOffset */);
setDividerVisibility(true, finishT);
return;
}
@@ -451,10 +452,16 @@
IRemoteAnimationFinishedCallback finishedCallback,
SurfaceControl.Transaction t) {
if (apps == null || apps.length == 0) {
- // Switch the split position if launching as MULTIPLE_TASK failed.
- if ((fillInIntent.getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
- setSideStagePosition(SplitLayout.reversePosition(
- getSideStagePosition()), null);
+ if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
+ mMainExecutor.execute(() ->
+ exitSplitScreen(mMainStage.getChildCount() == 0
+ ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
+ } else {
+ // Switch the split position if launching as MULTIPLE_TASK failed.
+ if ((fillInIntent.getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
+ setSideStagePosition(SplitLayout.reversePosition(
+ getSideStagePosition()), null);
+ }
}
// Do nothing when the animation was cancelled.
@@ -650,7 +657,7 @@
mShouldUpdateRecents = true;
// If any stage has no child after animation finished, it means that split will display
// nothing, such status will happen if task and intent is same app but not support
- // multi-instagce, we should exit split and expand that app as full screen.
+ // multi-instance, we should exit split and expand that app as full screen.
if (!cancel && (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0)) {
mMainExecutor.execute(() ->
exitSplitScreen(mMainStage.getChildCount() == 0
@@ -1742,8 +1749,9 @@
}
@Override
- public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) {
- mSplitTransitions.onTransitionConsumed(transition, aborted);
+ public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+ @Nullable SurfaceControl.Transaction finishT) {
+ mSplitTransitions.onTransitionConsumed(transition, aborted, finishT);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index f414d69..1af9415 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -33,6 +33,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
@@ -376,7 +377,13 @@
SurfaceControl leash, boolean firstAppeared) {
final Point taskPositionInParent = taskInfo.positionInParent;
mSyncQueue.runInSync(t -> {
- t.setWindowCrop(leash, null);
+ // The task surface might be released before running in the sync queue for the case like
+ // trampoline launch, so check if the surface is valid before processing it.
+ if (!leash.isValid()) {
+ Slog.w(TAG, "Skip updating invalid child task surface of task#" + taskInfo.taskId);
+ return;
+ }
+ t.setCrop(leash, null);
t.setPosition(leash, taskPositionInParent.x, taskPositionInParent.y);
if (firstAppeared && !ENABLE_SHELL_TRANSITIONS) {
t.setAlpha(leash, 1f);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 11b453c..5cce6b9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -274,7 +274,8 @@
}
@Override
- public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) {
+ public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+ @Nullable SurfaceControl.Transaction finishT) {
MixedTransition mixed = null;
for (int i = mActiveTransitions.size() - 1; i >= 0; --i) {
if (mActiveTransitions.get(i).mTransition != transition) continue;
@@ -283,7 +284,7 @@
}
if (mixed == null) return;
if (mixed.mType == MixedTransition.TYPE_ENTER_PIP_FROM_SPLIT) {
- mPipHandler.onTransitionConsumed(transition, aborted);
+ mPipHandler.onTransitionConsumed(transition, aborted, finishT);
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
index cedb340..9469529 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
@@ -82,7 +82,8 @@
}
@Override
- public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) {
+ public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+ @Nullable SurfaceControl.Transaction finishT) {
mRequestedRemotes.remove(transition);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index cd29741..279d57a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -159,8 +159,10 @@
private void onInit() {
// The very last handler (0 in the list) should be the default one.
mHandlers.add(mDefaultTransitionHandler);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "addHandler: Default");
// Next lowest priority is remote transitions.
mHandlers.add(mRemoteTransitionHandler);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "addHandler: Remote");
ContentResolver resolver = mContext.getContentResolver();
mTransitionAnimationScaleSetting = Settings.Global.getFloat(resolver,
@@ -206,7 +208,13 @@
* @see TransitionHandler
*/
public void addHandler(@NonNull TransitionHandler handler) {
+ if (mHandlers.isEmpty()) {
+ throw new RuntimeException("Unexpected handler added prior to initialization, please "
+ + "use ShellInit callbacks to ensure proper ordering");
+ }
mHandlers.add(handler);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "addHandler: %s",
+ handler.getClass().getSimpleName());
}
public ShellExecutor getMainExecutor() {
@@ -535,7 +543,8 @@
active.mMerged = true;
active.mAborted = abort;
if (active.mHandler != null) {
- active.mHandler.onTransitionConsumed(active.mToken, abort);
+ active.mHandler.onTransitionConsumed(
+ active.mToken, abort, abort ? null : active.mFinishT);
}
return;
}
@@ -543,7 +552,8 @@
active.mAborted = abort;
if (active.mAborted && active.mHandler != null) {
// Notifies to clean-up the aborted transition.
- active.mHandler.onTransitionConsumed(transition, true /* aborted */);
+ active.mHandler.onTransitionConsumed(
+ transition, true /* aborted */, null /* finishTransaction */);
}
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
"Transition animation finished (abort=%b), notifying core %s", abort, transition);
@@ -579,7 +589,8 @@
ActiveTransition aborted = mActiveTransitions.remove(activeIdx);
// Notifies to clean-up the aborted transition.
if (aborted.mHandler != null) {
- aborted.mHandler.onTransitionConsumed(transition, true /* aborted */);
+ aborted.mHandler.onTransitionConsumed(
+ transition, true /* aborted */, null /* finishTransaction */);
}
mOrganizer.finishTransition(aborted.mToken, null /* wct */, null /* wctCB */);
}
@@ -765,8 +776,13 @@
* Called when a transition which was already "claimed" by this handler has been merged
* into another animation or has been aborted. Gives this handler a chance to clean-up any
* expectations.
+ *
+ * @param transition The transition been consumed.
+ * @param aborted Whether the transition is aborted or not.
+ * @param finishTransaction The transaction to be applied after the transition animated.
*/
- default void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) { }
+ default void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+ @Nullable SurfaceControl.Transaction finishTransaction) { }
/**
* Sets transition animation scale settings value to handler.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 4380bdc..506a4c0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -66,6 +66,7 @@
final DisplayController mDisplayController;
final ShellTaskOrganizer mTaskOrganizer;
final Supplier<SurfaceControl.Builder> mSurfaceControlBuilderSupplier;
+ final Supplier<WindowContainerTransaction> mWindowContainerTransactionSupplier;
final SurfaceControlViewHostFactory mSurfaceControlViewHostFactory;
private final DisplayController.OnDisplaysChangedListener mOnDisplaysChangedListener =
new DisplayController.OnDisplaysChangedListener() {
@@ -102,7 +103,8 @@
RunningTaskInfo taskInfo,
SurfaceControl taskSurface) {
this(context, displayController, taskOrganizer, taskInfo, taskSurface,
- SurfaceControl.Builder::new, new SurfaceControlViewHostFactory() {});
+ SurfaceControl.Builder::new, WindowContainerTransaction::new,
+ new SurfaceControlViewHostFactory() {});
}
WindowDecoration(
@@ -112,6 +114,7 @@
RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
+ Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
mContext = context;
mDisplayController = displayController;
@@ -119,6 +122,7 @@
mTaskInfo = taskInfo;
mTaskSurface = taskSurface;
mSurfaceControlBuilderSupplier = surfaceControlBuilderSupplier;
+ mWindowContainerTransactionSupplier = windowContainerTransactionSupplier;
mSurfaceControlViewHostFactory = surfaceControlViewHostFactory;
mDisplay = mDisplayController.getDisplay(mTaskInfo.displayId);
@@ -229,7 +233,9 @@
mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
startT.setWindowCrop(mTaskBackgroundSurface, taskBounds.width(), taskBounds.height())
.setShadowRadius(mTaskBackgroundSurface, shadowRadius)
- .setColor(mTaskBackgroundSurface, mTmpColor);
+ .setColor(mTaskBackgroundSurface, mTmpColor)
+ .setLayer(mTaskBackgroundSurface, -1)
+ .show(mTaskBackgroundSurface);
// Caption view
mCaptionWindowManager.setConfiguration(taskConfig);
@@ -301,6 +307,10 @@
mTaskBackgroundSurface.release();
mTaskBackgroundSurface = null;
}
+
+ final WindowContainerTransaction wct = mWindowContainerTransactionSupplier.get();
+ wct.removeInsetsProvider(mTaskInfo.token, CAPTION_INSETS_TYPES);
+ mTaskOrganizer.applyTransaction(wct);
}
@Override
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
index 857f578..579638d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
@@ -21,13 +21,13 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
@@ -70,7 +70,7 @@
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class PipTaskOrganizerTest extends ShellTestCase {
- private PipTaskOrganizer mSpiedPipTaskOrganizer;
+ private PipTaskOrganizer mPipTaskOrganizer;
@Mock private DisplayController mMockDisplayController;
@Mock private SyncTransactionQueue mMockSyncTransactionQueue;
@@ -100,14 +100,15 @@
mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState,
new PipSnapAlgorithm());
mMainExecutor = new TestShellExecutor();
- mSpiedPipTaskOrganizer = spy(new PipTaskOrganizer(mContext,
+ mPipTaskOrganizer = new PipTaskOrganizer(mContext,
mMockSyncTransactionQueue, mPipTransitionState, mPipBoundsState,
mPipBoundsAlgorithm, mMockPhonePipMenuController, mMockPipAnimationController,
mMockPipSurfaceTransactionHelper, mMockPipTransitionController,
mMockPipParamsChangedForwarder, mMockOptionalSplitScreen, mMockDisplayController,
- mMockPipUiEventLogger, mMockShellTaskOrganizer, mMainExecutor));
+ mMockPipUiEventLogger, mMockShellTaskOrganizer, mMainExecutor);
mMainExecutor.flushAll();
preparePipTaskOrg();
+ preparePipSurfaceTransactionHelper();
}
@Test
@@ -124,14 +125,14 @@
public void startSwipePipToHome_updatesAspectRatio() {
final Rational aspectRatio = new Rational(2, 1);
- mSpiedPipTaskOrganizer.startSwipePipToHome(mComponent1, null, createPipParams(aspectRatio));
+ mPipTaskOrganizer.startSwipePipToHome(mComponent1, null, createPipParams(aspectRatio));
assertEquals(aspectRatio.floatValue(), mPipBoundsState.getAspectRatio(), 0.01f);
}
@Test
public void startSwipePipToHome_updatesLastPipComponentName() {
- mSpiedPipTaskOrganizer.startSwipePipToHome(mComponent1, null, createPipParams(null));
+ mPipTaskOrganizer.startSwipePipToHome(mComponent1, null, createPipParams(null));
assertEquals(mComponent1, mPipBoundsState.getLastPipComponentName());
}
@@ -140,7 +141,7 @@
public void startSwipePipToHome_updatesOverrideMinSize() {
final Size minSize = new Size(400, 320);
- mSpiedPipTaskOrganizer.startSwipePipToHome(mComponent1, createActivityInfo(minSize),
+ mPipTaskOrganizer.startSwipePipToHome(mComponent1, createActivityInfo(minSize),
createPipParams(null));
assertEquals(minSize, mPipBoundsState.getOverrideMinSize());
@@ -150,7 +151,7 @@
public void onTaskAppeared_updatesAspectRatio() {
final Rational aspectRatio = new Rational(2, 1);
- mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
+ mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
createPipParams(aspectRatio)), mock(SurfaceControl.class));
assertEquals(aspectRatio.floatValue(), mPipBoundsState.getAspectRatio(), 0.01f);
@@ -158,7 +159,7 @@
@Test
public void onTaskAppeared_updatesLastPipComponentName() {
- mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)),
+ mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)),
mock(SurfaceControl.class));
assertEquals(mComponent1, mPipBoundsState.getLastPipComponentName());
@@ -168,7 +169,7 @@
public void onTaskAppeared_updatesOverrideMinSize() {
final Size minSize = new Size(400, 320);
- mSpiedPipTaskOrganizer.onTaskAppeared(
+ mPipTaskOrganizer.onTaskAppeared(
createTaskInfo(mComponent1, createPipParams(null), minSize),
mock(SurfaceControl.class));
@@ -179,16 +180,16 @@
public void onTaskInfoChanged_notInPip_deferUpdatesAspectRatio() {
final Rational startAspectRatio = new Rational(2, 1);
final Rational newAspectRatio = new Rational(1, 2);
- mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
+ mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
createPipParams(startAspectRatio)), mock(SurfaceControl.class));
// It is in entering transition, should defer onTaskInfoChanged callback in this case.
- mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1,
+ mPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1,
createPipParams(newAspectRatio)));
verify(mMockPipParamsChangedForwarder, never()).notifyAspectRatioChanged(anyFloat());
// Once the entering transition finishes, the new aspect ratio applies in a deferred manner
- mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
+ sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
verify(mMockPipParamsChangedForwarder)
.notifyAspectRatioChanged(newAspectRatio.floatValue());
}
@@ -197,11 +198,11 @@
public void onTaskInfoChanged_inPip_updatesAspectRatioIfChanged() {
final Rational startAspectRatio = new Rational(2, 1);
final Rational newAspectRatio = new Rational(1, 2);
- mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
+ mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
createPipParams(startAspectRatio)), mock(SurfaceControl.class));
- mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
+ sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
- mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1,
+ mPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1,
createPipParams(newAspectRatio)));
verify(mMockPipParamsChangedForwarder)
@@ -210,11 +211,11 @@
@Test
public void onTaskInfoChanged_inPip_updatesLastPipComponentName() {
- mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
+ mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
createPipParams(null)), mock(SurfaceControl.class));
- mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
+ sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
- mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2,
+ mPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2,
createPipParams(null)));
assertEquals(mComponent2, mPipBoundsState.getLastPipComponentName());
@@ -222,12 +223,12 @@
@Test
public void onTaskInfoChanged_inPip_updatesOverrideMinSize() {
- mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
+ mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
createPipParams(null)), mock(SurfaceControl.class));
- mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
+ sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
final Size minSize = new Size(400, 320);
- mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2,
+ mPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2,
createPipParams(null), minSize));
assertEquals(minSize, mPipBoundsState.getOverrideMinSize());
@@ -235,23 +236,42 @@
@Test
public void onTaskVanished_clearsPipBounds() {
- mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
+ mPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
createPipParams(null)), mock(SurfaceControl.class));
mPipBoundsState.setBounds(new Rect(100, 100, 200, 150));
- mSpiedPipTaskOrganizer.onTaskVanished(createTaskInfo(mComponent1, createPipParams(null)));
+ mPipTaskOrganizer.onTaskVanished(createTaskInfo(mComponent1, createPipParams(null)));
assertTrue(mPipBoundsState.getBounds().isEmpty());
}
+ private void sendOnPipTransitionFinished(
+ @PipAnimationController.TransitionDirection int direction) {
+ mPipTaskOrganizer.sendOnPipTransitionFinished(direction);
+ // PipTransitionController will call back into PipTaskOrganizer.
+ mPipTaskOrganizer.mPipTransitionCallback.onPipTransitionFinished(direction);
+ }
+
private void preparePipTaskOrg() {
final DisplayInfo info = new DisplayInfo();
mPipBoundsState.setDisplayLayout(new DisplayLayout(info,
mContext.getResources(), true, true));
- mSpiedPipTaskOrganizer.setOneShotAnimationType(PipAnimationController.ANIM_TYPE_ALPHA);
- mSpiedPipTaskOrganizer.setSurfaceControlTransactionFactory(
+ mPipTaskOrganizer.setOneShotAnimationType(PipAnimationController.ANIM_TYPE_ALPHA);
+ mPipTaskOrganizer.setSurfaceControlTransactionFactory(
MockSurfaceControlHelper::createMockSurfaceControlTransaction);
- doNothing().when(mSpiedPipTaskOrganizer).enterPipWithAlphaAnimation(any(), anyLong());
- doNothing().when(mSpiedPipTaskOrganizer).scheduleAnimateResizePip(any(), anyInt(), any());
+ }
+
+ private void preparePipSurfaceTransactionHelper() {
+ doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper)
+ .crop(any(), any(), any());
+ doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper)
+ .resetScale(any(), any(), any());
+ doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper)
+ .round(any(), any(), anyBoolean());
+ doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper)
+ .scale(any(), any(), any(), any(), anyFloat());
+ doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper)
+ .alpha(any(), any(), anyFloat());
+ doNothing().when(mMockPipSurfaceTransactionHelper).onDensityOrFontScaleChanged(any());
}
private static ActivityManager.RunningTaskInfo createTaskInfo(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index b318bb2..226843e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -204,6 +204,8 @@
verify(mMockSurfaceControlStartT)
.setColor(taskBackgroundSurface, new float[] {1.f, 1.f, 0.f});
verify(mMockSurfaceControlStartT).setShadowRadius(taskBackgroundSurface, 10);
+ verify(mMockSurfaceControlStartT).setLayer(taskBackgroundSurface, -1);
+ verify(mMockSurfaceControlStartT).show(taskBackgroundSurface);
verify(mMockSurfaceControlViewHostFactory)
.create(any(), eq(defaultDisplay), any(), anyBoolean());
@@ -233,6 +235,57 @@
}
@Test
+ public void testLayoutResultCalculation_visibleFocusedTaskToInvisible() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+
+ final SurfaceControl decorContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder decorContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(decorContainerSurface);
+ mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder);
+ final SurfaceControl taskBackgroundSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder taskBackgroundSurfaceBuilder =
+ createMockSurfaceControlBuilder(taskBackgroundSurface);
+ mMockSurfaceControlBuilders.add(taskBackgroundSurfaceBuilder);
+
+ final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
+ new ActivityManager.TaskDescription.Builder()
+ .setBackgroundColor(Color.YELLOW);
+ final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setTaskDescriptionBuilder(taskDescriptionBuilder)
+ .setBounds(TASK_BOUNDS)
+ .setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y)
+ .setVisible(true)
+ .build();
+ taskInfo.isFocused = true;
+ // Density is 2. Outsets are (20, 40, 60, 80) px. Shadow radius is 10px. Caption height is
+ // 64px.
+ taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
+ mOutsetsDp.set(10, 20, 30, 40);
+
+ final SurfaceControl taskSurface = mock(SurfaceControl.class);
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+
+ windowDecor.relayout(taskInfo);
+
+ verify(mMockSurfaceControlViewHost, never()).release();
+ verify(decorContainerSurface, never()).release();
+ verify(taskBackgroundSurface, never()).release();
+ verify(mMockWindowContainerTransaction, never())
+ .removeInsetsProvider(eq(taskInfo.token), any());
+
+ taskInfo.isVisible = false;
+ windowDecor.relayout(taskInfo);
+
+ verify(mMockSurfaceControlViewHost).release();
+ verify(decorContainerSurface).release();
+ verify(taskBackgroundSurface).release();
+ verify(mMockWindowContainerTransaction).removeInsetsProvider(eq(taskInfo.token), any());
+ }
+
+ @Test
public void testNotCrashWhenDisplayAppearsAfterTask() {
doReturn(mock(Display.class)).when(mMockDisplayController)
.getDisplay(Display.DEFAULT_DISPLAY);
@@ -282,7 +335,7 @@
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer,
taskInfo, testSurface, new MockSurfaceControlBuilderSupplier(),
- mMockSurfaceControlViewHostFactory);
+ () -> mMockWindowContainerTransaction, mMockSurfaceControlViewHostFactory);
}
private class MockSurfaceControlBuilderSupplier implements Supplier<SurfaceControl.Builder> {
@@ -313,9 +366,11 @@
ShellTaskOrganizer taskOrganizer, ActivityManager.RunningTaskInfo taskInfo,
SurfaceControl taskSurface,
Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
+ Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
super(context, displayController, taskOrganizer, taskInfo, taskSurface,
- surfaceControlBuilderSupplier, surfaceControlViewHostFactory);
+ surfaceControlBuilderSupplier, windowContainerTransactionSupplier,
+ surfaceControlViewHostFactory);
}
@Override
diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp
index 6a7119b..f5ed568 100644
--- a/libs/hwui/jni/Typeface.cpp
+++ b/libs/hwui/jni/Typeface.cpp
@@ -380,18 +380,6 @@
env->SetStaticObjectField(cls, fid, typeface);
}
-// Critical Native
-static jint Typeface_getFamilySize(CRITICAL_JNI_PARAMS_COMMA jlong faceHandle) {
- return toTypeface(faceHandle)->fFontCollection->getFamilyCount();
-}
-
-// Critical Native
-static jlong Typeface_getFamily(CRITICAL_JNI_PARAMS_COMMA jlong faceHandle, jint index) {
- std::shared_ptr<minikin::FontFamily> family =
- toTypeface(faceHandle)->fFontCollection->getFamilyAt(index);
- return reinterpret_cast<jlong>(new FontFamilyWrapper(std::move(family)));
-}
-
// Regular JNI
static void Typeface_warmUpCache(JNIEnv* env, jobject, jstring jFilePath) {
ScopedUtfChars filePath(env, jFilePath);
@@ -431,8 +419,6 @@
{"nativeReadTypefaces", "(Ljava/nio/ByteBuffer;I)[J", (void*)Typeface_readTypefaces},
{"nativeForceSetStaticFinalField", "(Ljava/lang/String;Landroid/graphics/Typeface;)V",
(void*)Typeface_forceSetStaticFinalField},
- {"nativeGetFamilySize", "(J)I", (void*)Typeface_getFamilySize},
- {"nativeGetFamily", "(JI)J", (void*)Typeface_getFamily},
{"nativeWarmUpCache", "(Ljava/lang/String;)V", (void*)Typeface_warmUpCache},
{"nativeAddFontCollections", "(J)V", (void*)Typeface_addFontCollection},
{"nativeRegisterLocaleList", "(Ljava/lang/String;)V", (void*)Typeface_registerLocaleList},
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 7b27358..53d4efa 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -45,6 +45,7 @@
import java.nio.ReadOnlyBufferException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -1811,7 +1812,7 @@
synchronized(mBufferLock) {
switch (mBufferMode) {
case BUFFER_MODE_LEGACY:
- validateInputByteBuffer(mCachedInputBuffers, index);
+ validateInputByteBufferLocked(mCachedInputBuffers, index);
break;
case BUFFER_MODE_BLOCK:
while (mQueueRequests.size() <= index) {
@@ -1840,7 +1841,7 @@
synchronized(mBufferLock) {
switch (mBufferMode) {
case BUFFER_MODE_LEGACY:
- validateOutputByteBuffer(mCachedOutputBuffers, index, info);
+ validateOutputByteBufferLocked(mCachedOutputBuffers, index, info);
break;
case BUFFER_MODE_BLOCK:
while (mOutputFrames.size() <= index) {
@@ -2328,10 +2329,6 @@
*/
public final void start() {
native_start();
- synchronized(mBufferLock) {
- cacheBuffers(true /* input */);
- cacheBuffers(false /* input */);
- }
}
private native final void native_start();
@@ -2388,8 +2385,10 @@
*/
public final void flush() {
synchronized(mBufferLock) {
- invalidateByteBuffers(mCachedInputBuffers);
- invalidateByteBuffers(mCachedOutputBuffers);
+ invalidateByteBuffersLocked(mCachedInputBuffers);
+ invalidateByteBuffersLocked(mCachedOutputBuffers);
+ mValidInputIndices.clear();
+ mValidOutputIndices.clear();
mDequeuedInputBuffers.clear();
mDequeuedOutputBuffers.clear();
}
@@ -2673,14 +2672,14 @@
+ "is not compatible with CONFIGURE_FLAG_USE_BLOCK_MODEL. "
+ "Please use getQueueRequest() to queue buffers");
}
- invalidateByteBuffer(mCachedInputBuffers, index);
+ invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
mDequeuedInputBuffers.remove(index);
}
try {
native_queueInputBuffer(
index, offset, size, presentationTimeUs, flags);
} catch (CryptoException | IllegalStateException e) {
- revalidateByteBuffer(mCachedInputBuffers, index);
+ revalidateByteBuffer(mCachedInputBuffers, index, true /* input */);
throw e;
}
}
@@ -2943,14 +2942,14 @@
+ "is not compatible with CONFIGURE_FLAG_USE_BLOCK_MODEL. "
+ "Please use getQueueRequest() to queue buffers");
}
- invalidateByteBuffer(mCachedInputBuffers, index);
+ invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
mDequeuedInputBuffers.remove(index);
}
try {
native_queueSecureInputBuffer(
index, offset, info, presentationTimeUs, flags);
} catch (CryptoException | IllegalStateException e) {
- revalidateByteBuffer(mCachedInputBuffers, index);
+ revalidateByteBuffer(mCachedInputBuffers, index, true /* input */);
throw e;
}
}
@@ -2984,7 +2983,7 @@
int res = native_dequeueInputBuffer(timeoutUs);
if (res >= 0) {
synchronized(mBufferLock) {
- validateInputByteBuffer(mCachedInputBuffers, res);
+ validateInputByteBufferLocked(mCachedInputBuffers, res);
}
}
return res;
@@ -3581,10 +3580,10 @@
int res = native_dequeueOutputBuffer(info, timeoutUs);
synchronized (mBufferLock) {
if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
- cacheBuffers(false /* input */);
+ cacheBuffersLocked(false /* input */);
} else if (res >= 0) {
- validateOutputByteBuffer(mCachedOutputBuffers, res, info);
- if (mHasSurface) {
+ validateOutputByteBufferLocked(mCachedOutputBuffers, res, info);
+ if (mHasSurface || mCachedOutputBuffers == null) {
mDequeuedOutputInfos.put(res, info.dup());
}
}
@@ -3678,9 +3677,9 @@
synchronized(mBufferLock) {
switch (mBufferMode) {
case BUFFER_MODE_LEGACY:
- invalidateByteBuffer(mCachedOutputBuffers, index);
+ invalidateByteBufferLocked(mCachedOutputBuffers, index, false /* input */);
mDequeuedOutputBuffers.remove(index);
- if (mHasSurface) {
+ if (mHasSurface || mCachedOutputBuffers == null) {
info = mDequeuedOutputInfos.remove(index);
}
break;
@@ -3832,15 +3831,24 @@
private ByteBuffer[] mCachedInputBuffers;
private ByteBuffer[] mCachedOutputBuffers;
+ private BitSet mValidInputIndices = new BitSet();
+ private BitSet mValidOutputIndices = new BitSet();
+
private final BufferMap mDequeuedInputBuffers = new BufferMap();
private final BufferMap mDequeuedOutputBuffers = new BufferMap();
private final Map<Integer, BufferInfo> mDequeuedOutputInfos =
new HashMap<Integer, BufferInfo>();
final private Object mBufferLock;
- private final void invalidateByteBuffer(
- @Nullable ByteBuffer[] buffers, int index) {
- if (buffers != null && index >= 0 && index < buffers.length) {
+ private void invalidateByteBufferLocked(
+ @Nullable ByteBuffer[] buffers, int index, boolean input) {
+ if (buffers == null) {
+ if (index < 0) {
+ throw new IllegalStateException("index is negative (" + index + ")");
+ }
+ BitSet indices = input ? mValidInputIndices : mValidOutputIndices;
+ indices.clear(index);
+ } else if (index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
buffer.setAccessible(false);
@@ -3848,9 +3856,14 @@
}
}
- private final void validateInputByteBuffer(
+ private void validateInputByteBufferLocked(
@Nullable ByteBuffer[] buffers, int index) {
- if (buffers != null && index >= 0 && index < buffers.length) {
+ if (buffers == null) {
+ if (index < 0) {
+ throw new IllegalStateException("index is negative (" + index + ")");
+ }
+ mValidInputIndices.set(index);
+ } else if (index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
buffer.setAccessible(true);
@@ -3859,10 +3872,16 @@
}
}
- private final void revalidateByteBuffer(
- @Nullable ByteBuffer[] buffers, int index) {
+ private void revalidateByteBuffer(
+ @Nullable ByteBuffer[] buffers, int index, boolean input) {
synchronized(mBufferLock) {
- if (buffers != null && index >= 0 && index < buffers.length) {
+ if (buffers == null) {
+ if (index < 0) {
+ throw new IllegalStateException("index is negative (" + index + ")");
+ }
+ BitSet indices = input ? mValidInputIndices : mValidOutputIndices;
+ indices.set(index);
+ } else if (index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
buffer.setAccessible(true);
@@ -3871,9 +3890,14 @@
}
}
- private final void validateOutputByteBuffer(
+ private void validateOutputByteBufferLocked(
@Nullable ByteBuffer[] buffers, int index, @NonNull BufferInfo info) {
- if (buffers != null && index >= 0 && index < buffers.length) {
+ if (buffers == null) {
+ if (index < 0) {
+ throw new IllegalStateException("index is negative (" + index + ")");
+ }
+ mValidOutputIndices.set(index);
+ } else if (index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
buffer.setAccessible(true);
@@ -3882,7 +3906,7 @@
}
}
- private final void invalidateByteBuffers(@Nullable ByteBuffer[] buffers) {
+ private void invalidateByteBuffersLocked(@Nullable ByteBuffer[] buffers) {
if (buffers != null) {
for (ByteBuffer buffer: buffers) {
if (buffer != null) {
@@ -3892,27 +3916,29 @@
}
}
- private final void freeByteBuffer(@Nullable ByteBuffer buffer) {
+ private void freeByteBufferLocked(@Nullable ByteBuffer buffer) {
if (buffer != null /* && buffer.isDirect() */) {
// all of our ByteBuffers are direct
java.nio.NioUtils.freeDirectBuffer(buffer);
}
}
- private final void freeByteBuffers(@Nullable ByteBuffer[] buffers) {
+ private void freeByteBuffersLocked(@Nullable ByteBuffer[] buffers) {
if (buffers != null) {
for (ByteBuffer buffer: buffers) {
- freeByteBuffer(buffer);
+ freeByteBufferLocked(buffer);
}
}
}
- private final void freeAllTrackedBuffers() {
+ private void freeAllTrackedBuffers() {
synchronized(mBufferLock) {
- freeByteBuffers(mCachedInputBuffers);
- freeByteBuffers(mCachedOutputBuffers);
+ freeByteBuffersLocked(mCachedInputBuffers);
+ freeByteBuffersLocked(mCachedOutputBuffers);
mCachedInputBuffers = null;
mCachedOutputBuffers = null;
+ mValidInputIndices.clear();
+ mValidOutputIndices.clear();
mDequeuedInputBuffers.clear();
mDequeuedOutputBuffers.clear();
mQueueRequests.clear();
@@ -3920,14 +3946,31 @@
}
}
- private final void cacheBuffers(boolean input) {
+ private void cacheBuffersLocked(boolean input) {
ByteBuffer[] buffers = null;
try {
buffers = getBuffers(input);
- invalidateByteBuffers(buffers);
+ invalidateByteBuffersLocked(buffers);
} catch (IllegalStateException e) {
// we don't get buffers in async mode
}
+ if (buffers != null) {
+ BitSet indices = input ? mValidInputIndices : mValidOutputIndices;
+ for (int i = 0; i < buffers.length; ++i) {
+ ByteBuffer buffer = buffers[i];
+ if (buffer == null || !indices.get(i)) {
+ continue;
+ }
+ buffer.setAccessible(true);
+ if (!input) {
+ BufferInfo info = mDequeuedOutputInfos.get(i);
+ if (info != null) {
+ buffer.limit(info.offset + info.size).position(info.offset);
+ }
+ }
+ }
+ indices.clear();
+ }
if (input) {
mCachedInputBuffers = buffers;
} else {
@@ -3963,6 +4006,9 @@
+ "objects and attach to QueueRequest objects.");
}
if (mCachedInputBuffers == null) {
+ cacheBuffersLocked(true /* input */);
+ }
+ if (mCachedInputBuffers == null) {
throw new IllegalStateException();
}
// FIXME: check codec status
@@ -4001,6 +4047,9 @@
+ "Please use getOutputFrame to get output frames.");
}
if (mCachedOutputBuffers == null) {
+ cacheBuffersLocked(false /* input */);
+ }
+ if (mCachedOutputBuffers == null) {
throw new IllegalStateException();
}
// FIXME: check codec status
@@ -4038,7 +4087,7 @@
}
ByteBuffer newBuffer = getBuffer(true /* input */, index);
synchronized (mBufferLock) {
- invalidateByteBuffer(mCachedInputBuffers, index);
+ invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
mDequeuedInputBuffers.put(index, newBuffer);
}
return newBuffer;
@@ -4075,7 +4124,7 @@
}
Image newImage = getImage(true /* input */, index);
synchronized (mBufferLock) {
- invalidateByteBuffer(mCachedInputBuffers, index);
+ invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
mDequeuedInputBuffers.put(index, newImage);
}
return newImage;
@@ -4111,7 +4160,7 @@
}
ByteBuffer newBuffer = getBuffer(false /* input */, index);
synchronized (mBufferLock) {
- invalidateByteBuffer(mCachedOutputBuffers, index);
+ invalidateByteBufferLocked(mCachedOutputBuffers, index, false /* input */);
mDequeuedOutputBuffers.put(index, newBuffer);
}
return newBuffer;
@@ -4146,7 +4195,7 @@
}
Image newImage = getImage(false /* input */, index);
synchronized (mBufferLock) {
- invalidateByteBuffer(mCachedOutputBuffers, index);
+ invalidateByteBufferLocked(mCachedOutputBuffers, index, false /* input */);
mDequeuedOutputBuffers.put(index, newImage);
}
return newImage;
diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
new file mode 100644
index 0000000..9f92887
--- /dev/null
+++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java
@@ -0,0 +1,441 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.interactive;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Rect;
+import android.media.tv.AdResponse;
+import android.media.tv.BroadcastInfoResponse;
+import android.media.tv.TvContentRating;
+import android.media.tv.TvTrackInfo;
+import android.media.tv.interactive.TvInteractiveAppService.Session;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+import android.view.InputChannel;
+import android.view.InputEvent;
+import android.view.InputEventReceiver;
+import android.view.Surface;
+
+import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
+
+import java.util.List;
+
+/**
+ * Implements the internal ITvInteractiveAppSession interface.
+ * @hide
+ */
+public class ITvInteractiveAppSessionWrapper
+ extends ITvInteractiveAppSession.Stub implements HandlerCaller.Callback {
+ private static final String TAG = "ITvInteractiveAppSessionWrapper";
+
+ private static final int EXECUTE_MESSAGE_TIMEOUT_SHORT_MILLIS = 1000;
+ private static final int EXECUTE_MESSAGE_TIMEOUT_LONG_MILLIS = 5 * 1000;
+
+ private static final int DO_RELEASE = 1;
+ private static final int DO_START_INTERACTIVE_APP = 2;
+ private static final int DO_STOP_INTERACTIVE_APP = 3;
+ private static final int DO_RESET_INTERACTIVE_APP = 4;
+ private static final int DO_CREATE_BI_INTERACTIVE_APP = 5;
+ private static final int DO_DESTROY_BI_INTERACTIVE_APP = 6;
+ private static final int DO_SET_TELETEXT_APP_ENABLED = 7;
+ private static final int DO_SEND_CURRENT_CHANNEL_URI = 8;
+ private static final int DO_SEND_CURRENT_CHANNEL_LCN = 9;
+ private static final int DO_SEND_STREAM_VOLUME = 10;
+ private static final int DO_SEND_TRACK_INFO_LIST = 11;
+ private static final int DO_SEND_CURRENT_TV_INPUT_ID = 12;
+ private static final int DO_SEND_SIGNING_RESULT = 13;
+ private static final int DO_NOTIFY_ERROR = 14;
+ private static final int DO_NOTIFY_TUNED = 15;
+ private static final int DO_NOTIFY_TRACK_SELECTED = 16;
+ private static final int DO_NOTIFY_TRACKS_CHANGED = 17;
+ private static final int DO_NOTIFY_VIDEO_AVAILABLE = 18;
+ private static final int DO_NOTIFY_VIDEO_UNAVAILABLE = 19;
+ private static final int DO_NOTIFY_CONTENT_ALLOWED = 20;
+ private static final int DO_NOTIFY_CONTENT_BLOCKED = 21;
+ private static final int DO_NOTIFY_SIGNAL_STRENGTH = 22;
+ private static final int DO_SET_SURFACE = 23;
+ private static final int DO_DISPATCH_SURFACE_CHANGED = 24;
+ private static final int DO_NOTIFY_BROADCAST_INFO_RESPONSE = 25;
+ private static final int DO_NOTIFY_AD_RESPONSE = 26;
+ private static final int DO_CREATE_MEDIA_VIEW = 27;
+ private static final int DO_RELAYOUT_MEDIA_VIEW = 28;
+ private static final int DO_REMOVE_MEDIA_VIEW = 29;
+
+ private final HandlerCaller mCaller;
+ private Session mSessionImpl;
+ private InputChannel mChannel;
+ private TvInteractiveAppEventReceiver mReceiver;
+
+ public ITvInteractiveAppSessionWrapper(
+ Context context, Session mSessionImpl, InputChannel channel) {
+ this.mSessionImpl = mSessionImpl;
+ mCaller = new HandlerCaller(context, null, this, true /* asyncHandler */);
+ mChannel = channel;
+ if (channel != null) {
+ mReceiver = new TvInteractiveAppEventReceiver(channel, context.getMainLooper());
+ }
+ }
+
+ @Override
+ public void executeMessage(Message msg) {
+ if (mSessionImpl == null) {
+ return;
+ }
+
+ long startTime = System.nanoTime();
+ switch (msg.what) {
+ case DO_RELEASE: {
+ mSessionImpl.release();
+ mSessionImpl = null;
+ if (mReceiver != null) {
+ mReceiver.dispose();
+ mReceiver = null;
+ }
+ if (mChannel != null) {
+ mChannel.dispose();
+ mChannel = null;
+ }
+ break;
+ }
+ case DO_START_INTERACTIVE_APP: {
+ mSessionImpl.startInteractiveApp();
+ break;
+ }
+ case DO_STOP_INTERACTIVE_APP: {
+ mSessionImpl.stopInteractiveApp();
+ break;
+ }
+ case DO_RESET_INTERACTIVE_APP: {
+ mSessionImpl.resetInteractiveApp();
+ break;
+ }
+ case DO_CREATE_BI_INTERACTIVE_APP: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ mSessionImpl.createBiInteractiveApp((Uri) args.arg1, (Bundle) args.arg2);
+ args.recycle();
+ break;
+ }
+ case DO_DESTROY_BI_INTERACTIVE_APP: {
+ mSessionImpl.destroyBiInteractiveApp((String) msg.obj);
+ break;
+ }
+ case DO_SET_TELETEXT_APP_ENABLED: {
+ mSessionImpl.setTeletextAppEnabled((Boolean) msg.obj);
+ break;
+ }
+ case DO_SEND_CURRENT_CHANNEL_URI: {
+ mSessionImpl.sendCurrentChannelUri((Uri) msg.obj);
+ break;
+ }
+ case DO_SEND_CURRENT_CHANNEL_LCN: {
+ mSessionImpl.sendCurrentChannelLcn((Integer) msg.obj);
+ break;
+ }
+ case DO_SEND_STREAM_VOLUME: {
+ mSessionImpl.sendStreamVolume((Float) msg.obj);
+ break;
+ }
+ case DO_SEND_TRACK_INFO_LIST: {
+ mSessionImpl.sendTrackInfoList((List<TvTrackInfo>) msg.obj);
+ break;
+ }
+ case DO_SEND_CURRENT_TV_INPUT_ID: {
+ mSessionImpl.sendCurrentTvInputId((String) msg.obj);
+ break;
+ }
+ case DO_SEND_SIGNING_RESULT: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ mSessionImpl.sendSigningResult((String) args.arg1, (byte[]) args.arg2);
+ args.recycle();
+ break;
+ }
+ case DO_NOTIFY_ERROR: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ mSessionImpl.notifyError((String) args.arg1, (Bundle) args.arg2);
+ args.recycle();
+ break;
+ }
+ case DO_NOTIFY_TUNED: {
+ mSessionImpl.notifyTuned((Uri) msg.obj);
+ break;
+ }
+ case DO_NOTIFY_TRACK_SELECTED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ mSessionImpl.notifyTrackSelected((Integer) args.arg1, (String) args.arg2);
+ args.recycle();
+ break;
+ }
+ case DO_NOTIFY_TRACKS_CHANGED: {
+ mSessionImpl.notifyTracksChanged((List<TvTrackInfo>) msg.obj);
+ break;
+ }
+ case DO_NOTIFY_VIDEO_AVAILABLE: {
+ mSessionImpl.notifyVideoAvailable();
+ break;
+ }
+ case DO_NOTIFY_VIDEO_UNAVAILABLE: {
+ mSessionImpl.notifyVideoUnavailable((Integer) msg.obj);
+ break;
+ }
+ case DO_NOTIFY_CONTENT_ALLOWED: {
+ mSessionImpl.notifyContentAllowed();
+ break;
+ }
+ case DO_NOTIFY_CONTENT_BLOCKED: {
+ mSessionImpl.notifyContentBlocked((TvContentRating) msg.obj);
+ break;
+ }
+ case DO_NOTIFY_SIGNAL_STRENGTH: {
+ mSessionImpl.notifySignalStrength((Integer) msg.obj);
+ break;
+ }
+ case DO_SET_SURFACE: {
+ mSessionImpl.setSurface((Surface) msg.obj);
+ break;
+ }
+ case DO_DISPATCH_SURFACE_CHANGED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ mSessionImpl.dispatchSurfaceChanged(
+ (Integer) args.arg1, (Integer) args.arg2, (Integer) args.arg3);
+ args.recycle();
+ break;
+ }
+ case DO_NOTIFY_BROADCAST_INFO_RESPONSE: {
+ mSessionImpl.notifyBroadcastInfoResponse((BroadcastInfoResponse) msg.obj);
+ break;
+ }
+ case DO_NOTIFY_AD_RESPONSE: {
+ mSessionImpl.notifyAdResponse((AdResponse) msg.obj);
+ break;
+ }
+ case DO_CREATE_MEDIA_VIEW: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ mSessionImpl.createMediaView((IBinder) args.arg1, (Rect) args.arg2);
+ args.recycle();
+ break;
+ }
+ case DO_RELAYOUT_MEDIA_VIEW: {
+ mSessionImpl.relayoutMediaView((Rect) msg.obj);
+ break;
+ }
+ case DO_REMOVE_MEDIA_VIEW: {
+ mSessionImpl.removeMediaView(true);
+ break;
+ }
+ default: {
+ Log.w(TAG, "Unhandled message code: " + msg.what);
+ break;
+ }
+ }
+ long durationMs = (System.nanoTime() - startTime) / (1000 * 1000);
+ if (durationMs > EXECUTE_MESSAGE_TIMEOUT_SHORT_MILLIS) {
+ Log.w(TAG, "Handling message (" + msg.what + ") took too long time (duration="
+ + durationMs + "ms)");
+ if (durationMs > EXECUTE_MESSAGE_TIMEOUT_LONG_MILLIS) {
+ // TODO: handle timeout
+ }
+ }
+ }
+
+ @Override
+ public void startInteractiveApp() {
+ mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_START_INTERACTIVE_APP));
+ }
+
+ @Override
+ public void stopInteractiveApp() {
+ mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_STOP_INTERACTIVE_APP));
+ }
+
+ @Override
+ public void resetInteractiveApp() {
+ mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_RESET_INTERACTIVE_APP));
+ }
+
+ @Override
+ public void createBiInteractiveApp(@NonNull Uri biIAppUri, @Nullable Bundle params) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageOO(DO_CREATE_BI_INTERACTIVE_APP, biIAppUri, params));
+ }
+
+ @Override
+ public void destroyBiInteractiveApp(@NonNull String biIAppId) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageO(DO_DESTROY_BI_INTERACTIVE_APP, biIAppId));
+ }
+
+ @Override
+ public void setTeletextAppEnabled(boolean enable) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageO(DO_SET_TELETEXT_APP_ENABLED, enable));
+ }
+
+ @Override
+ public void sendCurrentChannelUri(@Nullable Uri channelUri) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageO(DO_SEND_CURRENT_CHANNEL_URI, channelUri));
+ }
+
+ @Override
+ public void sendCurrentChannelLcn(int lcn) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageO(DO_SEND_CURRENT_CHANNEL_LCN, lcn));
+ }
+
+ @Override
+ public void sendStreamVolume(float volume) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageO(DO_SEND_STREAM_VOLUME, volume));
+ }
+
+ @Override
+ public void sendTrackInfoList(@NonNull List<TvTrackInfo> tracks) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageO(DO_SEND_TRACK_INFO_LIST, tracks));
+ }
+
+ @Override
+ public void sendCurrentTvInputId(@Nullable String inputId) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageO(DO_SEND_CURRENT_TV_INPUT_ID, inputId));
+ }
+
+ @Override
+ public void sendSigningResult(@NonNull String signingId, @NonNull byte[] result) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageOO(DO_SEND_SIGNING_RESULT, signingId, result));
+ }
+
+ @Override
+ public void notifyError(@NonNull String errMsg, @NonNull Bundle params) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageOO(DO_NOTIFY_ERROR, errMsg, params));
+ }
+
+ @Override
+ public void release() {
+ mSessionImpl.scheduleMediaViewCleanup();
+ mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_RELEASE));
+ }
+
+ @Override
+ public void notifyTuned(Uri channelUri) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_TUNED, channelUri));
+ }
+
+ @Override
+ public void notifyTrackSelected(int type, final String trackId) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageOO(DO_NOTIFY_TRACK_SELECTED, type, trackId));
+ }
+
+ @Override
+ public void notifyTracksChanged(List<TvTrackInfo> tracks) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_TRACKS_CHANGED, tracks));
+ }
+
+ @Override
+ public void notifyVideoAvailable() {
+ mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_NOTIFY_VIDEO_AVAILABLE));
+ }
+
+ @Override
+ public void notifyVideoUnavailable(int reason) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_VIDEO_UNAVAILABLE, reason));
+ }
+
+ @Override
+ public void notifyContentAllowed() {
+ mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_NOTIFY_CONTENT_ALLOWED));
+ }
+
+ @Override
+ public void notifyContentBlocked(String rating) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_CONTENT_BLOCKED, rating));
+ }
+
+ @Override
+ public void notifySignalStrength(int strength) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_SIGNAL_STRENGTH, strength));
+ }
+
+ @Override
+ public void setSurface(Surface surface) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_SURFACE, surface));
+ }
+
+ @Override
+ public void dispatchSurfaceChanged(int format, int width, int height) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageIIII(DO_DISPATCH_SURFACE_CHANGED, format, width, height, 0));
+ }
+
+ @Override
+ public void notifyBroadcastInfoResponse(BroadcastInfoResponse response) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageO(DO_NOTIFY_BROADCAST_INFO_RESPONSE, response));
+ }
+
+ @Override
+ public void notifyAdResponse(AdResponse response) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_AD_RESPONSE, response));
+ }
+
+ @Override
+ public void createMediaView(IBinder windowToken, Rect frame) {
+ mCaller.executeOrSendMessage(
+ mCaller.obtainMessageOO(DO_CREATE_MEDIA_VIEW, windowToken, frame));
+ }
+
+ @Override
+ public void relayoutMediaView(Rect frame) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_RELAYOUT_MEDIA_VIEW, frame));
+ }
+
+ @Override
+ public void removeMediaView() {
+ mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_REMOVE_MEDIA_VIEW));
+ }
+
+ private final class TvInteractiveAppEventReceiver extends InputEventReceiver {
+ TvInteractiveAppEventReceiver(InputChannel inputChannel, Looper looper) {
+ super(inputChannel, looper);
+ }
+
+ @Override
+ public void onInputEvent(InputEvent event) {
+ if (mSessionImpl == null) {
+ // The session has been finished.
+ finishInputEvent(event, false);
+ return;
+ }
+
+ int handled = mSessionImpl.dispatchInputEvent(event, this);
+ if (handled != TvInteractiveAppManager.Session.DISPATCH_IN_PROGRESS) {
+ finishInputEvent(
+ event, handled == TvInteractiveAppManager.Session.DISPATCH_HANDLED);
+ }
+ }
+ }
+}
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
index 54700b6..f5b4322 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
@@ -45,7 +45,6 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.RemoteCallbackList;
@@ -1416,193 +1415,6 @@
}
}
- /**
- * Implements the internal ITvInteractiveAppSession interface.
- * @hide
- */
- public static class ITvInteractiveAppSessionWrapper extends ITvInteractiveAppSession.Stub {
- // TODO: put ITvInteractiveAppSessionWrapper in a separate Java file
- private final Session mSessionImpl;
- private InputChannel mChannel;
- private TvInteractiveAppEventReceiver mReceiver;
-
- public ITvInteractiveAppSessionWrapper(
- Context context, Session mSessionImpl, InputChannel channel) {
- this.mSessionImpl = mSessionImpl;
- mChannel = channel;
- if (channel != null) {
- mReceiver = new TvInteractiveAppEventReceiver(channel, context.getMainLooper());
- }
- }
-
- @Override
- public void startInteractiveApp() {
- mSessionImpl.startInteractiveApp();
- }
-
- @Override
- public void stopInteractiveApp() {
- mSessionImpl.stopInteractiveApp();
- }
-
- @Override
- public void resetInteractiveApp() {
- mSessionImpl.resetInteractiveApp();
- }
-
- @Override
- public void createBiInteractiveApp(@NonNull Uri biIAppUri, @Nullable Bundle params) {
- mSessionImpl.createBiInteractiveApp(biIAppUri, params);
- }
-
- @Override
- public void setTeletextAppEnabled(boolean enable) {
- mSessionImpl.setTeletextAppEnabled(enable);
- }
-
- @Override
- public void destroyBiInteractiveApp(@NonNull String biIAppId) {
- mSessionImpl.destroyBiInteractiveApp(biIAppId);
- }
-
- @Override
- public void sendCurrentChannelUri(@Nullable Uri channelUri) {
- mSessionImpl.sendCurrentChannelUri(channelUri);
- }
-
- @Override
- public void sendCurrentChannelLcn(int lcn) {
- mSessionImpl.sendCurrentChannelLcn(lcn);
- }
-
- @Override
- public void sendStreamVolume(float volume) {
- mSessionImpl.sendStreamVolume(volume);
- }
-
- @Override
- public void sendTrackInfoList(@NonNull List<TvTrackInfo> tracks) {
- mSessionImpl.sendTrackInfoList(tracks);
- }
-
- @Override
- public void sendCurrentTvInputId(@Nullable String inputId) {
- mSessionImpl.sendCurrentTvInputId(inputId);
- }
-
- @Override
- public void sendSigningResult(@NonNull String signingId, @NonNull byte[] result) {
- mSessionImpl.sendSigningResult(signingId, result);
- }
-
- @Override
- public void notifyError(@NonNull String errMsg, @NonNull Bundle params) {
- mSessionImpl.notifyError(errMsg, params);
- }
-
- @Override
- public void release() {
- mSessionImpl.scheduleMediaViewCleanup();
- mSessionImpl.release();
- }
-
- @Override
- public void notifyTuned(Uri channelUri) {
- mSessionImpl.notifyTuned(channelUri);
- }
-
- @Override
- public void notifyTrackSelected(int type, final String trackId) {
- mSessionImpl.notifyTrackSelected(type, trackId);
- }
-
- @Override
- public void notifyTracksChanged(List<TvTrackInfo> tracks) {
- mSessionImpl.notifyTracksChanged(tracks);
- }
-
- @Override
- public void notifyVideoAvailable() {
- mSessionImpl.notifyVideoAvailable();
- }
-
- @Override
- public void notifyVideoUnavailable(int reason) {
- mSessionImpl.notifyVideoUnavailable(reason);
- }
-
- @Override
- public void notifyContentAllowed() {
- mSessionImpl.notifyContentAllowed();
- }
-
- @Override
- public void notifyContentBlocked(String rating) {
- mSessionImpl.notifyContentBlocked(TvContentRating.unflattenFromString(rating));
- }
-
- @Override
- public void notifySignalStrength(int strength) {
- mSessionImpl.notifySignalStrength(strength);
- }
-
- @Override
- public void setSurface(Surface surface) {
- mSessionImpl.setSurface(surface);
- }
-
- @Override
- public void dispatchSurfaceChanged(int format, int width, int height) {
- mSessionImpl.dispatchSurfaceChanged(format, width, height);
- }
-
- @Override
- public void notifyBroadcastInfoResponse(BroadcastInfoResponse response) {
- mSessionImpl.notifyBroadcastInfoResponse(response);
- }
-
- @Override
- public void notifyAdResponse(AdResponse response) {
- mSessionImpl.notifyAdResponse(response);
- }
-
- @Override
- public void createMediaView(IBinder windowToken, Rect frame) {
- mSessionImpl.createMediaView(windowToken, frame);
- }
-
- @Override
- public void relayoutMediaView(Rect frame) {
- mSessionImpl.relayoutMediaView(frame);
- }
-
- @Override
- public void removeMediaView() {
- mSessionImpl.removeMediaView(true);
- }
-
- private final class TvInteractiveAppEventReceiver extends InputEventReceiver {
- TvInteractiveAppEventReceiver(InputChannel inputChannel, Looper looper) {
- super(inputChannel, looper);
- }
-
- @Override
- public void onInputEvent(InputEvent event) {
- if (mSessionImpl == null) {
- // The session has been finished.
- finishInputEvent(event, false);
- return;
- }
-
- int handled = mSessionImpl.dispatchInputEvent(event, this);
- if (handled != TvInteractiveAppManager.Session.DISPATCH_IN_PROGRESS) {
- finishInputEvent(
- event, handled == TvInteractiveAppManager.Session.DISPATCH_HANDLED);
- }
- }
- }
- }
-
@SuppressLint("HandlerLeak")
private final class ServiceHandler extends Handler {
private static final int DO_CREATE_SESSION = 1;
diff --git a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/MainActivity.kt b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/MainActivity.kt
index 8ecc2a2..eef81e0 100644
--- a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/MainActivity.kt
+++ b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/MainActivity.kt
@@ -16,43 +16,7 @@
package com.android.settingslib.spa.codelab
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.navigation.compose.NavHost
-import androidx.navigation.compose.composable
-import androidx.navigation.compose.rememberNavController
-import com.android.settingslib.spa.framework.localNavController
-import com.android.settingslib.spa.theme.SettingsTheme
+import com.android.settingslib.spa.codelab.page.codelabPageRepository
+import com.android.settingslib.spa.framework.SpaActivity
-class MainActivity : ComponentActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContent {
- MainContent()
- }
- }
-}
-
-object Destinations {
- const val Home = "Home"
- const val Preference = "Preference"
-}
-
-@Composable
-private fun MainContent() {
- SettingsTheme {
- val navController = rememberNavController()
- CompositionLocalProvider(navController.localNavController()) {
- NavHost(
- navController = navController,
- startDestination = Destinations.Home,
- ) {
- composable(Destinations.Home) { HomeScreen() }
- composable(Destinations.Preference) { PreferenceCodelab() }
- }
- }
- }
-}
+class MainActivity : SpaActivity(codelabPageRepository)
diff --git a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/ArgumentPage.kt b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/ArgumentPage.kt
new file mode 100644
index 0000000..484b604
--- /dev/null
+++ b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/ArgumentPage.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.codelab.page
+
+import android.os.Bundle
+import androidx.compose.foundation.layout.Column
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.navigation.NavType
+import androidx.navigation.navArgument
+import com.android.settingslib.spa.api.SettingsPageProvider
+import com.android.settingslib.spa.framework.navigator
+import com.android.settingslib.spa.framework.toState
+import com.android.settingslib.spa.theme.SettingsTheme
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+
+private const val STRING_PARAM_NAME = "stringParam"
+private const val INT_PARAM_NAME = "intParam"
+
+object ArgumentPageProvider : SettingsPageProvider {
+ override val name = Destinations.Argument
+
+ override val arguments = listOf(
+ navArgument(STRING_PARAM_NAME) { type = NavType.StringType },
+ navArgument(INT_PARAM_NAME) { type = NavType.IntType },
+ )
+
+ @Composable
+ override fun Page(arguments: Bundle?) {
+ ArgumentPage(
+ stringParam = arguments!!.getString(STRING_PARAM_NAME, "default"),
+ intParam = arguments.getInt(INT_PARAM_NAME),
+ )
+ }
+
+ @Composable
+ fun EntryItem(stringParam: String, intParam: Int) {
+ Preference(object : PreferenceModel {
+ override val title = "Sample page with arguments"
+ override val summary =
+ "$STRING_PARAM_NAME=$stringParam, $INT_PARAM_NAME=$intParam".toState()
+ override val onClick = navigator("${Destinations.Argument}/$stringParam/$intParam")
+ })
+ }
+}
+
+@Composable
+fun ArgumentPage(stringParam: String, intParam: Int) {
+ Column {
+ Preference(object : PreferenceModel {
+ override val title = "String param value"
+ override val summary = stringParam.toState()
+ })
+
+ Preference(object : PreferenceModel {
+ override val title = "Int param value"
+ override val summary = intParam.toString().toState()
+ })
+
+ ArgumentPageProvider.EntryItem(stringParam = "foo", intParam = intParam + 1)
+
+ ArgumentPageProvider.EntryItem(stringParam = "bar", intParam = intParam + 1)
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun ArgumentPagePreview() {
+ SettingsTheme {
+ ArgumentPage(stringParam = "foo", intParam = 0)
+ }
+}
diff --git a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/HomeScreen.kt b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/HomePage.kt
similarity index 73%
rename from packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/HomeScreen.kt
rename to packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/HomePage.kt
index 574857f..27c70e4 100644
--- a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/HomeScreen.kt
+++ b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/HomePage.kt
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-package com.android.settingslib.spa.codelab
+package com.android.settingslib.spa.codelab.page
+import android.os.Bundle
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
@@ -24,14 +25,22 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
-import com.android.settingslib.spa.framework.onClickNavigateTo
+import com.android.settingslib.spa.api.SettingsPageProvider
+import com.android.settingslib.spa.codelab.R
import com.android.settingslib.spa.theme.SettingsDimension
import com.android.settingslib.spa.theme.SettingsTheme
-import com.android.settingslib.spa.widget.preference.Preference
-import com.android.settingslib.spa.widget.preference.PreferenceModel
+
+object HomePageProvider : SettingsPageProvider {
+ override val name = Destinations.Home
+
+ @Composable
+ override fun Page(arguments: Bundle?) {
+ HomePage()
+ }
+}
@Composable
-fun HomeScreen() {
+private fun HomePage() {
Column {
Text(
text = stringResource(R.string.app_name),
@@ -40,10 +49,9 @@
style = MaterialTheme.typography.headlineMedium,
)
- Preference(object : PreferenceModel {
- override val title = "Preference"
- override val onClick: (() -> Unit) = onClickNavigateTo(Destinations.Preference)
- })
+ PreferencePageProvider.EntryItem()
+
+ ArgumentPageProvider.EntryItem(stringParam = "foo", intParam = 0)
}
}
@@ -51,6 +59,6 @@
@Composable
private fun HomeScreenPreview() {
SettingsTheme {
- HomeScreen()
+ HomePage()
}
}
diff --git a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/PageRepository.kt b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/PageRepository.kt
new file mode 100644
index 0000000..862fc1e
--- /dev/null
+++ b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/PageRepository.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.codelab.page
+
+import com.android.settingslib.spa.api.SettingsPageRepository
+
+object Destinations {
+ const val Home = "Home"
+ const val Preference = "Preference"
+ const val Argument = "Argument"
+}
+
+val codelabPageRepository = SettingsPageRepository(
+ allPages = listOf(HomePageProvider, PreferencePageProvider, ArgumentPageProvider),
+ startDestination = Destinations.Home,
+)
diff --git a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/PreferenceCodelab.kt b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/PreferencePage.kt
similarity index 80%
rename from packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/PreferenceCodelab.kt
rename to packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/PreferencePage.kt
index 4e24aa1..81627f6 100644
--- a/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/PreferenceCodelab.kt
+++ b/packages/SettingsLib/Spa/codelab/src/com/android/settingslib/spa/codelab/page/PreferencePage.kt
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-package com.android.settingslib.spa.codelab
+package com.android.settingslib.spa.codelab.page
+import android.os.Bundle
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
@@ -29,14 +30,33 @@
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
+import com.android.settingslib.spa.api.SettingsPageProvider
+import com.android.settingslib.spa.framework.navigator
import com.android.settingslib.spa.framework.toState
import com.android.settingslib.spa.theme.SettingsTheme
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import kotlinx.coroutines.delay
+object PreferencePageProvider : SettingsPageProvider {
+ override val name = Destinations.Preference
+
+ @Composable
+ override fun Page(arguments: Bundle?) {
+ PreferencePage()
+ }
+
+ @Composable
+ fun EntryItem() {
+ Preference(object : PreferenceModel {
+ override val title = "Sample Preference"
+ override val onClick = navigator(Destinations.Preference)
+ })
+ }
+}
+
@Composable
-fun PreferenceCodelab() {
+private fun PreferencePage() {
Column(Modifier.verticalScroll(rememberScrollState())) {
Preference(object : PreferenceModel {
override val title = "Preference"
@@ -82,8 +102,8 @@
@Preview(showBackground = true)
@Composable
-private fun PreferenceCodelabPreview() {
+private fun PreferencePagePreview() {
SettingsTheme {
- PreferenceCodelab()
+ PreferencePage()
}
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/api/SettingsPageProvider.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/api/SettingsPageProvider.kt
new file mode 100644
index 0000000..0ad0003
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/api/SettingsPageProvider.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.api
+
+import android.os.Bundle
+import androidx.compose.runtime.Composable
+import androidx.navigation.NamedNavArgument
+
+/**
+ * An SettingsPageProvider represent a Settings page.
+ */
+interface SettingsPageProvider {
+
+ /** The page name without arguments. */
+ val name: String
+
+ /** The page arguments, default is no arguments. */
+ val arguments: List<NamedNavArgument>
+ get() = emptyList()
+
+ /** The [Composable] used to render this page. */
+ @Composable
+ fun Page(arguments: Bundle?)
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/api/SettingsPageRepository.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/api/SettingsPageRepository.kt
new file mode 100644
index 0000000..ce39f4f
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/api/SettingsPageRepository.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.api
+
+data class SettingsPageRepository(
+ val allPages: List<SettingsPageProvider>,
+ val startDestination: String,
+)
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/NavControllerWrapper.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/NavControllerWrapper.kt
index 55bc78b..35112ad 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/NavControllerWrapper.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/NavControllerWrapper.kt
@@ -39,7 +39,7 @@
}
@Composable
-fun onClickNavigateTo(route: String): () -> Unit {
+fun navigator(route: String): () -> Unit {
val navController = LocalNavController.current
return { navController.navigate(route) }
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/SpaActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/SpaActivity.kt
new file mode 100644
index 0000000..28a5899e
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/SpaActivity.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.framework
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.navigation.compose.NavHost
+import androidx.navigation.compose.composable
+import androidx.navigation.compose.rememberNavController
+import com.android.settingslib.spa.api.SettingsPageProvider
+import com.android.settingslib.spa.api.SettingsPageRepository
+import com.android.settingslib.spa.theme.SettingsTheme
+
+open class SpaActivity(
+ private val settingsPageRepository: SettingsPageRepository,
+) : ComponentActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContent {
+ MainContent()
+ }
+ }
+
+ @Composable
+ private fun MainContent() {
+ SettingsTheme {
+ val navController = rememberNavController()
+ CompositionLocalProvider(navController.localNavController()) {
+ NavHost(navController, settingsPageRepository.startDestination) {
+ for (page in settingsPageRepository.allPages) {
+ composable(
+ route = page.route,
+ arguments = page.arguments,
+ ) { navBackStackEntry ->
+ page.Page(navBackStackEntry.arguments)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private val SettingsPageProvider.route: String
+ get() = name + arguments.joinToString("") { argument -> "/{${argument.name}}" }
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt
new file mode 100644
index 0000000..d415e9b
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BaseLayout.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.widget.preference
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.material3.Divider
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.alpha
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import com.android.settingslib.spa.framework.toState
+import com.android.settingslib.spa.theme.SettingsDimension
+import com.android.settingslib.spa.theme.SettingsOpacity
+import com.android.settingslib.spa.theme.SettingsTheme
+
+@Composable
+internal fun BaseLayout(
+ title: String,
+ subTitle: @Composable () -> Unit,
+ modifier: Modifier = Modifier,
+ icon: (@Composable () -> Unit)? = null,
+ enabled: State<Boolean> = true.toState(),
+ paddingStart: Dp = SettingsDimension.itemPaddingStart,
+ paddingEnd: Dp = SettingsDimension.itemPaddingEnd,
+ paddingVertical: Dp = SettingsDimension.itemPaddingVertical,
+ widget: @Composable () -> Unit = {},
+) {
+ Row(
+ modifier = modifier
+ .fillMaxWidth()
+ .padding(end = paddingEnd),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ val alphaModifier =
+ Modifier.alpha(if (enabled.value) SettingsOpacity.Full else SettingsOpacity.Disabled)
+ BaseIcon(icon, alphaModifier, paddingStart)
+ Titles(
+ title = title,
+ subTitle = subTitle,
+ modifier = alphaModifier
+ .weight(1f)
+ .padding(vertical = paddingVertical),
+ )
+ widget()
+ }
+}
+
+@Composable
+private fun BaseIcon(
+ icon: @Composable (() -> Unit)?,
+ modifier: Modifier,
+ paddingStart: Dp,
+) {
+ if (icon != null) {
+ Box(
+ modifier = modifier.size(SettingsDimension.itemIconContainerSize),
+ contentAlignment = Alignment.Center,
+ ) {
+ icon()
+ }
+ } else {
+ Spacer(modifier = Modifier.width(width = paddingStart))
+ }
+}
+
+// Extracts a scope to avoid frequent recompose outside scope.
+@Composable
+private fun Titles(title: String, subTitle: @Composable () -> Unit, modifier: Modifier) {
+ Column(modifier) {
+ Text(
+ text = title,
+ color = MaterialTheme.colorScheme.onSurface,
+ style = MaterialTheme.typography.titleMedium,
+ )
+ subTitle()
+ }
+}
+
+@Preview
+@Composable
+private fun BaseLayoutPreview() {
+ SettingsTheme {
+ BaseLayout(
+ title = "Title",
+ subTitle = {
+ Divider(thickness = 10.dp)
+ }
+ )
+ }
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt
index 7476f4e..563a47a 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/BasePreference.kt
@@ -16,14 +16,6 @@
package com.android.settingslib.spa.widget.preference
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.BatteryChargingFull
import androidx.compose.material3.Icon
@@ -31,14 +23,11 @@
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.alpha
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import com.android.settingslib.spa.framework.toState
import com.android.settingslib.spa.theme.SettingsDimension
-import com.android.settingslib.spa.theme.SettingsOpacity
import com.android.settingslib.spa.theme.SettingsTheme
@Composable
@@ -53,52 +42,25 @@
paddingVertical: Dp = SettingsDimension.itemPaddingVertical,
widget: @Composable () -> Unit = {},
) {
- Row(
- modifier = modifier
- .fillMaxWidth()
- .padding(end = paddingEnd),
- verticalAlignment = Alignment.CenterVertically,
- ) {
- val alphaModifier =
- Modifier.alpha(if (enabled.value) SettingsOpacity.Full else SettingsOpacity.Disabled)
- if (icon != null) {
- Box(
- modifier = alphaModifier.size(SettingsDimension.itemIconContainerSize),
- contentAlignment = Alignment.Center,
- ) {
- icon()
+ BaseLayout(
+ title = title,
+ subTitle = {
+ if (summary.value.isNotEmpty()) {
+ Text(
+ text = summary.value,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ style = MaterialTheme.typography.bodyMedium,
+ )
}
- } else {
- Spacer(modifier = Modifier.width(width = paddingStart))
- }
- TitleAndSummary(
- title = title,
- summary = summary,
- modifier = alphaModifier
- .weight(1f)
- .padding(vertical = paddingVertical),
- )
- widget()
- }
-}
-
-// Extracts a scope to avoid frequent recompose outside scope.
-@Composable
-private fun TitleAndSummary(title: String, summary: State<String>, modifier: Modifier) {
- Column(modifier) {
- Text(
- text = title,
- color = MaterialTheme.colorScheme.onSurface,
- style = MaterialTheme.typography.titleMedium,
- )
- if (summary.value.isNotEmpty()) {
- Text(
- text = summary.value,
- color = MaterialTheme.colorScheme.onSurfaceVariant,
- style = MaterialTheme.typography.bodyMedium,
- )
- }
- }
+ },
+ modifier = modifier,
+ icon = icon,
+ enabled = enabled,
+ paddingStart = paddingStart,
+ paddingEnd = paddingEnd,
+ paddingVertical = paddingVertical,
+ widget = widget,
+ )
}
@Preview
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index 7165c14..1de7668 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Gebruik stelselkeuse (verstek)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-oudio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-oudio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Gebruik stelselkeuse (verstek)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-oudio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-oudio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Gebruik stelselkeuse (verstek)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 264faad..fe8030f 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Lêeroordrag"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Invoertoestel"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internettoegang"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Deling van kontakte en oproepgeskiedenis"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Gebruik vir deling van kontakte en oproepgeskiedenis"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Deling van internetverbinding"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Teksboodskappe"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-toegang"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Weer"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luggehalte"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Uitsaai-inligting"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Huiskontroles"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Kies \'n profielprent"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Verstekgebruikerikoon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fisieke sleutelbord"</string>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index 1108c82..a900d13 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ኦዲዮ"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ኦዲዮ"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ኦዲዮ"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ኦዲዮ"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
<item msgid="8003118270854840095">"44.1 ኪኸ"</item>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index b68cbd7..d3c034f 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ፋይል ማስተላለፍ"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ግቤት መሣሪያ"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"የበይነመረብ ድረስ"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"የእውቂያዎች እና የጥሪ ታሪክ ማጋራት"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"እውቂያዎችን እና የጥሪ ታሪክን ለማጋራት ይጠቀሙበት"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"የበይነ መረብ ተያያዥ ማጋሪያ"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"የጽሑፍ መልዕክቶች"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"የሲም መዳረሻ"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"የአየር ሁኔታ"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"የአየር ጥራት"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"የCast መረጃ"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"የመገለጫ ሥዕል ይምረጡ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ነባሪ የተጠቃሚ አዶ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"አካላዊ ቁልፍ ሰሌዳ"</string>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index eb4be38..8f7d7d2 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"استخدام اختيار النظام (تلقائي)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"استخدام اختيار النظام (تلقائي)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"استخدام اختيار النظام (تلقائي)"</item>
<item msgid="8003118270854840095">"44.1 كيلو هرتز"</item>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index c8b263b..6783654 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"نقل الملف"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"جهاز الإرسال"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"استخدام الإنترنت"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"مشاركة جهات الاتصال وسجل المكالمات"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"استخدام إعدادات بلوتوث لمشاركة جهات الاتصال وسجل المكالمات"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"مشاركة اتصال الإنترنت"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"الرسائل النصية"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"الوصول إلى شريحة SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"الطقس"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"جودة الهواء"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"معلومات البث"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"اختيار صورة الملف الشخصي"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"رمز المستخدم التلقائي"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"لوحة مفاتيح خارجية"</string>
diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml
index df23f67..4c879d0 100644
--- a/packages/SettingsLib/res/values-as/arrays.xml
+++ b/packages/SettingsLib/res/values-as/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"ছিষ্টেমৰ বাছনি ব্যৱহাৰ কৰক (ডিফ\'ল্ট)"</item>
- <item msgid="4055460186095649420">"এছবিচি"</item>
- <item msgid="720249083677397051">"এএচি"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিঅ\'"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিঅ’"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"ছিষ্টেমৰ বাছনি ব্যৱহাৰ কৰক (ডিফ\'ল্ট)"</item>
- <item msgid="9024885861221697796">"এছবিচি"</item>
- <item msgid="4688890470703790013">"এএচি"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিঅ’"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিঅ’"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ছিষ্টেমৰ বাছনি ব্যৱহাৰ কৰক (ডিফ\'ল্ট)"</item>
<item msgid="8003118270854840095">"৪৪.১ কিল\'হাৰ্টজ"</item>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index ea1aff0..543c703 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ফাইল স্থানান্তৰণ"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ইনপুট ডিভাইচ"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"ইণ্টাৰনেট সংযোগ"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"সম্পৰ্কসূচী আৰু কলৰ ইতিহাস শ্বেয়াৰ কৰা"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"সম্পৰ্কসূচী আৰু কলৰ ইতিহাস শ্বেয়াৰ কৰাৰ বাবে ব্যৱহাৰ কৰক"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ইণ্টাৰনেট সংযোগ শ্বেয়াৰ"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"পাঠ বাৰ্তা"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"ছিম প্ৰৱেশ"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"বতৰ"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"বায়ুৰ গুণগত মান"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"কাষ্টৰ তথ্য"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"এখন প্ৰ’ফাইল চিত্ৰ বাছনি কৰক"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ডিফ’ল্ট ব্যৱহাৰকাৰীৰ চিহ্ন"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"কায়িক কীব’ৰ্ড"</string>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index 5163791..48974a7 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Sistem Seçimini istifadə edin (Defolt)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Sistem Seçimini istifadə edin (Defolt)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Sistem Seçimini istifadə edin (Defolt)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 88333e82..f3e5d95 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fayl transferi"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Daxiletmə cihazı"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"İnternetə giriş"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kontaktlar və zəng tarixçəsi paylaşımı"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Kontaktlar və zəng tarixçəsi paylaşımı üçün istifadə edin"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"internet bağlantı paylaşımı"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Mətn Mesajları"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-karta giriş"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Hava"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Havanın keyfiyyəti"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Yayım məlumatı"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Profil şəkli seçin"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Defolt istifadəçi ikonası"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fiziki klaviatura"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index 5cc43f6..337da26 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Koristi izbor sistema (podrazumevano)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Koristi izbor sistema (podrazumevano)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Koristi izbor sistema (podrazumevano)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index a84d019..6a880aa 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos datoteke"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Ulazni uređaj"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Pristup Internetu"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Deljenje kontakata i istorije poziva"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Koristite za deljenje kontakata i istorije poziva"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Deljenje internet veze"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS-ovi"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Pristup SIM kartici"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Vreme"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvalitet vazduha"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Podaci o prebacivanju"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Odaberite sliku profila"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Podrazumevana ikona korisnika"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fizička tastatura"</string>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index 6259c2d..d843629 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Выбар сістэмы (стандартны)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Выбар сістэмы (стандартны)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Аўдыя <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Выбар сістэмы (стандартны)"</item>
<item msgid="8003118270854840095">"44,1 кГц"</item>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 37f8410..a902426 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Перадача файлаў"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Прылада ўводу"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Доступ у інтэрнэт"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Абагульванне кантактаў і гісторыі выклікаў"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Ужываць для абагульвання кантактаў і гісторыі выклікаў"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Прадастаўленне доступу да Інтэрнэту"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Тэкставыя паведамленні"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Доступ да SIM-карты"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Надвор\'е"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Якасць паветра"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Даныя пра трансляцыю"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Выберыце відарыс профілю"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Стандартны карыстальніцкі значок"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Фізічная клавіятура"</string>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index 49e66c0..1aad6ca7 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Използване на сист. избор (стандартно)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"Разширено аудиокодиране (AAC)"</item>
- <item msgid="1049450003868150455">"Аудио: <xliff:g id="APTX">aptX™</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item>
- <item msgid="2908219194098827570">"Аудио: <xliff:g id="APTX_HD">aptX™ HD</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Използване на сист. избор (стандартно)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"Разширено аудиокодиране (AAC)"</item>
- <item msgid="8627333814413492563">"Аудио: <xliff:g id="APTX">aptX™</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item>
- <item msgid="3517061573669307965">"Аудио: <xliff:g id="APTX_HD">aptX™ HD</xliff:g> от <xliff:g id="QUALCOMM">Qualcomm®</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Използване на сист. избор (стандартно)"</item>
<item msgid="8003118270854840095">"44,1 кХц"</item>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index f2cf69e..c512366 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Прехвърляне на файл"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Входно устройство"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Достъп до интернет"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Споделяне на контактите и ист. на обажд."</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Служи за споделяне на контактите и историята на обажданията"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Споделяне на връзката с интернет"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Текстови съобщения"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Достъп до SIM картата"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Времето"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Качество на въздуха"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Предаване: Инф."</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Изберете снимка на потребителския профил"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Икона за основния потребител"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Физическа клавиатура"</string>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index fdb611b..5e6bb95 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিও"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিও"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> অডিও"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> অডিও"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
<item msgid="8003118270854840095">"৪৪.১ kHz"</item>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 801fb34..23eed04 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ফাইল স্থানান্তর"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ইনপুট ডিভাইস"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"ইন্টারনেট অ্যাক্সেস"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"পরিচিতি এবং কলের ইতিহাস শেয়ার করা"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"পরিচিতি ও কলের ইতিহাস শেয়ার করার জন্য ব্যবহার করুন"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ইন্টারনেট কানেকশন শেয়ার করা হচ্ছে"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"এসএমএস"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"সিম অ্যাক্সেস"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"আবহাওয়া"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"এয়ার কোয়ালিটি"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"কাস্ট সম্পর্কিত তথ্য"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"হোম কন্ট্রোল"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"একটি প্রোফাইল ছবি বেছে নিন"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ডিফল্ট ব্যবহারকারীর আইকন"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ফিজিক্যাল কীবোর্ড"</string>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 32edef1..262a35f 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Korištenje odabira sistema (zadano)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Korištenje odabira sistema (zadano)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Korištenje odabira sistema (zadano)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 61082f6..78a484f 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenošenje fajla"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Ulazni uređaj"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Pristup internetu"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Dijeljenje kontakata i historije poziva"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Upotrijebite za dijeljenje kontakata i historije poziva"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Dijeljenje internet veze"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS-ovi"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Pristup SIM-u"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Vremenska prognoza"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvalitet zraka"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Podaci o emitiranju"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Odaberite sliku profila"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Zadana ikona korisnika"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fizička tastatura"</string>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index a267af8..8c34a1f 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Utilitza la selecció del sistema (predeterminada)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Utilitza la selecció del sistema (predeterminada)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Àudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Utilitza la selecció del sistema (predeterminada)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 881f9d4..606a379 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferència de fitxers"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositiu d\'entrada"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Accés a Internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Compartició de contactes i trucades"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Utilitza per compartir contactes i l\'historial de trucades"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Compartició de connexió d\'Internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Missatges de text"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Accés a la SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Temps"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualitat de l\'aire"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Informació d\'emissió"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Tria una foto de perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icona d\'usuari predeterminat"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclat físic"</string>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index 3eeae64..90bcaa4 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Použít systémový výběr (výchozí)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Použít systémový výběr (výchozí)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Zvuk <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Použít systémový výběr (výchozí)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 7f314bd..37c0bb4 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Přenos souborů"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Vstupní zařízení"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Přístup k internetu"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Sdílení kontaktů a historie volání"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Používat ke sdílení kontaktů a historie hovorů"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Sdílení internetového připojení"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Textové zprávy"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Přístup k SIM kartě"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Počasí"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvalita vzduchu"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info o odesílání"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Vyberte profilový obrázek"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Výchozí uživatelská ikona"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fyzická klávesnice"</string>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index 58ca722..155104ae 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Brug systemvalg (standard)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Brug systemvalg (standard)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Brug systemvalg (standard)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index c470b81..d80e1ec 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Filoverførsel"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Inputenhed"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetadgang"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Deling af kontakter og opkaldshistorik"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Brug til deling af kontakter og opkaldshistorik"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Deling af internetforbindelse"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Sms-beskeder"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Adgang til SIM-kort"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Vejr"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luftkvalitet"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast-oplysninger"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Vælg et profilbillede"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikon for standardbruger"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fysisk tastatur"</string>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index a8eb3f6..31126a8 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Systemauswahl verwenden (Standard)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-Audio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-Audio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Systemauswahl verwenden (Standard)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-Audio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-Audio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Systemauswahl verwenden (Standard)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 34a622b..d4fafe1 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Dateiübertragung"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Eingabegerät"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetzugriff"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Teilen von Kontakten und der Anrufliste"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Zum Teilen von Kontakten und der Anrufliste verwenden"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Freigabe der Internetverbindung"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Zugriff auf SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Wetter"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luftqualität"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Streaming-Info"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Profilbild auswählen"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Standardmäßiges Nutzersymbol"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Physische Tastatur"</string>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index ccd06fa..70000e1 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Ήχος <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index fdc7419..aa613a5 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Μεταφορά αρχείου"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Συσκευή εισόδου"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Πρόσβαση στο Διαδίκτυο"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Κοινοποίηση επαφών και ιστορικού κλήσεων"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Χρήση για την κοινοποίηση επαφών και του ιστορικού κλήσεων"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Κοινή χρήση σύνδεσης στο Διαδίκτυο"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Μηνύματα κειμένου"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Πρόσβαση SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Καιρός"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ποιότητα αέρα"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Πληροφορίες ηθοποιών"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Επιλογή φωτογραφίας προφίλ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Προεπιλεγμένο εικονίδιο χρήστη"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Φυσικό πληκτρολόγιο"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index 697e49a..fc6f791 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Use system selection (default)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Use system selection (default)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Use system selection (default)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 234109b..62c8e21 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Input device"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internet access"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacts and call history sharing"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use for contacts and call history sharing"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet connection sharing"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Text messages"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air quality"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml
index 697e49a..fc6f791 100644
--- a/packages/SettingsLib/res/values-en-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Use system selection (default)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Use system selection (default)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Use system selection (default)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index d88bb0e..8650b77 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Input device"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internet access"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacts and call history sharing"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use for contacts and call history sharing"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet connection sharing"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Text messages"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air quality"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index 697e49a..fc6f791 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Use system selection (default)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Use system selection (default)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Use system selection (default)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 234109b..62c8e21 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Input device"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internet access"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacts and call history sharing"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use for contacts and call history sharing"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet connection sharing"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Text messages"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air quality"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index 697e49a..fc6f791 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Use system selection (default)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Use system selection (default)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Use system selection (default)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 234109b..62c8e21 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"File transfer"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Input device"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internet access"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacts and call history sharing"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use for contacts and call history sharing"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet connection sharing"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Text messages"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM access"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air quality"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast info"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/arrays.xml b/packages/SettingsLib/res/values-en-rXC/arrays.xml
index aca3eb4..34db380 100644
--- a/packages/SettingsLib/res/values-en-rXC/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rXC/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Use System Selection (Default)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Use System Selection (Default)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Use System Selection (Default)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 5d775d3..21697b9 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -660,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Weather"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Air Quality"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Cast Info"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Home Controls"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Choose a profile picture"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Default user icon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Physical keyboard"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index 6a926d2..9b1aa3a 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Usar selección del sistema (predeterminado)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Usar selección del sistema (predeterminado)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Usar selección del sistema (predeterminado)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 98c1400..27cd0ab 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferencia de archivos"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acceso a Internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Compartir contactos e historial de llam."</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Uso para compartir contactos e historial de llamadas"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Compartir conexión a Internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensajes de texto"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acceso a SIM"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Clima"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Calidad del aire"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info de reparto"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Control de la casa"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Elige una foto de perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ícono de usuario predeterminado"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index 7c37fa5..0677864 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Usar preferencia del sistema (predeterminado)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Usar preferencia del sistema (predeterminado)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Usar preferencia del sistema (predeterminado)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 90c4fb8..d221c8d 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferencia de archivos"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acceso a Internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Compartir contactos e historial de llamadas"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Usar para compartir los contactos y el historial de llamadas"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Compartir conexión a Internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensajes de texto"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acceso a tarjeta SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Tiempo"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Calidad del aire"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de emisión"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Elige una imagen de perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icono de usuario predeterminado"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index 14d0fd1..d986ecf 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Süsteemi valiku kasutamine (vaikeseade)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Süsteemi valiku kasutamine (vaikeseade)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Heli: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Süsteemi valiku kasutamine (vaikeseade)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index a6c787a..f32ae23 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Failiedastus"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Sisendseade"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Juurdepääs internetile"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kontaktide ja kõneajaloo jagamine"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Kasutage kontaktide ja kõneajaloo jagamiseks"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Interneti-ühenduse jagamine"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Tekstsõnumid"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Juurdepääs SIM-ile"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Ilm"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Õhukvaliteet"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Osatäitjate teave"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Valige profiilipilt"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Vaikekasutajaikoon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Füüsiline klaviatuur"</string>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index cc47e27..d166e1b 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Erabili sistema-hautapena (lehenetsia)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audioa"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audioa"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Erabili sistema-hautapena (lehenetsia)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audioa"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audioa"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Erabili sistema-hautapena (lehenetsia)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 87cfaa8..bcb57e8 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fitxategi-transferentzia"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Sarrerako gailua"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Interneteko konexioa"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kontaktuak eta deien historia partekatzeko aukera"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Erabili kontaktuetarako eta deien historia partekatzeko"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Interneteko konexioa partekatzea"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Testu-mezuak"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIMerako sarbidea"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Eguraldia"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Airearen kalitatea"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Igorpenari buruzko informazioa"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Aukeratu profileko argazki bat"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Erabiltzaile lehenetsiaren ikonoa"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teklatu fisikoa"</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index d76389b..b7761dd 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"استفاده از انتخاب سیستم (پیشفرض)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"استفاده از انتخاب سیستم (پیشفرض)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"صوت <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"استفاده از انتخاب سیستم (پیشفرض)"</item>
<item msgid="8003118270854840095">"۴۴٫۱ کیلوهرتز"</item>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 51d74dd..6abe873 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"انتقال فایل"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"دستگاه ورودی"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"دسترسی به اینترنت"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"همرسانی مخاطبین و سابقه تماس"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"استفاده برای همرسانی مخاطبین و سابقه تماس"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"اشتراکگذاری اتصال اینترنت"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"پیامهای نوشتاری"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"دسترسی سیمکارت"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"آبوهوا"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"کیفیت هوا"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"اطلاعات پخش محتوا"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"انتخاب عکس نمایه"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"نماد کاربر پیشفرض"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"صفحهکلید فیزیکی"</string>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index f828186..2969892 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Käytä järjestelmän valintaa (oletus)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ‑ääni"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ‑ääni"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Käytä järjestelmän valintaa (oletus)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ‑ääni"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ‑ääni"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Käytä järjestelmän valintaa (oletus)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index c0f90b8..2f3436e 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Tiedostonsiirto"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Syöttölaite"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetyhteys"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Yhteystietojen ja soittohistorian jako"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Käytä yhteystiedoissa ja soittohistorian jakamiseen"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internetyhteyden jakaminen"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Tekstiviestit"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-kortin käyttö"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Sää"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ilmanlaatu"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Striimaustiedot"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Valitse profiilikuva"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Oletuskäyttäjäkuvake"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fyysinen näppäimistö"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 50c1bcb..12acbb6 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Utiliser sélect. du système (par défaut)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Utiliser sélect. du système (par défaut)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Utiliser sélect. du système (par défaut)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 14515cd..28b3cd9 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfert de fichier"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Périphérique d\'entrée"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Accès Internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Partage des contacts et des appels"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Sert à partager des contacts et l\'historique des appels"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Partage de connexion Internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Messages texte"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Accès à la carte SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Météo"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualité de l\'air"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info diffusion"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Choisir une photo de profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icône d\'utilisateur par défaut"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Clavier physique"</string>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index 6343f0d..80ac7e4 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Utiliser la sélection du système (par défaut)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Utiliser la sélection du système (par défaut)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Utiliser la sélection du système (par défaut)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 19ea6dd..da1497a 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfert de fichiers"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Périphérique d\'entrée"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Accès Internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Partage contacts/historique des appels"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"À utiliser pour partage des contacts/historique des appels"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Partage de connexion Internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Accès à la carte SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Météo"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualité de l\'air"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Infos distribution"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Choisissez une photo de profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icône de l\'utilisateur par défaut"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Clavier physique"</string>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index 22fb223..b6cf48e 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Usar selección do sistema (predeterminado)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Usa a selección do sistema (predeterminado)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Usar selección do sistema (predeterminado)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 94fa72a..7822749 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferencia de ficheiros"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acceso a Internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Compartir contactos e hist. de chamadas"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Uso da opción de compartir contactos e historial de chamadas"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Uso compartido da conexión a Internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensaxes de texto"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acceso á SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"O tempo"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Calidade do aire"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Datos da emisión"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Escolle unha imaxe do perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icona do usuario predeterminado"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index 318b5f5..7e668e7 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ઑડિયો"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ઑડિયો"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ઑડિયો"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ઑડિયો"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index a474d82..cebb1fe 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ફાઇલ સ્થાનાંતરણ"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ઇનપુટ ડિવાઇસ"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"ઇન્ટરનેટ ઍક્સેસ"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"સંપર્કો અને કૉલ ઇતિહાસની શેરિંગ"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"સંપર્કો અને કૉલ ઇતિહાસની શેરિંગ માટે ઉપયોગ કરો"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ઇન્ટરનેટ કનેક્શન શેરિંગ"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"ટેક્સ્ટ સંદેશા"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"સિમ ઍક્સેસ"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"હવામાન"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"હવાની ક્વૉલિટી"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"કાસ્ટ વિશેની માહિતી"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"પ્રોફાઇલ ફોટો પસંદ કરો"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ડિફૉલ્ટ વપરાશકર્તાનું આઇકન"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ભૌતિક કીબોર્ડ"</string>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 61a8f92..13da75b 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडियो"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडियो"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"सिस्टम से चुने जाने का इस्तेमाल करें (डिफ़ॉल्ट)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडियो"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडियो"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 55fc547..417d2b2 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"फ़ाइल स्थानांतरण"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"इनपुट डिवाइस"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"इंटरनेट ऐक्सेस"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"संपर्क और कॉल का इतिहास शेयर करें"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"इसका इस्तेमाल संपर्क और कॉल का इतिहास शेयर करने के लिए करें"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"इंटरनेट कनेक्शन साझाकरण"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"लेख संदेश"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"सिम ऐक्सेस"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"मौसम"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"हवा की क्वालिटी"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"कास्टिंग की जानकारी"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"प्रोफ़ाइल फ़ोटो चुनें"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"उपयोगकर्ता के लिए डिफ़ॉल्ट आइकॉन"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"फ़िज़िकल कीबोर्ड"</string>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index c979bc4..0e66858 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Upotreba odabira sustava (zadano)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Upotreba odabira sustava (zadano)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Upotreba odabira sustava (zadano)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 55a3e5e..267000f 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prijenos datoteke"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Ulazni uređaj"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Pristup internetu"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Dijeljenje kontakata i povijesti poziva"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Upotreba za dijeljenje kontakata i povijesti poziva"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Dijeljenje internetske veze"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS-ovi"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Pristup SIM-u"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Vremenska prognoza"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvaliteta zraka"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Inform. o emitiranju"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Odabir profilne slike"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikona zadanog korisnika"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fizička tipkovnica"</string>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index 230e554..a5f37ea 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Rendszerérték (alapértelmezett)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Rendszerérték (alapértelmezett)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Hang: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Rendszerérték (alapértelmezett)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 2454d1c..69ddad8 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fájlátvitel"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Beviteli eszköz"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetelérés"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Névjegyek és hívásnapló megosztása"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Névjegyek és hívásnapló megosztásához használható"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internetkapcsolat megosztása"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Szöveges üzenetek"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-elérés"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Időjárás"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Levegőminőség"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Átküldési információ"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Profilkép választása"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Alapértelmezett felhasználó ikonja"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fizikai billentyűzet"</string>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index 2a9c544..50d7c7f 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> աուդիո"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> աուդիո"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> աուդիո"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> աուդիո"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
<item msgid="8003118270854840095">"44,1 կՀց"</item>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 8966551..d8efbd3 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Ֆայլերի փոխանցում"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Ներմուծման սարք"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Ինտերնետի հասանելիություն"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Կիսվել կոնտակտներով/զանգերի պատմությամբ"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Օգտագործել՝ կոնտակտներով/զանգերի պատմությամբ կիսվելու համար"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Ինտերնետ կապի տարածում"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS հաղորդագրություններ"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM քարտի հասանելիություն"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Եղանակ"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Օդի որակը"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Հեռարձակման տվյալներ"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Պրոֆիլի նկար ընտրեք"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Օգտատիրոջ կանխադրված պատկերակ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Ֆիզիկական ստեղնաշար"</string>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 6349e53..5b0ad98 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Gunakan Pilihan Sistem (Default)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Gunakan Pilihan Sistem (Default)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Gunakan Pilihan Sistem (Default)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index c525317..029ad8b 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfer file"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Perangkat masukan"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Akses Internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Berbagi kontak dan histori panggilan"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Gunakan untuk berbagi kontak dan histori panggilan"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Berbagi koneksi internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Akses SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Cuaca"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kualitas Udara"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info Transmisi"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Pilih foto profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikon pengguna default"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Keyboard fisik"</string>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 730fcaf..9d481f8 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Nota val kerfisins (sjálfgefið)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> hljóð"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> hljóð"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Nota val kerfisins (sjálfgefið)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> hljóð"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> hljóð"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Nota val kerfisins (sjálfgefið)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index c06d2f0..ccf06b0 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Skráaflutningur"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Inntakstæki"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetaðgangur"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Tengiliðir, SMS-skilaboð og símtalaferill"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Nota til að deila tengiliðum og símtalaferli"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Deiling nettengingar"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Textaskilaboð"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Aðgangur að SIM-korti"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Veður"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Loftgæði"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Útsendingaruppl."</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Veldu prófílmynd"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Tákn sjálfgefins notanda"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Vélbúnaðarlyklaborð"</string>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index b7e114f..62450da3 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Usa selezione di sistema (predefinita)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Usa selezione di sistema (predefinita)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Usa selezione di sistema (predefinita)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index b3ac25a..3811152 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Trasferimento file"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo di input"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Accesso a Internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Condivis. contatti e cronologia chiamate"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Usa per condivisione di contatti e cronologia chiamate"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Condivisione connessione Internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Accesso alla SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Meteo"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualità dell\'aria"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info sul cast"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Scegli un\'immagine del profilo"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icona dell\'utente predefinito"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Tastiera fisica"</string>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 587016f..49f3fcf 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"שימוש בבחירת המערכת (ברירת המחדל)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"שימוש בבחירת המערכת (ברירת המחדל)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"אודיו <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"שימוש בבחירת המערכת (ברירת המחדל)"</item>
<item msgid="8003118270854840095">"44.1 קילו-הרץ"</item>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index f021b37..3421fb5 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"העברת קבצים"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"מכשיר קלט"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"גישה לאינטרנט"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"שיתוף אנשי הקשר והיסטוריית השיחות"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"ההגדרה משמשת לשיתוף של אנשי הקשר והיסטוריית השיחות"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"שיתוף חיבור לאינטרנט"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"הודעות טקסט"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"גישה ל-SIM"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"מזג אוויר"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"איכות האוויר"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"פרטי ההעברה"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"בית חכם"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"בחירה של תמונת פרופיל"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"סמל המשתמש שמוגדר כברירת מחדל"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"מקלדת פיזית"</string>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index ad84d9e..d73cc43 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"システムの選択(デフォルト)を使用"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> オーディオ"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> オーディオ"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"システムの選択(デフォルト)を使用"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> オーディオ"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> オーディオ"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"システムの選択(デフォルト)を使用"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 2994e4d..e7d2cf8 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ファイル転送"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"入力デバイス"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"インターネットアクセス"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"連絡先と通話履歴の共有"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"連絡先と通話履歴の共有に使用します"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"インターネット接続の共有"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"テキスト メッセージ"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIMアクセス"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"天気"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"大気質"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"キャスト情報"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"プロフィール写真の選択"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"デフォルト ユーザー アイコン"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"物理キーボード"</string>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index 01f1dcc7..c0d6f97 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> აუდიო"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> აუდიო"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> აუდიო"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> აუდიო"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
<item msgid="8003118270854840095">"44,1 კჰც"</item>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 0c3277b..09f5471 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ფაილების გადაცემა"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"შეყვანის მოწყობილობა"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"ინტერნეტზე წვდომა"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"კონტაქტ. და საუბრის ისტორიის გაზიარება"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"გამოიყენეთ კონტაქტებისა და საუბრის ისტორიის გასაზიარებლად"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ინტერნეტ კავშირის გაზიარება"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"ტექსტური შეტყობინებები"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM წვდომა"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"ამინდი"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"ჰაერის ხარისხი"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ტრანსლირების ინფო"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"სახლის მართვა"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"აირჩიეთ პროფილის სურათი"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"მომხმარებლის ნაგულისხმევი ხატულა"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ფიზიკური კლავიატურა"</string>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index 33fd25b..fc998e7 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Жүйенің таңдағанын алу (әдепкі)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудиокодегі"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудиокодегі"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Жүйенің таңдағанын алу (әдепкі)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудиокодегі"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудиокодегі"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Жүйенің таңдағанын алу (әдепкі)"</item>
<item msgid="8003118270854840095">"44,1 кГц"</item>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 63c9575..3281303 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Файл жіберу"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Кіріс құрылғысы"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Интернетке қосылу"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Контактілер мен қоңыраулар тарихын бөлісу"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Контактілер мен қоңыраулар тарихын бөлісу үшін пайдалану"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Интернет байланысын ортақ қолдану"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Мәтіндік хабарлар"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM картасына кіру"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Ауа райы"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ауа сапасы"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Трансляция ақпараты"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Профиль суретін таңдау"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Әдепкі пайдаланушы белгішесі"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Пернетақта"</string>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index ef3aa52..a005f4d 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"ប្រើការជ្រើសរើសប្រព័ន្ធ (លំនាំដើម)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"ប្រើការជ្រើសរើសប្រព័ន្ធ (លំនាំដើម)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g>សំឡេង <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ប្រើការជ្រើសរើសប្រព័ន្ធ (លំនាំដើម)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 9b9228a..87c1aa2 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ផ្ទេរឯកសារ"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ឧបករណ៍បញ្ចូល"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"ការចូលប្រើអ៊ីនធឺណិត"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"ការចែករំលែកទំនាក់ទំនង និងប្រវត្តិហៅទូរសព្ទ"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"ការប្រើសម្រាប់ការចែករំលែកទំនាក់ទំនង និងប្រវត្តិហៅទូរសព្ទ"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ចែករំលែកការតភ្ជាប់អ៊ីនធឺណិត"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"សារជាអក្សរ"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"ការចូលដំណើរការស៊ីម"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"អាកាសធាតុ"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"គុណភាពខ្យល់"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ព័ត៌មានអំពីការបញ្ជូន"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"ជ្រើសរើសរូបភាពកម្រងព័ត៌មាន"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"រូបអ្នកប្រើប្រាស់លំនាំដើម"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ក្ដារចុចរូបវន្ត"</string>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index 6623564..b6014ce 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ಆಡಿಯೋ"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ಆಡಿಯೋ"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ಆಡಿಯೋ"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ಆಡಿಯೋ"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
@@ -184,7 +172,7 @@
<item msgid="7300881231043255746">"ಕೆರ್ನಲ್ ಮಾತ್ರ"</item>
</string-array>
<string-array name="select_logpersist_summaries">
- <item msgid="97587758561106269">"ಆಫ್ ಆಗಿದೆ"</item>
+ <item msgid="97587758561106269">"ಆಫ್"</item>
<item msgid="7126170197336963369">"ಎಲ್ಲಾ ಲಾಗ್ ಬಫರ್ಗಳು"</item>
<item msgid="7167543126036181392">"ಎಲ್ಲಾ ಆದರೆ ರೇಡಿಯೊ ಲಾಗ್ ಬಫರ್ಗಳು"</item>
<item msgid="5135340178556563979">"ಕೆರ್ನಲ್ ಲಾಗ್ ಬಫರ್ ಮಾತ್ರ"</item>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 7071598..ab437e8 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ಫೈಲ್ ವರ್ಗಾವಣೆ"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ಇನ್ಪುಟ್ ಸಾಧನ"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶ"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"ಸಂಪರ್ಕಗಳು ಹಾಗೂ ಕರೆ ಇತಿಹಾಸ ಹಂಚಿಕೊಳ್ಳುವಿಕೆ"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"ಸಂಪರ್ಕಗಳು ಮತ್ತು ಕರೆ ಇತಿಹಾಸ ಹಂಚಿಕೆಗಾಗಿ ಬಳಸಿ"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕ ಹಂಚಿಕೊಳ್ಳುವಿಕೆ"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"ಪಠ್ಯ ಸಂದೇಶಗಳು"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"ಸಿಮ್ ಪ್ರವೇಶ"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"ಹವಾಮಾನ"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"ವಾಯು ಗುಣಮಟ್ಟ"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ಬಿತ್ತರಿಸಿದ ಮಾಹಿತಿ"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"ಪ್ರೊಫೈಲ್ ಚಿತ್ರವನ್ನು ಆಯ್ಕೆ ಮಾಡಿ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ಡೀಫಾಲ್ಟ್ ಬಳಕೆದಾರರ ಐಕಾನ್"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ಭೌತಿಕ ಕೀಬೋರ್ಡ್"</string>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index a207706..7138113 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"시스템 설정 사용(기본)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 오디오"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 오디오"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"시스템 설정 사용(기본)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 오디오"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 오디오"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"시스템 설정 사용(기본)"</item>
<item msgid="8003118270854840095">"44.1kHz"</item>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 6ba289d..2b8ab75 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"파일 전송"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"입력 장치"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"인터넷 액세스"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"연락처 및 통화 기록 공유"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"연락처 및 통화 기록 공유에 사용"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"인터넷 연결 공유"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"문자 메시지"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM 액세스"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"날씨"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"대기 상태"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"전송 정보"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"프로필 사진 선택하기"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"기본 사용자 아이콘"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"물리적 키보드"</string>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index 67cdc7c..40271f7 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"карта13"</item>
<item msgid="8147982633566548515">"карта14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Система тандаганды колдонуу (демейки)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Система тандаганды колдонуу (демейки)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Система тандаганды колдонуу (демейки)"</item>
<item msgid="8003118270854840095">"44,1 кГц"</item>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 3eb43fa..e993e3f 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Файл алмашуу"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Киргизүү түзмөгү"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Интернетке мүмкүнчүлүк алуу"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Байланыштарды жана чалуу таржымалын бөлүшүү"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Байланыштарды жана чалуу таржымалын бөлүшүү үчүн колдонуу"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Интернет байланышын бөлүшүү"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS билдирүүлөрү"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM картаны пайдалануу мүмкүнчүлүгү"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Аба ырайы"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Абанын сапаты"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Тышкы экранга чыгаруу маалыматы"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Профилдин сүрөтүн тандоо"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Демейки колдонуучунун сүрөтчөсү"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Аппараттык баскычтоп"</string>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index 56a9741..792ca39 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"ໃຊ້ການເລືອກຂອງລະບົບ (ຄ່າເລີ່ມຕົ້ນ)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"ໃຊ້ການເລືອກຂອງລະບົບ (ຄ່າເລີ່ມຕົ້ນ)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"ສຽງ <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ໃຊ້ການເລືອກຂອງລະບົບ (ຄ່າເລີ່ມຕົ້ນ)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 2dcad1f..d295932 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ການໂອນຍ້າຍໄຟລ໌"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ອຸປະກອນປ້ອນຂໍ້ມູນ"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"ການເຂົ້າເຖິງອິນເຕີເນັດ"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"ແບ່ງປັນລາຍຊື່ຜູ້ຕິດຕໍ່ ແລະ ປະຫວັດການໂທ"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"ໃຊ້ສໍາລັບແບ່ງປັນລາຍຊື່ຜູ້ຕິດຕໍ່ ແລະ ປະຫວັດການໂທ"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ການແບ່ງປັນການເຊື່ອມຕໍ່ອິນເຕີເນັດ"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"ຂໍ້ຄວາມ"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"ການເຂົ້າເຖິງ SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"ສະພາບອາກາດ"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"ຄຸນນະພາບອາກາດ"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ຂໍ້ມູນການສົ່ງສັນຍານ"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"ເລືອກຮູບໂປຣໄຟລ໌"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ໄອຄອນຜູ້ໃຊ້ເລີ່ມຕົ້ນ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ແປ້ນພິມພາຍນອກ"</string>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index a7aba78..946f69c 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Naudoti sistemos pasirink. (numatytasis)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> garsas"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> garsas"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Naudoti sistemos pasirink. (numatytasis)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> garsas"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> garsas"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Naudoti sistemos pasirink. (numatytasis)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 8aaec47..e38889b 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Failo perkėlimas"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Įvesties įrenginys"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Prieiga prie interneto"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kontaktų ir skambučių istorijos bendrinimas"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Naudoti kontaktams ir skambučių istorijai bendrinti"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Interneto ryšio bendrinimas"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Teksto pranešimai"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM prieiga"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Orai"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Oro kokybė"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Perdav. informacija"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Namų sist. valdikl."</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Pasirinkite profilio nuotrauką"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Numatytojo naudotojo piktograma"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fizinė klaviatūra"</string>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 840d794..f4ae452 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Sistēmas atlases izmantošana (nokl.)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Sistēmas atlases izmantošana (nokl.)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Sistēmas atlases izmantošana (nokl.)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index fcfb9b89..d899ada 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Failu pārsūtīšana"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Ievades ierīce"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Interneta piekļuve"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kontaktpersonu un zvanu vēst. kopīgošana"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Paredzēts kontaktpersonu un zvanu vēstures kopīgošanai"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Interneta savienojuma koplietošana"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Īsziņas"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Piekļuve SIM kartei"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Laikapstākļi"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Gaisa kvalitāte"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Apraides informācija"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Profila attēla izvēle"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Noklusējuma lietotāja ikona"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fiziskā tastatūra"</string>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index 2f22165..9c46f21 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Користи избор на системот (стандардно)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Користи избор на системот (стандардно)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Користи избор на системот (стандардно)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 144de00..c8033e3 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Пренос на датотека"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Влезен уред"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Пристап до интернет"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Споделување контакти и историја на повици"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Користење на споделувањето контакти и историја на повици"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Споделување конекција на интернет"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Текстуални пораки"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Пристап до SIM"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Временска прогноза"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Квалитет на воздух"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Инфо за улогите"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Контроли за домот"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Изберете профилна слика"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Икона за стандарден корисник"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Физичка тастатура"</string>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index 3aa9472..4715e2a 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ഓഡിയോ"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ഓഡിയോ"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ഓഡിയോ"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ഓഡിയോ"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ (ഡിഫോൾട്ട്)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 59cd6bc..089f6af 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ഫയൽ കൈമാറൽ"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ഇൻപുട്ട് ഉപകരണം"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"ഇന്റർനെറ്റ് ആക്സസ്"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"കോൺടാക്റ്റുകളും കോൾ ചരിത്രം പങ്കിടലും"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"കോൺടാക്റ്റുകളുടെയും കോൾ ചരിത്രം പങ്കിടലിന്റെയും ഉപയോഗം"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ഇന്റർനെറ്റ് കണക്ഷൻ പങ്കിടൽ"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"അക്ഷര സന്ദേശങ്ങൾ"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"സിം ആക്സസ്"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"കാലാവസ്ഥ"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"വായു നിലവാരം"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"കാസ്റ്റ് വിവരങ്ങൾ"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ഹോം കൺട്രോളുകൾ"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"പ്രൊഫൈൽ ചിത്രം തിരഞ്ഞെടുക്കുക"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ഡിഫോൾട്ട് ഉപയോക്തൃ ഐക്കൺ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ഫിസിക്കൽ കീബോർഡ്"</string>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index 9bd10a78..63fa53b 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
<item msgid="8003118270854840095">"44.1 кГц"</item>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 1bd6bea..cc35053 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Файл дамжуулалт"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Оруулах төхөөрөмж"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Интернэт хандалт"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Харилцагчид ба дуудлагын түүх хуваалцах"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Харилцагчид ба дуудлагын түүх хуваалцахад ашиглах"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Интернэт холболтыг хуваалцах"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Мессеж"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM Хандалт"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Цаг агаар"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Агаарын чанар"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Дамжуулах мэдээлэл"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Гэрийн удирдлага"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Профайл зураг сонгох"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Өгөгдмөл хэрэглэгчийн дүрс тэмдэг"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Биет гар"</string>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index 45bc5b8..a54f990 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"सिस्टीम निवड वापरा (डीफॉल्ट)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडिओ"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडिओ"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"सिस्टम निवड वापरा (डीफॉल्ट)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडिओ"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ऑडिओ"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"सिस्टम निवड वापरा (डीफॉल्ट)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index c163219..1907d00 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"फाइल स्थानांतरण"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"इनपुट डिव्हाइस"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"इंटरनेट अॅक्सेस"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"संपर्क आणि कॉल इतिहास शेअरिंग"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"संपर्क आणि कॉल इतिहास शेअरिंगसाठी वापरा"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"इंटरनेट कनेक्शन शेअररण"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"मजकूर मेसेज"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"सिम अॅक्सेस"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"हवामान"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"हवेची गुणवत्ता"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"कास्टसंबंधित माहिती"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"होम कंट्रोल"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"प्रोफाइल फोटो निवडा"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"डीफॉल्ट वापरकर्ता आयकन"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"वास्तविक कीबोर्ड"</string>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index d88ea76..b26ed23 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Gunakan Pilihan Sistem (Lalai)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Gunakan Pilihan Sistem (Lalai)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Gunakan Pilihan Sistem (Lalai)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 55c8814..b3929c9 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Pemindahan fail"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Peranti input"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Akses Internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Perkongsian kenalan & sejarah panggilan"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Digunakan untuk perkongsian kenalan dan sejarah panggilan"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Perkongsian sambungan Internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Mesej Teks"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Akses SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Cuaca"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kualiti Udara"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Maklumat Pelakon"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Pilih gambar profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikon pengguna lalai"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Papan kekunci fizikal"</string>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index 857a6ae..ed95dfe 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> အသံ"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> အသံ"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> အသံ"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> အသံ"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
<item msgid="8003118270854840095">"၄၄.၁ kHz"</item>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 38b1fe8..f7a33a9 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ဖိုင်လွဲပြောင်းခြင်း"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ထည့်သွင်းသော စက်"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"အင်တာနက်ချိတ်ဆက်ခြင်း"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"အဆက်အသွယ်၊ ယခင်ခေါ်ဆိုမှုများ မျှဝေခြင်း"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"အဆက်အသွယ်နှင့် ယခင်ခေါ်ဆိုမှုများ မျှဝေရန် သုံးသည်"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"အင်တာနက်ဆက်သွယ်မှု မျှဝေခြင်း"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"မိုဘိုင်းမက်ဆေ့ဂျ်များ"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM အသုံးပြုခြင်း"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"မိုးလေဝသ"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"လေထုအရည်အသွေး"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ကာစ် အချက်အလက်"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"ပရိုဖိုင်ပုံ ရွေးပါ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"မူရင်းအသုံးပြုသူ သင်္ကေတ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ပကတိ ကီးဘုတ်"</string>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 0f6e1fc..317c2db 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Bruk systemvalg (standard)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Bruk systemvalg (standard)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-lyd"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-lyd"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Bruk systemvalg (standard)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index ef2111d..9b99631 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Filoverføring"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Inndataenhet"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internett-tilgang"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Deling av kontakter og anropslogg"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Bruk for deling av kontakter og anropslogg"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Deling av internettilkobling"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Tekstmeldinger"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Tilgang til SIM-kortet"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Vær"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luftkvalitet"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Castinformasjon"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Velg et profilbilde"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Standard brukerikon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fysisk tastatur"</string>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 611066e..b3c3ee2 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> अडियो"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> अडियो"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> अडियो"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> अडियो"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"सिस्टमको छनौट प्रयोग गरियोस् (डिफल्ट)"</item>
<item msgid="8003118270854840095">"४४.१ kHz"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 9fa7749..1534cba 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"फाइल स्थानान्तरण"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"इनपुट उपकरण"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"इन्टरनेट पहुँच"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"कन्ट्याक्ट र कलको इतिहास सेयर गर्ने"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"कन्ट्याक्ट र कलको इतिहास सेयर गर्न प्रयोग गरियोस्"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"इन्टरनेट जडान साझेदारी गर्दै"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"टेक्स्ट म्यासेजहरू"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM पहुँच"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"मौसम"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"वायुको गुणस्तर"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"कास्टसम्बन्धी जानकारी"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"प्रोफाइल फोटो छान्नुहोस्"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"प्रयोगकर्ताको डिफल्ट आइकन"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"भौतिक किबोर्ड"</string>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index e0690df..e809452 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Systeemselectie gebruiken (standaard)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Gebruik systeemselectie (standaard)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Systeemselectie gebruiken (standaard)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index f4cbfd5..ba11b46 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Bestandsoverdracht"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Invoerapparaat"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internettoegang"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacten en gespreksgeschiedenis delen"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Gebruiken om contacten en gespreksgeschiedenis te delen"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internetverbinding delen"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Sms-berichten"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Sim-toegang"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Weer"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luchtkwaliteit"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Castinformatie"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Bediening voor in huis"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Kies een profielfoto"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Standaard gebruikersicoon"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fysiek toetsenbord"</string>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index dd25b3e..d42aeaf 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"ସିଷ୍ଟମ୍ ଚୟନ ବ୍ୟବହାର କରନ୍ତୁ (ଡିଫଲ୍ଟ)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ଅଡିଓ"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ଅଡିଓ"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"ସିଷ୍ଟମ୍ର ଚୟନ (ଡିଫଲ୍ଟ୍) ବ୍ୟବହାର କରନ୍ତୁ"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ଅଡିଓ"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ଅଡିଓ"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ସିଷ୍ଟମ୍ର ଚୟନ (ଡିଫଲ୍ଟ୍) ବ୍ୟବହାର କରନ୍ତୁ"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 76c3671..09fa59d 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ଫାଇଲ୍ ଟ୍ରାନ୍ସଫର୍"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ଇନ୍ପୁଟ୍ ଡିଭାଇସ୍"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"କଣ୍ଟାକ୍ଟ ଏବଂ କଲ ଇତିହାସ ସେୟାରିଂ"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"କଣ୍ଟାକ୍ଟ ଏବଂ କଲ ଇତିହାସ ସେୟାରିଂ ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ଇଣ୍ଟର୍ନେଟ୍ ସଂଯୋଗ ଶେୟାରିଙ୍ଗ"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"ଟେକ୍ସଟ୍ ମେସେଜ୍"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM ଆକ୍ସେସ୍"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"ପାଣିପାଗ"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"ବାୟୁର ଗୁଣବତ୍ତା"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"କାଷ୍ଟ ସୂଚନା"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"ଏକ ପ୍ରୋଫାଇଲ ଛବି ବାଛନ୍ତୁ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ଡିଫଲ୍ଟ ଉପଯୋଗକର୍ତ୍ତା ଆଇକନ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ଫିଜିକାଲ କୀବୋର୍ଡ"</string>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index 6ba2145..a3fae22 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ਆਡੀਓ"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ਆਡੀਓ"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ਆਡੀਓ"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ਆਡੀਓ"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index e34ece8..9df0fef 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ਇਨਪੁੱਟ ਡੀਵਾਈਸ"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"ਸੰਪਰਕ ਅਤੇ ਕਾਲ ਇਤਿਹਾਸ ਸਾਂਝਾ ਕਰਨਾ"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"ਸੰਪਰਕ ਅਤੇ ਕਾਲ ਇਤਿਹਾਸ ਸਾਂਝਾ ਕਰਨ ਲਈ ਵਰਤੋਂ ਕਰੋ"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ਇੰਟਰਨੈੱਟ ਕਨੈਕਸ਼ਨ ਸਾਂਝਾਕਰਨ"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"ਲਿਖਤ ਸੁਨੇਹੇ"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"ਸਿਮ ਪਹੁੰਚ"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"ਮੌਸਮ"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"ਹਵਾ ਦੀ ਕੁਆਲਿਟੀ"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ਕਾਸਟ ਸੰਬੰਧੀ ਜਾਣਕਾਰੀ"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"ਕੋਈ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਚੁਣੋ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਵਰਤੋਂਕਾਰ ਪ੍ਰਤੀਕ"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"ਭੌਤਿਕ ਕੀ-ਬੋਰਡ"</string>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index 5f91d35..f0453d1 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Używaj wyboru systemu (domyślnie)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Używaj wyboru systemu (domyślnie)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Używaj wyboru systemu (domyślnie)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index fe56c61..f4599fd 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Przesyłanie pliku"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Urządzenie wejściowe"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Dostęp do internetu"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Udostępnianie kontaktów i historii połączeń"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Używaj w przypadku udostępniania kontaktów i historii połączeń"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Udostępnianie połączenia internetowego"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS-y"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Dostęp do karty SIM"</string>
@@ -228,7 +226,7 @@
<string name="category_personal" msgid="6236798763159385225">"Osobiste"</string>
<string name="category_work" msgid="4014193632325996115">"Służbowe"</string>
<string name="development_settings_title" msgid="140296922921597393">"Opcje programisty"</string>
- <string name="development_settings_enable" msgid="4285094651288242183">"Włącz opcje dla programistów"</string>
+ <string name="development_settings_enable" msgid="4285094651288242183">"Włącz opcje programisty"</string>
<string name="development_settings_summary" msgid="8718917813868735095">"Ustaw opcje związane z programowaniem aplikacji."</string>
<string name="development_settings_not_available" msgid="355070198089140951">"Opcje programisty są niedostępne dla tego użytkownika"</string>
<string name="vpn_settings_not_available" msgid="2894137119965668920">"Ustawienia VPN są niedostępne dla tego użytkownika"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Pogoda"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Jakość powietrza"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Obsada"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Wybierz zdjęcie profilowe"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikona domyślnego użytkownika"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Klawiatura fizyczna"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index c5a847f..1883ef3 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Usar seleção do sistema (padrão)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Usar seleção do sistema (padrão)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Usar seleção do sistema (padrão)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index aa66c6043..12507c5 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferência de arquivo"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acesso à Internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Compartilhar contatos e histórico de chamadas"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use para compartilhar contatos e o histórico de chamadas"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Compartilhamento de conexão à Internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensagens de texto"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acesso ao chip"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Clima"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualidade do ar"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de transmissão"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Escolher a foto do perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ícone de usuário padrão"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index 3e7ee05..985bd51 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Utilizar seleção do sistema (predefinido)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Utilizar seleção do sistema (predefinido)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Utilizar seleção do sistema (predefinido)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index cf76780..4988136 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferência do ficheiro"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acesso à internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Part. histórico de chamadas e contactos"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Usar para partilha do histórico de chamadas e dos contactos"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Partilha da ligação à internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensagens de texto"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acesso ao SIM"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Meteorologia"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualidade do ar"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de transmissão"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Ctr. domésticos"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Escolha uma imagem do perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ícone do utilizador predefinido"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index c5a847f..1883ef3 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Usar seleção do sistema (padrão)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Usar seleção do sistema (padrão)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Áudio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Usar seleção do sistema (padrão)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index aa66c6043..12507c5 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferência de arquivo"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispositivo de entrada"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acesso à Internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Compartilhar contatos e histórico de chamadas"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use para compartilhar contatos e o histórico de chamadas"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Compartilhamento de conexão à Internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Mensagens de texto"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acesso ao chip"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Clima"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Qualidade do ar"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info. de transmissão"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Escolher a foto do perfil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ícone de usuário padrão"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Teclado físico"</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 454867e..f1e9986 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Folosiți selectarea sistemului (prestabilit)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Folosiți selectarea sistemului (prestabilit)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Audio <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Folosiți selectarea sistemului (prestabilit)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 946f4b7..f49fcdd 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transfer de fișiere"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Dispozitiv de intrare"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Acces la internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Acces la agendă și istoricul apelurilor"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Folosiți pentru accesul la agendă și istoricul apelurilor"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Distribuirea conexiunii la internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Mesaje text"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Acces la SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Meteo"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Calitatea aerului"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Informații artiști"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Alegeți o fotografie de profil"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Pictograma prestabilită a utilizatorului"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Tastatură fizică"</string>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 28b4695..b1211a5 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Выбор системы (по умолчанию)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Выбор системы (по умолчанию)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Аудиокодек: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Выбор системы (по умолчанию)"</item>
<item msgid="8003118270854840095">"44,1 кГц"</item>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index bcd83cf..38930a5 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Профиль OPP"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Профиль HID"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Доступ к интернету"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Доступ к контактам и журналу звонков"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Использовать для доступа к контактам и журналу звонков"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Профиль PAN"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Текстовые сообщения"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Доступ к SIM-карте"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Погода"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Качество воздуха"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Данные о трансляции"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Выберите фото профиля"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Значок пользователя по умолчанию"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Физическая клавиатура"</string>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index c2dbf60..8386c1a 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ශ්රව්යය"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ශ්රව්යය"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ශ්රව්යය"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ශ්රව්යය"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 7f5eb49..fa0296f 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ගොනු හුවමාරුව"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ආදාන උපාංගය"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"අන්තර්ජාල ප්රවේශය"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"සම්බන්ධතා සහ ඇමතුම් ඉතිහාසය බෙදා ගැනීම"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"සම්බන්ධතා සහ ඇමතුම් ඉතිහාසය බෙදා ගැනීම සඳහා භාවිතා කරන්න"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"අන්තර්ජාල සම්බන්ධතා බෙදාගැනීම"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"පෙළ පණිවිඩ"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM ප්රවේශය"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"කාලගුණය"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"වායු ගුණත්වය"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"විකාශ තතු"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"පැතිකඩ පින්තූරයක් තේරීම"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"පෙරනිමි පරිශීලක නිරූපකය"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"භෞතික යතුරු පුවරුව"</string>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index b285888..370b23f 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Použiť voľbu systému (predvolené)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Použiť voľbu systému (predvolené)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Zvuk: <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Použiť voľbu systému (predvolené)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 31925ea..a7c69c8 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos súborov"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Vstupné zariadenie"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Prístup na internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Zdieľanie kontaktov a histórie hovorov"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Používané pri zdieľaní kontaktov a histórie hovorov"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Zdieľanie pripojenia na Internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Textové správy"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Prístup k SIM karte"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Počasie"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kvalita vzduchu"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Informácie o prenose"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Ovládanie domácnosti"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Výber profilovej fotky"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Predvolená ikona používateľa"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fyzická klávesnica"</string>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index 8db3e99..6e33e38 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Uporabi sistemsko izbiro (privzeto)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Uporabi sistemsko izbiro (privzeto)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Zvok <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Uporabi sistemsko izbiro (privzeto)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 687ff38..7334cea 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Prenos datoteke"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Vnosna naprava"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetni dostop"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Deljenje stikov in zgodovine klicev"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Uporabite za deljenje stikov in zgodovine klicev."</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Deljenje internetne povezave"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Sporočila SMS"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Dostop do kartice SIM"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Vreme"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kakovost zraka"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"O zasedbi"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"Nadzor doma"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"Izbira profilne slike"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Privzeta ikona uporabnika"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fizična tipkovnica"</string>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index a82f716..8a6d853 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Audioja e <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 7e96990..59359cdf 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Transferimi i skedarëve"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Pajisja e hyrjes"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Qasje në internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Ndarje: kontakte e historik telefonatash"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Përdor për ndarje kontaktesh e të historikut të telefonatave"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Ndarja e lidhjes së internetit"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Mesazhet me tekst"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Qasje në kartën SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Moti"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Cilësia e ajrit"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Të dhënat e aktorëve"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Zgjidh një fotografi profili"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikona e parazgjedhur e përdoruesit"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Tastiera fizike"</string>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index 4cd83606..7e198bf 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Користи избор система (подразумевано)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Користи избор система (подразумевано)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> аудио"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> аудио"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Користи избор система (подразумевано)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 2842223..eee3f89 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Пренос датотеке"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Улазни уређај"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Приступ Интернету"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Дељење контаката и историје позива"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Користите за дељење контаката и историје позива"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Дељење интернет везе"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS-ови"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Приступ SIM картици"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Време"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Квалитет ваздуха"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Подаци о пребацивању"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Одаберите слику профила"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Подразумевана икона корисника"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Физичка тастатура"</string>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index 1432ec2..f99a85b 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Använd systemval (standardinställning)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-ljud"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-ljud"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Använd systemval (standardinställning)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>-ljud"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>-ljud"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Använd systemval (standardinställning)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index b0f8df5..1a8815c 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Filöverföring"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Indataenhet"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetåtkomst"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Delning av kontakter och samtalshistorik"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Använd för delning av kontakter och samtalshistorik"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Delning av Internetanslutning"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Sms"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM-åtkomst"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Väder"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Luftkvalitet"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Info om rollistan"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Välj en profilbild"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Ikon för standardanvändare"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fysiskt tangentbord"</string>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index cb74761..dab4279 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"ramani ya 13"</item>
<item msgid="8147982633566548515">"ramani ya 14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Tumia Uteuzi wa Mfumo (Chaguomsingi)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Tumia Uteuzi wa Mfumo (Chaguomsingi)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Sauti ya <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Tumia Uteuzi wa Mfumo (Chaguomsingi)"</item>
<item msgid="8003118270854840095">"kHz 44.1"</item>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 7e62d3f..5f1d141 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Uhamishaji wa faili"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Kifaa cha kuingiza"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Ufikiaji wa intaneti"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kushiriki anwani na rekodi ya simu zilizopigwa"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Tumia kushiriki anwani na rekodi ya simu zilizopigwa"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Kushiriki muunganisho wa tovuti"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Ufikiaji wa SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Hali ya Hewa"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ubora wa Hewa"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Maelezo ya Wahusika"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Chagua picha ya wasifu"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Aikoni chaguomsingi ya mtumiaji"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Kibodi halisi"</string>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 1f5380f..a0f1fa6 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ஆடியோ"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ஆடியோ"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ஆடியோ"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ஆடியோ"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index abab3fb..b8c37b0 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ஃபைல் இடமாற்றம்"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"உள்ளீட்டுச் சாதனம்"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"இணைய அணுகல்"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"தொடர்புகள் & அழைப்புப் பதிவைப் பகிர்தல்"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"தொடர்புகளையும் அழைப்புப் பதிவையும் பகிர்வதற்குப் பயன்படுத்து"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"இணைய இணைப்பு பகிர்தல்"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"உரைச் செய்திகள்"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"சிம் அணுகல்"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"வானிலை"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"காற்றின் தரம்"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"அலைபரப்புத் தகவல்"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"சுயவிவரப் படத்தைத் தேர்வுசெய்யுங்கள்"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"இயல்புநிலைப் பயனர் ஐகான்"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"கீபோர்டு"</string>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index 513fb6e..18a2758 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"సిస్టమ్ ఎంపికను ఉపయోగించండి (ఆటోమేటిక్)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ఆడియో"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ఆడియో"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"సిస్టమ్ ఎంపికను ఉపయోగించండి (ఆటోమేటిక్)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ఆడియో"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ఆడియో"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"సిస్టమ్ ఎంపికను ఉపయోగించండి (ఆటోమేటిక్)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index a362f24..504c827 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"ఫైల్ బదిలీ"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ఇన్పుట్ పరికరం"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"ఇంటర్నెట్ యాక్సెస్"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacts and call history sharing"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Use for contacts and call history sharing"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ఇంటర్నెట్ కనెక్షన్ షేరింగ్"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"టెక్స్ట్ మెసేజ్లు"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM యాక్సెస్"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"వాతావరణం"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"గాలి క్వాలిటీ"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"కాస్ట్ సమాచారం"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"హోమ్ కంట్రోల్స్"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"ప్రొఫైల్ ఫోటోను ఎంచుకోండి"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ఆటోమేటిక్ సెట్టింగ్ యూజర్ చిహ్నం"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"భౌతిక కీబోర్డ్"</string>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index 732124a..04a5f4d 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"ใช้การเลือกของระบบ (ค่าเริ่มต้น)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"ใช้การเลือกของระบบ (ค่าเริ่มต้น)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"เสียง <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"ใช้การเลือกของระบบ (ค่าเริ่มต้น)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index a4e0508..f33630d 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"การถ่ายโอนไฟล์"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"อุปกรณ์อินพุต"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"การเข้าถึงอินเทอร์เน็ต"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"การแชร์รายชื่อติดต่อและประวัติการโทร"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"ใช้สำหรับการแชร์รายชื่อติดต่อและประวัติการโทร"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"การแชร์การเชื่อมต่ออินเทอร์เน็ต"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"ข้อความ"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"การเข้าถึงซิม"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"สภาพอากาศ"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"คุณภาพอากาศ"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"ข้อมูลแคสต์"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"เลือกรูปโปรไฟล์"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ไอคอนผู้ใช้เริ่มต้น"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"แป้นพิมพ์จริง"</string>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index bdd8706..59cb1f3 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Gamitin ang Pagpili ng System (Default)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> na audio"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> na audio"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Gamitin ang Pagpili ng System (Default)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> na audio"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> na audio"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Gamitin ang Pagpili ng System (Default)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index e28fd96..f95f0e50 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Paglilipat ng file"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Device sa pag-input"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Access sa internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Contacts at pagbabahagi ng call history"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Gamitin para sa contacts at pagbabahagi ng call history"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Pagbabahagi ng koneksyon sa internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Mga Text Message"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Access sa SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Lagay ng Panahon"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Kalidad ng Hangin"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Impormasyon ng Cast"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Pumili ng larawan sa profile"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Icon ng default na user"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Pisikal na keyboard"</string>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index 0d0c69a..5ed35fa 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Sistem Seçimini Kullan (Varsayılan)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ses"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ses"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Sistem Seçimini Kullan (Varsayılan)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ses"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> ses"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Sistem Seçimini Kullan (Varsayılan)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 05ec1cc..2fa2bd1 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Dosya aktarımı"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Giriş cihazı"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"İnternet erişimi"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kişi ve çağrı geçmişi paylaşımı"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Kişi ve çağrı geçmişi paylaşımı için kullanın"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"İnternet bağlantısı paylaşımı"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Kısa Mesajlar"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM Erişimi"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Hava durumu"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Hava Kalitesi"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Yayın Bilgisi"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Profil fotoğrafı seçin"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Varsayılan kullanıcı simgesi"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Fiziksel klavye"</string>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index 49a4635..0410bd6 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Використовувати вибір системи (за умовчанням)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Використовувати вибір системи (за умовчанням)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Аудіо <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Використовувати вибір системи (за умовчанням)"</item>
<item msgid="8003118270854840095">"44,1 кГц"</item>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 184d0c1..9be0855 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Передавання файлів"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Пристрій введення"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Доступ до Інтернету"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Надсилання контактів та історії викликів"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Використовуйте, щоб надсилати контакти й історію викликів"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Надання доступу до Інтернету"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Текстові повідомлення"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Доступ до SIM-карти"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Погода"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Якість повітря"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Акторський склад"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Виберіть зображення профілю"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Значок користувача за умовчанням"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Фізична клавіатура"</string>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index 5dc2123..d097458 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> آڈیو"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> آڈیو"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> آڈیو"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> آڈیو"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 419833a..8eb9a11 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"فائل کی منتقلی"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"ان پٹ آلہ"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"انٹرنیٹ تک رسائی"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"رابطے اور کال کی سرگزشت کا اشتراک"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"رابطے اور کال کی سرگزشت کے اشتراک کے لیے استعمال کریں"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"انٹرنیٹ کنکشن کا اشتراک کرنا"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"ٹیکسٹ پیغامات"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM رسائی"</string>
@@ -662,6 +660,7 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"موسم"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"ہوا کا معیار"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"کاسٹ کرنے کی معلومات"</string>
+ <string name="dream_complication_title_home_controls" msgid="9153381632476738811">"ہوم کنٹرولز"</string>
<string name="avatar_picker_title" msgid="8492884172713170652">"پروفائل کی تصویر منتخب کریں"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"ڈیفالٹ صارف کا آئیکن"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"فزیکل کی بورڈ"</string>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index 589c592..7d09027 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Tizim tanlovi (birlamchi)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audiokodeki"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audiokodeki"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Tizim tanlovi (birlamchi)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> audiokodeki"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> audiokodeki"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Tizim tanlovi (birlamchi)"</item>
<item msgid="8003118270854840095">"44.1 kGs"</item>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index b1e22af..a5c8683 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Fayl uzatish"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Kiritish qurilmasi"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Internetga ulanish"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Kontakt va chaqiruvlar tarixiga kirish"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Kontaktlar va chaqiruvlar tarixiga kirish uchun foydalaning"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Internet aloqasi ulashmasi"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"SMS xabarlari"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM kartaga kirish"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Ob-havo"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Havo sifati"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Translatsiya axboroti"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Profil rasmini tanlash"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Foydalanuvchining standart belgisi"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Tashqi klaviatura"</string>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index 4cf8ff4..31867e2 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Sử dụng lựa chọn của hệ thống (Mặc định)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="2908219194098827570">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Sử dụng lựa chọn của hệ thống (Mặc định)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g>"</item>
- <item msgid="3517061573669307965">"Âm thanh <xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g>"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Sử dụng lựa chọn của hệ thống (Mặc định)"</item>
<item msgid="8003118270854840095">"44,1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 71bb08e..45a0465 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Chuyển tệp"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Thiết bị đầu vào"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Truy cập Internet"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Chia sẻ danh bạ và nhật ký cuộc gọi"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Dùng để chia sẻ danh bạ và nhật ký cuộc gọi"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Chia sẻ kết nối internet"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Tin nhắn văn bản"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Truy cập SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Thời tiết"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Chất lượng không khí"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Thông tin về dàn nghệ sĩ"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Chọn một ảnh hồ sơ"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Biểu tượng người dùng mặc định"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Bàn phím thực"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index af87f6f..973d7d0 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"使用系统选择(默认)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音频"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音频"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"使用系统选择(默认)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音频"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音频"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"使用系统选择(默认)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index f9e087b..2bc8a30 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"文件传输"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"输入设备"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"互联网连接"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"联系人信息和通话记录分享"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"用于联系人信息和通话记录分享"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"共享互联网连接"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"短信"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM 卡存取权限"</string>
@@ -661,7 +659,9 @@
<string name="dream_complication_title_date" msgid="8661176085446135789">"日期"</string>
<string name="dream_complication_title_weather" msgid="598609151677172783">"天气"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"空气质量"</string>
- <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"投射信息"</string>
+ <string name="dream_complication_title_cast_info" msgid="4038776652841885084">"投放信息"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"选择个人资料照片"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"默认用户图标"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"实体键盘"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index 2099410..87f3825 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"使用系統選擇 (預設)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"使用系統選擇 (預設)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"使用系統選擇 (預設)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index cd93f71..114bc64 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"檔案傳輸"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"輸入裝置"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"互聯網連線"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"分享通訊錄及通話記錄"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"用於分享通訊錄及通話記錄"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"互聯網連線分享"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"短訊"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM 卡存取"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"天氣"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"空氣質素"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"投放資料"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"選擇個人檔案相片"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"預設使用者圖示"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"實體鍵盤"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index 24991e3..529287f 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"map13"</item>
<item msgid="8147982633566548515">"map14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"系統自動選擇 (預設)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item>
- <item msgid="3825367753087348007">"LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"系統自動選擇 (預設)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> 音訊"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> 音訊"</item>
- <item msgid="2553206901068987657">"LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"系統自動選擇 (預設)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 4f36742..a7ae213 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"檔案傳輸"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"輸入裝置"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"網際網路連線"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"分享聯絡人和通話記錄"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"用於分享聯絡人和通話記錄"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"網際網路連線分享"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"簡訊"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM 卡存取權"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"天氣"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"空氣品質"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"演出者資訊"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"選擇個人資料相片"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"預設使用者圖示"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"實體鍵盤"</string>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index 8732b26..59ead86 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -85,22 +85,10 @@
<item msgid="7073042887003102964">"Imephu13"</item>
<item msgid="8147982633566548515">"Imephu14"</item>
</string-array>
- <string-array name="bluetooth_a2dp_codec_titles">
- <item msgid="2494959071796102843">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
- <item msgid="4055460186095649420">"SBC"</item>
- <item msgid="720249083677397051">"I-AAC"</item>
- <item msgid="1049450003868150455">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> umsindo"</item>
- <item msgid="2908219194098827570">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> umsindo"</item>
- <item msgid="3825367753087348007">"I-LDAC"</item>
- </string-array>
- <string-array name="bluetooth_a2dp_codec_summaries">
- <item msgid="8868109554557331312">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
- <item msgid="9024885861221697796">"SBC"</item>
- <item msgid="4688890470703790013">"I-AAC"</item>
- <item msgid="8627333814413492563">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> umsindo"</item>
- <item msgid="3517061573669307965">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX_HD">aptX™ HD</xliff:g> umsindo"</item>
- <item msgid="2553206901068987657">"I-LDAC"</item>
- </string-array>
+ <!-- no translation found for bluetooth_a2dp_codec_titles:6 (328951785723550863) -->
+ <!-- no translation found for bluetooth_a2dp_codec_titles:7 (506175145534048710) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:6 (3940992993241040716) -->
+ <!-- no translation found for bluetooth_a2dp_codec_summaries:7 (7940970833006181407) -->
<string-array name="bluetooth_a2dp_codec_sample_rate_titles">
<item msgid="926809261293414607">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
<item msgid="8003118270854840095">"44.1 kHz"</item>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 88c41c5..e037d12 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -117,10 +117,8 @@
<string name="bluetooth_profile_opp" msgid="6692618568149493430">"Dlulisa ifayela"</string>
<string name="bluetooth_profile_hid" msgid="2969922922664315866">"Idivaysi yokufakwayo"</string>
<string name="bluetooth_profile_pan" msgid="1006235139308318188">"Ukufinyelela i-Inthanethi"</string>
- <!-- no translation found for bluetooth_profile_pbap (4262303387989406171) -->
- <skip />
- <!-- no translation found for bluetooth_profile_pbap_summary (6466456791354759132) -->
- <skip />
+ <string name="bluetooth_profile_pbap" msgid="4262303387989406171">"Ukwabelana ngoxhumana nabo nomlando wekholi"</string>
+ <string name="bluetooth_profile_pbap_summary" msgid="6466456791354759132">"Ukusetshenziswa kokwabelana ngoxhumana nabo nomlando wekholi"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"Ukwabelana ngoxhumano lwe-Inthanethi"</string>
<string name="bluetooth_profile_map" msgid="8907204701162107271">"Imilayezo yombhalo"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"Ukufinyelela kwe-SIM"</string>
@@ -662,6 +660,8 @@
<string name="dream_complication_title_weather" msgid="598609151677172783">"Isimo sezulu"</string>
<string name="dream_complication_title_aqi" msgid="4587552608957834110">"Ikhwalithi Yomoya"</string>
<string name="dream_complication_title_cast_info" msgid="4038776652841885084">"Ulwazi Lokusakaza"</string>
+ <!-- no translation found for dream_complication_title_home_controls (9153381632476738811) -->
+ <skip />
<string name="avatar_picker_title" msgid="8492884172713170652">"Khetha isithombe sephrofayela"</string>
<string name="default_user_icon_description" msgid="6554047177298972638">"Isithonjana somsebenzisi sokuzenzakalelayo"</string>
<string name="physical_keyboard_title" msgid="4811935435315835220">"Ikhibhodi ephathekayo"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index a79cbb6..b879223 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1610,6 +1610,9 @@
<string name="dream_complication_title_cast_info">Cast Info</string>
<!-- Screensaver overlay which displays home controls. [CHAR LIMIT=20] -->
<string name="dream_complication_title_home_controls">Home Controls</string>
+ <!-- Screensaver overlay which displays smartspace. [CHAR LIMIT=20] -->
+ <string name="dream_complication_title_smartspace">Smartspace</string>
+
<!-- Title for a screen allowing the user to choose a profile picture. [CHAR LIMIT=NONE] -->
<string name="avatar_picker_title">Choose a profile picture</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index a46e232..2258617 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -92,7 +92,8 @@
COMPLICATION_TYPE_WEATHER,
COMPLICATION_TYPE_AIR_QUALITY,
COMPLICATION_TYPE_CAST_INFO,
- COMPLICATION_TYPE_HOME_CONTROLS
+ COMPLICATION_TYPE_HOME_CONTROLS,
+ COMPLICATION_TYPE_SMARTSPACE
})
@Retention(RetentionPolicy.SOURCE)
public @interface ComplicationType {}
@@ -103,6 +104,7 @@
public static final int COMPLICATION_TYPE_AIR_QUALITY = 4;
public static final int COMPLICATION_TYPE_CAST_INFO = 5;
public static final int COMPLICATION_TYPE_HOME_CONTROLS = 6;
+ public static final int COMPLICATION_TYPE_SMARTSPACE = 7;
private final Context mContext;
private final IDreamManager mDreamManager;
@@ -351,6 +353,9 @@
case COMPLICATION_TYPE_HOME_CONTROLS:
res = R.string.dream_complication_title_home_controls;
break;
+ case COMPLICATION_TYPE_SMARTSPACE:
+ res = R.string.dream_complication_title_smartspace;
+ break;
default:
return null;
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index 2f36ab9..8f9ced6 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -23,7 +23,6 @@
import android.graphics.Color
import android.graphics.Rect
import android.os.Looper
-import android.service.dreams.IDreamManager
import android.util.Log
import android.util.MathUtils
import android.view.GhostView
@@ -54,7 +53,7 @@
class DialogLaunchAnimator
@JvmOverloads
constructor(
- private val dreamManager: IDreamManager,
+ private val callback: Callback,
private val interactionJankMonitor: InteractionJankMonitor,
private val launchAnimator: LaunchAnimator = LaunchAnimator(TIMINGS, INTERPOLATORS),
private val isForTesting: Boolean = false
@@ -126,7 +125,7 @@
val animatedDialog =
AnimatedDialog(
launchAnimator,
- dreamManager,
+ callback,
interactionJankMonitor,
animateFrom,
onDialogDismissed = { openedDialogs.remove(it) },
@@ -194,8 +193,12 @@
val dialog = animatedDialog.dialog
- // Don't animate if the dialog is not showing.
- if (!dialog.isShowing) {
+ // Don't animate if the dialog is not showing or if we are locked and going to show the
+ // bouncer.
+ if (
+ !dialog.isShowing ||
+ (!callback.isUnlocked() && !callback.isShowingAlternateAuthOnUnlock())
+ ) {
return null
}
@@ -285,6 +288,23 @@
?.let { it.touchSurface = it.prepareForStackDismiss() }
dialog.dismiss()
}
+
+ interface Callback {
+ /** Whether the device is currently in dreaming (screensaver) mode. */
+ fun isDreaming(): Boolean
+
+ /**
+ * Whether the device is currently unlocked, i.e. if it is *not* on the keyguard or if the
+ * keyguard can be dismissed.
+ */
+ fun isUnlocked(): Boolean
+
+ /**
+ * Whether we are going to show alternate authentication (like UDFPS) instead of the
+ * traditional bouncer when unlocking the device.
+ */
+ fun isShowingAlternateAuthOnUnlock(): Boolean
+ }
}
/**
@@ -296,7 +316,7 @@
private class AnimatedDialog(
private val launchAnimator: LaunchAnimator,
- private val dreamManager: IDreamManager,
+ private val callback: DialogLaunchAnimator.Callback,
private val interactionJankMonitor: InteractionJankMonitor,
/** The view that triggered the dialog after being tapped. */
@@ -850,7 +870,7 @@
// If we are dreaming, the dialog was probably closed because of that so we don't animate
// into the touchSurface.
- if (dreamManager.isDreaming) {
+ if (callback.isDreaming()) {
return false
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
index a8a526a..f7049cf 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
@@ -48,9 +48,13 @@
val default: T
}
+/**
+ * Base class for most common boolean flags.
+ *
+ * See [UnreleasedFlag] and [ReleasedFlag] for useful implementations.
+ */
// Consider using the "parcelize" kotlin library.
-
-data class BooleanFlag @JvmOverloads constructor(
+abstract class BooleanFlag constructor(
override val id: Int,
override val default: Boolean = false,
override val teamfood: Boolean = false,
@@ -60,7 +64,7 @@
companion object {
@JvmField
val CREATOR = object : Parcelable.Creator<BooleanFlag> {
- override fun createFromParcel(parcel: Parcel) = BooleanFlag(parcel)
+ override fun createFromParcel(parcel: Parcel) = object : BooleanFlag(parcel) {}
override fun newArray(size: Int) = arrayOfNulls<BooleanFlag>(size)
}
}
@@ -80,12 +84,46 @@
}
}
+/**
+ * A Flag that is is false by default.
+ *
+ * It can be changed or overridden in debug builds but not in release builds.
+ */
+data class UnreleasedFlag @JvmOverloads constructor(
+ override val id: Int,
+ override val teamfood: Boolean = false,
+ override val overridden: Boolean = false
+) : BooleanFlag(id, false, teamfood, overridden)
+
+/**
+ * A Flag that is is true by default.
+ *
+ * It can be changed or overridden in any build, meaning it can be turned off if needed.
+ */
+data class ReleasedFlag @JvmOverloads constructor(
+ override val id: Int,
+ override val teamfood: Boolean = false,
+ override val overridden: Boolean = false
+) : BooleanFlag(id, true, teamfood, overridden)
+
+/**
+ * A Flag that reads its default values from a resource overlay instead of code.
+ *
+ * Prefer [UnreleasedFlag] and [ReleasedFlag].
+ */
data class ResourceBooleanFlag @JvmOverloads constructor(
override val id: Int,
@BoolRes override val resourceId: Int,
override val teamfood: Boolean = false
) : ResourceFlag<Boolean>
+/**
+ * A Flag that can reads its overrides from DeviceConfig.
+ *
+ * This is generally useful for flags that come from or are used _outside_ of SystemUI.
+ *
+ * Prefer [UnreleasedFlag] and [ReleasedFlag].
+ */
data class DeviceConfigBooleanFlag @JvmOverloads constructor(
override val id: Int,
override val name: String,
@@ -94,6 +132,13 @@
override val teamfood: Boolean = false
) : DeviceConfigFlag<Boolean>
+/**
+ * A Flag that can reads its overrides from System Properties.
+ *
+ * This is generally useful for flags that come from or are used _outside_ of SystemUI.
+ *
+ * Prefer [UnreleasedFlag] and [ReleasedFlag].
+ */
data class SysPropBooleanFlag @JvmOverloads constructor(
override val id: Int,
override val name: String,
diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
index 2560284..74bd9c6 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
@@ -27,7 +27,8 @@
import javax.inject.Named
@Module(includes = [
- SettingsUtilModule::class
+ ServerFlagReaderModule::class,
+ SettingsUtilModule::class,
])
abstract class FlagsModule {
@Binds
@@ -46,4 +47,4 @@
@Named(ALL_FLAGS)
fun providesAllFlags(): Map<Int, Flag<*>> = Flags.collectFlags()
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
index ab9e01e..38b5c9a 100644
--- a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
@@ -19,8 +19,8 @@
import dagger.Binds
import dagger.Module
-@Module
+@Module(includes = [ServerFlagReaderModule::class])
abstract class FlagsModule {
@Binds
abstract fun bindsFeatureFlagRelease(impl: FeatureFlagsRelease): FeatureFlags
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java b/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
index 23195af..00f1c01 100644
--- a/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
@@ -33,6 +33,7 @@
import android.view.ViewGroup;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.keyguard.dagger.KeyguardBouncerScope;
import com.android.systemui.dagger.qualifiers.Main;
@@ -208,7 +209,7 @@
hide();
if (mKeyguardCallback != null) {
mKeyguardCallback.dismiss(/* securityVerified= */ true, userId,
- /* bypassSecondaryLockScreen= */true);
+ /* bypassSecondaryLockScreen= */true, SecurityMode.Invalid);
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
index eb418ff..b8fcb10 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -179,7 +179,7 @@
if (dismissKeyguard) {
mDismissing = true;
mLatencyTracker.onActionStart(LatencyTracker.ACTION_LOCKSCREEN_UNLOCK);
- getKeyguardSecurityCallback().dismiss(true, userId);
+ getKeyguardSecurityCallback().dismiss(true, userId, getSecurityMode());
}
} else {
if (isValidPassword) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
index d32219a..db64f05 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
@@ -90,7 +90,7 @@
Log.i(TAG, "TrustAgent dismissed Keyguard.");
}
mSecurityCallback.dismiss(false /* authenticated */, userId,
- /* bypassSecondaryLockScreen */ false);
+ /* bypassSecondaryLockScreen */ false, SecurityMode.Invalid);
} else {
mViewMediatorCallback.playTrustedSound();
}
@@ -102,9 +102,9 @@
@Override
public boolean dismiss(boolean authenticated, int targetUserId,
- boolean bypassSecondaryLockScreen) {
+ boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
return mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
- authenticated, targetUserId, bypassSecondaryLockScreen);
+ authenticated, targetUserId, bypassSecondaryLockScreen, expectedSecurityMode);
}
@Override
@@ -212,7 +212,8 @@
* @return True if the keyguard is done.
*/
public boolean dismiss(int targetUserId) {
- return mSecurityCallback.dismiss(false, targetUserId, false);
+ return mSecurityCallback.dismiss(false, targetUserId, false,
+ getCurrentSecurityMode());
}
/**
@@ -360,10 +361,10 @@
}
public boolean handleBackKey() {
- if (mKeyguardSecurityContainerController.getCurrentSecurityMode()
- != SecurityMode.None) {
+ SecurityMode securityMode = mKeyguardSecurityContainerController.getCurrentSecurityMode();
+ if (securityMode != SecurityMode.None) {
mKeyguardSecurityContainerController.dismiss(
- false, KeyguardUpdateMonitor.getCurrentUser());
+ false, KeyguardUpdateMonitor.getCurrentUser(), securityMode);
return true;
}
return false;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index 98ac640..87300c3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -59,10 +59,11 @@
return false;
}
@Override
- public void dismiss(boolean securityVerified, int targetUserId) { }
+ public void dismiss(boolean securityVerified, int targetUserId,
+ SecurityMode expectedSecurityMode) { }
@Override
public void dismiss(boolean authenticated, int targetId,
- boolean bypassSecondaryLockScreen) { }
+ boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) { }
@Override
public void onUserInput() { }
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
index 58e0fb96..0ea1965 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
@@ -55,10 +55,11 @@
val faceAuthenticated: Boolean,
val faceDisabled: Boolean,
val goingToSleep: Boolean,
- val keyguardAwake: Boolean,
+ val keyguardAwakeExcludingBouncerShowing: Boolean,
val keyguardGoingAway: Boolean,
val listeningForFaceAssistant: Boolean,
val occludingAppRequestingFaceAuth: Boolean,
+ val onlyFaceEnrolled: Boolean,
val primaryUser: Boolean,
val scanningAllowedByStrongAuth: Boolean,
val secureCameraLaunched: Boolean,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index b97d9671..9aa6f03 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -171,7 +171,7 @@
if (dismissKeyguard) {
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
mLatencyTracker.onActionStart(LatencyTracker.ACTION_LOCKSCREEN_UNLOCK);
- getKeyguardSecurityCallback().dismiss(true, userId);
+ getKeyguardSecurityCallback().dismiss(true, userId, SecurityMode.Pattern);
}
} else {
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
index e384727..bc72f79 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
@@ -15,14 +15,17 @@
*/
package com.android.keyguard;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+
public interface KeyguardSecurityCallback {
/**
* Dismiss the given security screen.
* @param securityVerified true if the user correctly entered credentials for the given screen.
* @param targetUserId a user that needs to be the foreground user at the dismissal completion.
+ * @param expectedSecurityMode The security mode that is invoking this dismiss.
*/
- void dismiss(boolean securityVerified, int targetUserId);
+ void dismiss(boolean securityVerified, int targetUserId, SecurityMode expectedSecurityMode);
/**
* Dismiss the given security screen.
@@ -30,8 +33,10 @@
* @param targetUserId a user that needs to be the foreground user at the dismissal completion.
* @param bypassSecondaryLockScreen true if the user can bypass the secondary lock screen,
* if any, during this dismissal.
+ * @param expectedSecurityMode The security mode that is invoking this dismiss.
*/
- void dismiss(boolean securityVerified, int targetUserId, boolean bypassSecondaryLockScreen);
+ void dismiss(boolean securityVerified, int targetUserId, boolean bypassSecondaryLockScreen,
+ SecurityMode expectedSecurityMode);
/**
* Manually report user activity to keep the device awake.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 8fb622a..f697e25 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -236,7 +236,12 @@
// Used to notify the container when something interesting happens.
public interface SecurityCallback {
- boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen);
+ /**
+ * Potentially dismiss the current security screen, after validating that all device
+ * security has been unlocked. Otherwise show the next screen.
+ */
+ boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen,
+ SecurityMode expectedSecurityMode);
void userActivity();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 0b3fe46..e1957c0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -156,14 +156,17 @@
}
@Override
- public void dismiss(boolean authenticated, int targetId) {
- dismiss(authenticated, targetId, /* bypassSecondaryLockScreen */ false);
+ public void dismiss(boolean authenticated, int targetId,
+ SecurityMode expectedSecurityMode) {
+ dismiss(authenticated, targetId, /* bypassSecondaryLockScreen */ false,
+ expectedSecurityMode);
}
@Override
public void dismiss(boolean authenticated, int targetId,
- boolean bypassSecondaryLockScreen) {
- mSecurityCallback.dismiss(authenticated, targetId, bypassSecondaryLockScreen);
+ boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
+ mSecurityCallback.dismiss(authenticated, targetId, bypassSecondaryLockScreen,
+ expectedSecurityMode);
}
public boolean isVerifyUnlockOnly() {
@@ -385,8 +388,13 @@
return mCurrentSecurityMode;
}
- public void dismiss(boolean authenticated, int targetUserId) {
- mKeyguardSecurityCallback.dismiss(authenticated, targetUserId);
+ /**
+ * Potentially dismiss the current security screen, after validating that all device
+ * security has been unlocked. Otherwise show the next screen.
+ */
+ public void dismiss(boolean authenticated, int targetUserId,
+ SecurityMode expectedSecurityMode) {
+ mKeyguardSecurityCallback.dismiss(authenticated, targetUserId, expectedSecurityMode);
}
public void reset() {
@@ -456,12 +464,21 @@
* completion.
* @param bypassSecondaryLockScreen true if the user is allowed to bypass the secondary
* secondary lock screen requirement, if any.
+ * @param expectedSecurityMode SecurityMode that is invoking this request. SecurityMode.Invalid
+ * indicates that no check should be done
* @return true if keyguard is done
*/
public boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId,
- boolean bypassSecondaryLockScreen) {
+ boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
+ if (expectedSecurityMode != SecurityMode.Invalid
+ && expectedSecurityMode != getCurrentSecurityMode()) {
+ Log.w(TAG, "Attempted to invoke showNextSecurityScreenOrFinish with securityMode "
+ + expectedSecurityMode + ", but current mode is " + getCurrentSecurityMode());
+ return false;
+ }
+
boolean finish = false;
boolean strongAuth = false;
int eventSubtype = -1;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
index 2f6fa14..ecd88e6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
@@ -170,7 +170,8 @@
mRemainingAttempts = -1;
mShowDefaultMessage = true;
getKeyguardSecurityCallback().dismiss(
- true, KeyguardUpdateMonitor.getCurrentUser());
+ true, KeyguardUpdateMonitor.getCurrentUser(),
+ SecurityMode.SimPin);
} else {
mShowDefaultMessage = false;
if (result.getResult() == PinResult.PIN_RESULT_TYPE_INCORRECT) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
index 47aa43b..203f9b6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
@@ -69,7 +69,8 @@
if (simState == TelephonyManager.SIM_STATE_READY) {
mRemainingAttempts = -1;
mShowDefaultMessage = true;
- getKeyguardSecurityCallback().dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+ getKeyguardSecurityCallback().dismiss(true, KeyguardUpdateMonitor.getCurrentUser(),
+ SecurityMode.SimPuk);
} else {
resetState();
}
@@ -278,7 +279,8 @@
mShowDefaultMessage = true;
getKeyguardSecurityCallback().dismiss(
- true, KeyguardUpdateMonitor.getCurrentUser());
+ true, KeyguardUpdateMonitor.getCurrentUser(),
+ SecurityMode.SimPuk);
} else {
mShowDefaultMessage = false;
if (result.getResult() == PinResult.PIN_RESULT_TYPE_INCORRECT) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 489b4be..8b5e3c1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -213,7 +213,8 @@
* If no cancel signal has been received after this amount of time, set the biometric running
* state to stopped to allow Keyguard to retry authentication.
*/
- private static final int DEFAULT_CANCEL_SIGNAL_TIMEOUT = 3000;
+ @VisibleForTesting
+ protected static final int DEFAULT_CANCEL_SIGNAL_TIMEOUT = 3000;
private static final ComponentName FALLBACK_HOME_COMPONENT = new ComponentName(
"com.android.settings", "com.android.settings.FallbackHome");
@@ -316,10 +317,15 @@
private static final int HAL_ERROR_RETRY_TIMEOUT = 500; // ms
private static final int HAL_ERROR_RETRY_MAX = 20;
- private final Runnable mFpCancelNotReceived = this::onFingerprintCancelNotReceived;
+ @VisibleForTesting
+ protected final Runnable mFpCancelNotReceived = this::onFingerprintCancelNotReceived;
private final Runnable mFaceCancelNotReceived = this::onFaceCancelNotReceived;
+ @VisibleForTesting
+ protected Handler getHandler() {
+ return mHandler;
+ }
private final Handler mHandler;
private SparseBooleanArray mBiometricEnabledForUser = new SparseBooleanArray();
@@ -707,6 +713,11 @@
private void handleFingerprintAuthFailed() {
Assert.isMainThread();
+ if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
+ Log.d(TAG, "handleFingerprintAuthFailed()"
+ + " triggered while waiting for cancellation, removing watchdog");
+ mHandler.removeCallbacks(mFpCancelNotReceived);
+ }
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -737,6 +748,11 @@
private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiometric) {
Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated");
+ if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
+ Log.d(TAG, "handleFingerprintAuthenticated()"
+ + " triggered while waiting for cancellation, removing watchdog");
+ mHandler.removeCallbacks(mFpCancelNotReceived);
+ }
try {
final int userId;
try {
@@ -2458,8 +2474,11 @@
}
final boolean statusBarShadeLocked = mStatusBarState == StatusBarState.SHADE_LOCKED;
- final boolean awakeKeyguard = mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep
- && !statusBarShadeLocked;
+ // mKeyguardIsVisible is true even when the bouncer is shown, we don't want to run face auth
+ // on bouncer if both fp and fingerprint are enrolled.
+ final boolean awakeKeyguardExcludingBouncerShowing = mKeyguardIsVisible
+ && mDeviceInteractive && !mGoingToSleep
+ && !statusBarShadeLocked && !mBouncerFullyShown;
final int user = getCurrentUser();
final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user);
final boolean isLockDown =
@@ -2499,14 +2518,15 @@
final boolean faceDisabledForUser = isFaceDisabled(user);
final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user);
final boolean shouldListenForFaceAssistant = shouldListenForFaceAssistant();
+ final boolean onlyFaceEnrolled = isOnlyFaceEnrolled();
// Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
final boolean shouldListen =
- (mBouncerFullyShown && !mGoingToSleep
+ ((mBouncerFullyShown && !mGoingToSleep && onlyFaceEnrolled)
|| mAuthInterruptActive
|| mOccludingAppRequestingFace
- || awakeKeyguard
+ || awakeKeyguardExcludingBouncerShowing
|| shouldListenForFaceAssistant
|| mAuthController.isUdfpsFingerDown()
|| mUdfpsBouncerShowing)
@@ -2530,10 +2550,11 @@
faceAuthenticated,
faceDisabledForUser,
mGoingToSleep,
- awakeKeyguard,
+ awakeKeyguardExcludingBouncerShowing,
mKeyguardGoingAway,
shouldListenForFaceAssistant,
mOccludingAppRequestingFace,
+ onlyFaceEnrolled,
mIsPrimaryUser,
strongAuthAllowsScanning,
mSecureCameraLaunched,
@@ -2543,6 +2564,11 @@
return shouldListen;
}
+ private boolean isOnlyFaceEnrolled() {
+ return isFaceAuthEnabledForUser(getCurrentUser())
+ && !isUnlockWithFingerprintPossible(getCurrentUser());
+ }
+
private void maybeLogListenerModelData(KeyguardListenModel model) {
mLogger.logKeyguardListenerModel(model);
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
deleted file mode 100644
index 0db5bef..0000000
--- a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * Copyright (C) 2015 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.analytics;
-
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.widget.Toast;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.plugins.FalsingPlugin;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Tracks touch, sensor and phone events when the lockscreen is on. If the phone is unlocked
- * the data containing these events is saved to a file. This data is collected
- * to analyze how a human interaction looks like.
- *
- * A session starts when the screen is turned on.
- * A session ends when the screen is turned off or user unlocks the phone.
- */
-public class DataCollector implements SensorEventListener {
- private static final String TAG = "DataCollector";
- private static final String COLLECTOR_ENABLE = "data_collector_enable";
- private static final String COLLECT_BAD_TOUCHES = "data_collector_collect_bad_touches";
- private static final String ALLOW_REJECTED_TOUCH_REPORTS =
- "data_collector_allow_rejected_touch_reports";
- private static final String DISABLE_UNLOCKING_FOR_FALSING_COLLECTION =
- "data_collector_disable_unlocking";
-
- private static final long TIMEOUT_MILLIS = 11000; // 11 seconds.
- public static final boolean DEBUG = false;
-
- private final Handler mHandler = new Handler(Looper.getMainLooper());
- private final Context mContext;
-
- // Err on the side of caution, so logging is not started after a crash even tough the screen
- // is off.
- private SensorLoggerSession mCurrentSession = null;
-
- private boolean mEnableCollector = false;
- private boolean mCollectBadTouches = false;
- private boolean mCornerSwiping = false;
- private boolean mTrackingStarted = false;
- private boolean mAllowReportRejectedTouch = false;
- private boolean mDisableUnlocking = false;
-
- private static DataCollector sInstance = null;
-
- private FalsingPlugin mFalsingPlugin = null;
-
- protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- updateConfiguration();
- }
- };
-
- private final PluginListener mPluginListener = new PluginListener<FalsingPlugin>() {
- public void onPluginConnected(FalsingPlugin plugin, Context context) {
- mFalsingPlugin = plugin;
- }
-
- public void onPluginDisconnected(FalsingPlugin plugin) {
- mFalsingPlugin = null;
- }
- };
-
- private DataCollector(Context context) {
- mContext = context;
-
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(COLLECTOR_ENABLE), false,
- mSettingsObserver,
- UserHandle.USER_ALL);
-
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(COLLECT_BAD_TOUCHES), false,
- mSettingsObserver,
- UserHandle.USER_ALL);
-
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(ALLOW_REJECTED_TOUCH_REPORTS), false,
- mSettingsObserver,
- UserHandle.USER_ALL);
-
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(DISABLE_UNLOCKING_FOR_FALSING_COLLECTION), false,
- mSettingsObserver,
- UserHandle.USER_ALL);
-
- updateConfiguration();
-
- Dependency.get(PluginManager.class).addPluginListener(mPluginListener, FalsingPlugin.class);
- }
-
- public static DataCollector getInstance(Context context) {
- if (sInstance == null) {
- sInstance = new DataCollector(context);
- }
- return sInstance;
- }
-
- private void updateConfiguration() {
- mEnableCollector = Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
- mContext.getContentResolver(),
- COLLECTOR_ENABLE, 0);
- mCollectBadTouches = mEnableCollector && 0 != Settings.Secure.getInt(
- mContext.getContentResolver(),
- COLLECT_BAD_TOUCHES, 0);
- mAllowReportRejectedTouch = Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
- mContext.getContentResolver(),
- ALLOW_REJECTED_TOUCH_REPORTS, 0);
- mDisableUnlocking = mEnableCollector && Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
- mContext.getContentResolver(),
- DISABLE_UNLOCKING_FOR_FALSING_COLLECTION, 0);
- }
-
- private boolean sessionEntrypoint() {
- if (isEnabled() && mCurrentSession == null) {
- onSessionStart();
- return true;
- }
- return false;
- }
-
- private void sessionExitpoint(int result) {
- if (mCurrentSession != null) {
- onSessionEnd(result);
- }
- }
-
- private void onSessionStart() {
- mCornerSwiping = false;
- mTrackingStarted = false;
- mCurrentSession = new SensorLoggerSession(System.currentTimeMillis(), System.nanoTime());
- }
-
- private void onSessionEnd(int result) {
- SensorLoggerSession session = mCurrentSession;
- mCurrentSession = null;
-
- if (mEnableCollector || mDisableUnlocking) {
- session.end(System.currentTimeMillis(), result);
- queueSession(session);
- }
- }
-
- public Uri reportRejectedTouch() {
- if (mCurrentSession == null) {
- Toast.makeText(mContext, "Generating rejected touch report failed: session timed out.",
- Toast.LENGTH_LONG).show();
- return null;
- }
- SensorLoggerSession currentSession = mCurrentSession;
-
- currentSession.setType(Session.REJECTED_TOUCH_REPORT);
- currentSession.end(System.currentTimeMillis(), Session.SUCCESS);
- Session proto = currentSession.toProto();
-
- byte[] b = Session.toByteArray(proto);
- File dir = new File(mContext.getExternalCacheDir(), "rejected_touch_reports");
- dir.mkdir();
- File touch = new File(dir, "rejected_touch_report_" + System.currentTimeMillis());
-
- try {
- new FileOutputStream(touch).write(b);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
-
- return Uri.fromFile(touch);
- }
-
- private void queueSession(final SensorLoggerSession currentSession) {
- AsyncTask.execute(new Runnable() {
- @Override
- public void run() {
- byte[] b = Session.toByteArray(currentSession.toProto());
-
- if (mFalsingPlugin != null) {
- mFalsingPlugin.dataCollected(currentSession.getResult() == Session.SUCCESS, b);
- } else {
- String dir = mContext.getFilesDir().getAbsolutePath();
- if (currentSession.getResult() != Session.SUCCESS) {
- if (!mDisableUnlocking && !mCollectBadTouches) {
- return;
- }
- dir += "/bad_touches";
- } else if (!mDisableUnlocking) {
- dir += "/good_touches";
- }
-
- File file = new File(dir);
- file.mkdir();
- File touch = new File(file, "trace_" + System.currentTimeMillis());
- try {
- new FileOutputStream(touch).write(b);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }
- });
- }
-
- @Override
- public synchronized void onSensorChanged(SensorEvent event) {
- if (isEnabled() && mCurrentSession != null) {
- mCurrentSession.addSensorEvent(event, System.nanoTime());
- }
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- }
-
- /**
- * @return true if data is being collected - either for data gathering or creating a
- * rejected touch report.
- */
- public boolean isEnabled() {
- return mEnableCollector || mAllowReportRejectedTouch || mDisableUnlocking;
- }
-
- public boolean isUnlockingDisabled() {
- return mDisableUnlocking;
- }
- /**
- * @return true if the full data set for data gathering should be collected - including
- * extensive sensor data, which is is not normally included with rejected touch reports.
- */
- public boolean isEnabledFull() {
- return mEnableCollector;
- }
-
- public void onScreenTurningOn() {
- if (sessionEntrypoint()) {
- if (DEBUG) {
- Log.d(TAG, "onScreenTurningOn");
- }
- addEvent(PhoneEvent.ON_SCREEN_ON);
- }
- }
-
- public void onScreenOnFromTouch() {
- if (sessionEntrypoint()) {
- if (DEBUG) {
- Log.d(TAG, "onScreenOnFromTouch");
- }
- addEvent(PhoneEvent.ON_SCREEN_ON_FROM_TOUCH);
- }
- }
-
- public void onScreenOff() {
- if (DEBUG) {
- Log.d(TAG, "onScreenOff");
- }
- addEvent(PhoneEvent.ON_SCREEN_OFF);
- sessionExitpoint(Session.FAILURE);
- }
-
- public void onSucccessfulUnlock() {
- if (DEBUG) {
- Log.d(TAG, "onSuccessfulUnlock");
- }
- addEvent(PhoneEvent.ON_SUCCESSFUL_UNLOCK);
- sessionExitpoint(Session.SUCCESS);
- }
-
- public void onBouncerShown() {
- if (DEBUG) {
- Log.d(TAG, "onBouncerShown");
- }
- addEvent(PhoneEvent.ON_BOUNCER_SHOWN);
- }
-
- public void onBouncerHidden() {
- if (DEBUG) {
- Log.d(TAG, "onBouncerHidden");
- }
- addEvent(PhoneEvent.ON_BOUNCER_HIDDEN);
- }
-
- public void onQsDown() {
- if (DEBUG) {
- Log.d(TAG, "onQsDown");
- }
- addEvent(PhoneEvent.ON_QS_DOWN);
- }
-
- public void setQsExpanded(boolean expanded) {
- if (DEBUG) {
- Log.d(TAG, "setQsExpanded = " + expanded);
- }
- if (expanded) {
- addEvent(PhoneEvent.SET_QS_EXPANDED_TRUE);
- } else {
- addEvent(PhoneEvent.SET_QS_EXPANDED_FALSE);
- }
- }
-
- public void onTrackingStarted() {
- if (DEBUG) {
- Log.d(TAG, "onTrackingStarted");
- }
- mTrackingStarted = true;
- addEvent(PhoneEvent.ON_TRACKING_STARTED);
- }
-
- public void onTrackingStopped() {
- if (mTrackingStarted) {
- if (DEBUG) {
- Log.d(TAG, "onTrackingStopped");
- }
- mTrackingStarted = false;
- addEvent(PhoneEvent.ON_TRACKING_STOPPED);
- }
- }
-
- public void onNotificationActive() {
- if (DEBUG) {
- Log.d(TAG, "onNotificationActive");
- }
- addEvent(PhoneEvent.ON_NOTIFICATION_ACTIVE);
- }
-
-
- public void onNotificationDoubleTap() {
- if (DEBUG) {
- Log.d(TAG, "onNotificationDoubleTap");
- }
- addEvent(PhoneEvent.ON_NOTIFICATION_DOUBLE_TAP);
- }
-
- public void setNotificationExpanded() {
- if (DEBUG) {
- Log.d(TAG, "setNotificationExpanded");
- }
- addEvent(PhoneEvent.SET_NOTIFICATION_EXPANDED);
- }
-
- public void onNotificatonStartDraggingDown() {
- if (DEBUG) {
- Log.d(TAG, "onNotificationStartDraggingDown");
- }
- addEvent(PhoneEvent.ON_NOTIFICATION_START_DRAGGING_DOWN);
- }
-
- public void onStartExpandingFromPulse() {
- if (DEBUG) {
- Log.d(TAG, "onStartExpandingFromPulse");
- }
- // TODO: maybe add event
- }
-
- public void onExpansionFromPulseStopped() {
- if (DEBUG) {
- Log.d(TAG, "onExpansionFromPulseStopped");
- }
- // TODO: maybe add event
- }
-
- public void onNotificatonStopDraggingDown() {
- if (DEBUG) {
- Log.d(TAG, "onNotificationStopDraggingDown");
- }
- addEvent(PhoneEvent.ON_NOTIFICATION_STOP_DRAGGING_DOWN);
- }
-
- public void onNotificationDismissed() {
- if (DEBUG) {
- Log.d(TAG, "onNotificationDismissed");
- }
- addEvent(PhoneEvent.ON_NOTIFICATION_DISMISSED);
- }
-
- public void onNotificatonStartDismissing() {
- if (DEBUG) {
- Log.d(TAG, "onNotificationStartDismissing");
- }
- addEvent(PhoneEvent.ON_NOTIFICATION_START_DISMISSING);
- }
-
- public void onNotificatonStopDismissing() {
- if (DEBUG) {
- Log.d(TAG, "onNotificationStopDismissing");
- }
- addEvent(PhoneEvent.ON_NOTIFICATION_STOP_DISMISSING);
- }
-
- public void onCameraOn() {
- if (DEBUG) {
- Log.d(TAG, "onCameraOn");
- }
- addEvent(PhoneEvent.ON_CAMERA_ON);
- }
-
- public void onLeftAffordanceOn() {
- if (DEBUG) {
- Log.d(TAG, "onLeftAffordanceOn");
- }
- addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_ON);
- }
-
- public void onAffordanceSwipingStarted(boolean rightCorner) {
- if (DEBUG) {
- Log.d(TAG, "onAffordanceSwipingStarted");
- }
- mCornerSwiping = true;
- if (rightCorner) {
- addEvent(PhoneEvent.ON_RIGHT_AFFORDANCE_SWIPING_STARTED);
- } else {
- addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_SWIPING_STARTED);
- }
- }
-
- public void onAffordanceSwipingAborted() {
- if (mCornerSwiping) {
- if (DEBUG) {
- Log.d(TAG, "onAffordanceSwipingAborted");
- }
- mCornerSwiping = false;
- addEvent(PhoneEvent.ON_AFFORDANCE_SWIPING_ABORTED);
- }
- }
-
- public void onUnlockHintStarted() {
- if (DEBUG) {
- Log.d(TAG, "onUnlockHintStarted");
- }
- addEvent(PhoneEvent.ON_UNLOCK_HINT_STARTED);
- }
-
- public void onCameraHintStarted() {
- if (DEBUG) {
- Log.d(TAG, "onCameraHintStarted");
- }
- addEvent(PhoneEvent.ON_CAMERA_HINT_STARTED);
- }
-
- public void onLeftAffordanceHintStarted() {
- if (DEBUG) {
- Log.d(TAG, "onLeftAffordanceHintStarted");
- }
- addEvent(PhoneEvent.ON_LEFT_AFFORDANCE_HINT_STARTED);
- }
-
- public void onTouchEvent(MotionEvent event, int width, int height) {
- if (mCurrentSession != null) {
- if (DEBUG) {
- Log.v(TAG, "onTouchEvent(ev.action="
- + MotionEvent.actionToString(event.getAction()) + ")");
- }
- mCurrentSession.addMotionEvent(event);
- mCurrentSession.setTouchArea(width, height);
- }
- }
-
- private void addEvent(int eventType) {
- if (isEnabled() && mCurrentSession != null) {
- mCurrentSession.addPhoneEvent(eventType, System.nanoTime());
- }
- }
-
- public boolean isReportingEnabled() {
- return mAllowReportRejectedTouch;
- }
-
- public void onFalsingSessionStarted() {
- sessionEntrypoint();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
deleted file mode 100644
index d294012..0000000
--- a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2015 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.analytics;
-
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.SensorEvent;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.TouchEvent;
-
-import android.os.Build;
-import android.util.Log;
-import android.view.MotionEvent;
-
-import java.util.ArrayList;
-
-/**
- * Collects touch, sensor and phone events and converts the data to
- * TouchAnalyticsProto.Session.
- */
-public class SensorLoggerSession {
- private static final String TAG = "SensorLoggerSession";
-
- private final long mStartTimestampMillis;
- private final long mStartSystemTimeNanos;
-
- private long mEndTimestampMillis;
- private int mType;
-
- private ArrayList<TouchEvent> mMotionEvents = new ArrayList<>();
- private ArrayList<SensorEvent> mSensorEvents = new ArrayList<>();
- private ArrayList<PhoneEvent> mPhoneEvents = new ArrayList<>();
- private int mTouchAreaHeight;
- private int mTouchAreaWidth;
- private int mResult = Session.UNKNOWN;
-
- public SensorLoggerSession(long startTimestampMillis, long startSystemTimeNanos) {
- mStartTimestampMillis = startTimestampMillis;
- mStartSystemTimeNanos = startSystemTimeNanos;
- mType = Session.REAL;
- }
-
- public void setType(int type) {
- mType = type;
- }
-
- public void end(long endTimestampMillis, int result) {
- mResult = result;
- mEndTimestampMillis = endTimestampMillis;
-
- if (DataCollector.DEBUG) {
- Log.d(TAG, "Ending session result=" + result + " it lasted for " +
- (float) (mEndTimestampMillis - mStartTimestampMillis) / 1000f + "s");
- }
- }
-
- public void addMotionEvent(MotionEvent motionEvent) {
- TouchEvent event = motionEventToProto(motionEvent);
- mMotionEvents.add(event);
- }
-
- public void addSensorEvent(android.hardware.SensorEvent eventOrig, long systemTimeNanos) {
- SensorEvent event = sensorEventToProto(eventOrig, systemTimeNanos);
- mSensorEvents.add(event);
- }
-
- public void addPhoneEvent(int eventType, long systemTimeNanos) {
- PhoneEvent event = phoneEventToProto(eventType, systemTimeNanos);
- mPhoneEvents.add(event);
- }
-
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder("Session{");
- sb.append("mStartTimestampMillis=").append(mStartTimestampMillis);
- sb.append(", mStartSystemTimeNanos=").append(mStartSystemTimeNanos);
- sb.append(", mEndTimestampMillis=").append(mEndTimestampMillis);
- sb.append(", mResult=").append(mResult);
- sb.append(", mTouchAreaHeight=").append(mTouchAreaHeight);
- sb.append(", mTouchAreaWidth=").append(mTouchAreaWidth);
- sb.append(", mMotionEvents=[size=").append(mMotionEvents.size()).append("]");
- sb.append(", mSensorEvents=[size=").append(mSensorEvents.size()).append("]");
- sb.append(", mPhoneEvents=[size=").append(mPhoneEvents.size()).append("]");
- sb.append('}');
- return sb.toString();
- }
-
- public Session toProto() {
- Session proto = new Session();
- proto.startTimestampMillis = mStartTimestampMillis;
- proto.durationMillis = mEndTimestampMillis - mStartTimestampMillis;
- proto.build = Build.FINGERPRINT;
- proto.deviceId = Build.DEVICE;
- proto.result = mResult;
- proto.type = mType;
- proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents);
- proto.touchEvents = mMotionEvents.toArray(proto.touchEvents);
- proto.phoneEvents = mPhoneEvents.toArray(proto.phoneEvents);
- proto.touchAreaWidth = mTouchAreaWidth;
- proto.touchAreaHeight = mTouchAreaHeight;
- return proto;
- }
-
- private PhoneEvent phoneEventToProto(int eventType, long sysTimeNanos) {
- PhoneEvent proto = new PhoneEvent();
- proto.type = eventType;
- proto.timeOffsetNanos = sysTimeNanos - mStartSystemTimeNanos;
- return proto;
- }
-
- private SensorEvent sensorEventToProto(android.hardware.SensorEvent ev, long sysTimeNanos) {
- SensorEvent proto = new SensorEvent();
- proto.type = ev.sensor.getType();
- proto.timeOffsetNanos = sysTimeNanos - mStartSystemTimeNanos;
- proto.timestamp = ev.timestamp;
- proto.values = ev.values.clone();
- return proto;
- }
-
- private TouchEvent motionEventToProto(MotionEvent ev) {
- int count = ev.getPointerCount();
- TouchEvent proto = new TouchEvent();
- proto.timeOffsetNanos = ev.getEventTimeNano() - mStartSystemTimeNanos;
- proto.action = ev.getActionMasked();
- proto.actionIndex = ev.getActionIndex();
- proto.pointers = new TouchEvent.Pointer[count];
- for (int i = 0; i < count; i++) {
- TouchEvent.Pointer p = new TouchEvent.Pointer();
- p.x = ev.getX(i);
- p.y = ev.getY(i);
- p.size = ev.getSize(i);
- p.pressure = ev.getPressure(i);
- p.id = ev.getPointerId(i);
- proto.pointers[i] = p;
- }
- return proto;
- }
-
- public void setTouchArea(int width, int height) {
- mTouchAreaWidth = width;
- mTouchAreaHeight = height;
- }
-
- public int getResult() {
- return mResult;
- }
-
- public long getStartTimestampMillis() {
- return mStartTimestampMillis;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index e16ac08..c21e36a 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -97,6 +97,7 @@
import android.widget.LinearLayout;
import android.widget.TextView;
+import androidx.annotation.NonNull;
import androidx.core.view.ViewCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
@@ -132,7 +133,7 @@
private static final int FONT_SEARCH_STEP_PX = 4;
private final Context mContext;
- private final UiEventLogger mUiEventLogger;
+ private final ClipboardLogger mClipboardLogger;
private final BroadcastDispatcher mBroadcastDispatcher;
private final DisplayManager mDisplayManager;
private final DisplayMetrics mDisplayMetrics;
@@ -181,7 +182,7 @@
final Context displayContext = context.createDisplayContext(getDefaultDisplay());
mContext = displayContext.createWindowContext(TYPE_SCREENSHOT, null);
- mUiEventLogger = uiEventLogger;
+ mClipboardLogger = new ClipboardLogger(uiEventLogger);
mAccessibilityManager = AccessibilityManager.getInstance(mContext);
mTextClassifier = requireNonNull(context.getSystemService(TextClassificationManager.class))
@@ -231,7 +232,7 @@
@Override
public void onSwipeDismissInitiated(Animator animator) {
- mUiEventLogger.log(CLIPBOARD_OVERLAY_SWIPE_DISMISSED);
+ mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_SWIPE_DISMISSED);
mExitAnimator = animator;
}
@@ -249,7 +250,7 @@
});
mDismissButton.setOnClickListener(view -> {
- mUiEventLogger.log(CLIPBOARD_OVERLAY_DISMISS_TAPPED);
+ mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISS_TAPPED);
animateOut();
});
@@ -285,7 +286,8 @@
int newDisplayId) {
if (mContext.getResources().getConfiguration().orientation
!= mOrientation) {
- mUiEventLogger.log(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
+ mClipboardLogger.logSessionComplete(
+ CLIPBOARD_OVERLAY_DISMISSED_OTHER);
hideImmediate();
}
}
@@ -300,7 +302,7 @@
});
mTimeoutHandler.setOnTimeoutRunnable(() -> {
- mUiEventLogger.log(CLIPBOARD_OVERLAY_TIMED_OUT);
+ mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_TIMED_OUT);
animateOut();
});
@@ -308,7 +310,7 @@
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
- mUiEventLogger.log(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
+ mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
animateOut();
}
}
@@ -320,7 +322,7 @@
@Override
public void onReceive(Context context, Intent intent) {
if (SCREENSHOT_ACTION.equals(intent.getAction())) {
- mUiEventLogger.log(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
+ mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
animateOut();
}
}
@@ -390,7 +392,7 @@
mContext.getString(R.string.clipboard_send_nearby_description));
mRemoteCopyChip.setVisibility(View.VISIBLE);
mRemoteCopyChip.setOnClickListener((v) -> {
- mUiEventLogger.log(CLIPBOARD_OVERLAY_REMOTE_COPY_TAPPED);
+ mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_REMOTE_COPY_TAPPED);
mContext.startActivity(remoteCopyIntent);
animateOut();
});
@@ -450,7 +452,7 @@
chip.setContentDescription(action.getTitle());
chip.setIcon(action.getIcon(), false);
chip.setPendingIntent(action.getActionIntent(), () -> {
- mUiEventLogger.log(CLIPBOARD_OVERLAY_ACTION_TAPPED);
+ mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_ACTION_TAPPED);
animateOut();
});
chip.setAlpha(1);
@@ -486,7 +488,7 @@
touchRegion.op(tmpRect, Region.Op.UNION);
if (!touchRegion.contains(
(int) motionEvent.getRawX(), (int) motionEvent.getRawY())) {
- mUiEventLogger.log(CLIPBOARD_OVERLAY_TAP_OUTSIDE);
+ mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_TAP_OUTSIDE);
animateOut();
}
}
@@ -497,7 +499,7 @@
}
private void editImage(Uri uri) {
- mUiEventLogger.log(CLIPBOARD_OVERLAY_EDIT_TAPPED);
+ mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_EDIT_TAPPED);
String editorPackage = mContext.getString(R.string.config_screenshotEditor);
Intent editIntent = new Intent(Intent.ACTION_EDIT);
if (!TextUtils.isEmpty(editorPackage)) {
@@ -512,7 +514,7 @@
}
private void editText() {
- mUiEventLogger.log(CLIPBOARD_OVERLAY_EDIT_TAPPED);
+ mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_EDIT_TAPPED);
Intent editIntent = new Intent(mContext, EditTextActivity.class);
editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
mContext.startActivity(editIntent);
@@ -520,13 +522,15 @@
}
private void shareContent(ClipData clip) {
- mUiEventLogger.log(CLIPBOARD_OVERLAY_SHARE_TAPPED);
+ mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_SHARE_TAPPED);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
- shareIntent.putExtra(Intent.EXTRA_TEXT, clip.getItemAt(0).getText().toString());
shareIntent.setDataAndType(
clip.getItemAt(0).getUri(), clip.getDescription().getMimeType(0));
- shareIntent.putExtra(Intent.EXTRA_STREAM, clip.getItemAt(0).getUri());
- shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ shareIntent.putExtra(Intent.EXTRA_TEXT, clip.getItemAt(0).getText().toString());
+ if (clip.getItemAt(0).getUri() != null) {
+ shareIntent.putExtra(Intent.EXTRA_STREAM, clip.getItemAt(0).getUri());
+ shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ }
Intent chooserIntent = Intent.createChooser(shareIntent, null)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
@@ -864,6 +868,7 @@
mRemoteCopyChip.setVisibility(View.GONE);
resetActionChips();
mTimeoutHandler.cancelTimeout();
+ mClipboardLogger.reset();
}
@MainThread
@@ -969,4 +974,24 @@
mWindowManager.updateViewLayout(decorView, mWindowLayoutParams);
}
}
+
+ static class ClipboardLogger {
+ private final UiEventLogger mUiEventLogger;
+ private boolean mGuarded = false;
+
+ ClipboardLogger(UiEventLogger uiEventLogger) {
+ mUiEventLogger = uiEventLogger;
+ }
+
+ void logSessionComplete(@NonNull UiEventLogger.UiEventEnum event) {
+ if (!mGuarded) {
+ mGuarded = true;
+ mUiEventLogger.log(event);
+ }
+ }
+
+ void reset() {
+ mGuarded = false;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
index de7bf28..55c1806 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
@@ -215,16 +215,15 @@
final boolean cameraBlocked = mSensorPrivacyController
.isSensorBlocked(SensorPrivacyManager.Sensors.CAMERA);
@DreamOverlayStatusBarView.StatusIconType int iconType = Resources.ID_NULL;
- if (micBlocked && cameraBlocked) {
- iconType = DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED;
- } else if (!micBlocked && cameraBlocked) {
- iconType = DreamOverlayStatusBarView.STATUS_ICON_CAMERA_DISABLED;
- } else if (micBlocked && !cameraBlocked) {
- iconType = DreamOverlayStatusBarView.STATUS_ICON_MIC_DISABLED;
- }
- if (iconType != Resources.ID_NULL) {
- showIcon(iconType, true);
- }
+ showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_CAMERA_DISABLED,
+ !micBlocked && cameraBlocked);
+ showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_MIC_DISABLED,
+ micBlocked && !cameraBlocked);
+ showIcon(
+ DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED,
+ micBlocked && cameraBlocked);
}
private String buildNotificationsContentDescription(int notificationCount) {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
index 5457144..29bb2f4 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
@@ -163,7 +163,8 @@
COMPLICATION_TYPE_WEATHER,
COMPLICATION_TYPE_AIR_QUALITY,
COMPLICATION_TYPE_CAST_INFO,
- COMPLICATION_TYPE_HOME_CONTROLS
+ COMPLICATION_TYPE_HOME_CONTROLS,
+ COMPLICATION_TYPE_SMARTSPACE
})
@Retention(RetentionPolicy.SOURCE)
@interface ComplicationType {}
@@ -175,6 +176,7 @@
int COMPLICATION_TYPE_AIR_QUALITY = 1 << 3;
int COMPLICATION_TYPE_CAST_INFO = 1 << 4;
int COMPLICATION_TYPE_HOME_CONTROLS = 1 << 5;
+ int COMPLICATION_TYPE_SMARTSPACE = 1 << 6;
/**
* The {@link Host} interface specifies a way a {@link Complication} to communicate with its
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
index dcab90f..d5db63d 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
@@ -21,6 +21,7 @@
import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_DATE;
import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_HOME_CONTROLS;
import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_NONE;
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_SMARTSPACE;
import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_TIME;
import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_WEATHER;
@@ -51,6 +52,8 @@
return COMPLICATION_TYPE_CAST_INFO;
case DreamBackend.COMPLICATION_TYPE_HOME_CONTROLS:
return COMPLICATION_TYPE_HOME_CONTROLS;
+ case DreamBackend.COMPLICATION_TYPE_SMARTSPACE:
+ return COMPLICATION_TYPE_SMARTSPACE;
default:
return COMPLICATION_TYPE_NONE;
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
index ac6edba..567bdbc 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
@@ -52,6 +52,11 @@
return mViewHolderProvider.get();
}
+ @Override
+ public int getRequiredTypeAvailability() {
+ return COMPLICATION_TYPE_SMARTSPACE;
+ }
+
/**
* {@link CoreStartable} responsbile for registering {@link SmartSpaceComplication} with
* SystemUI.
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
index 2cee2520..dfa3bcd 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
@@ -23,7 +23,10 @@
*/
interface FeatureFlags : FlagListenable {
/** Returns a boolean value for the given flag. */
- fun isEnabled(flag: BooleanFlag): Boolean
+ fun isEnabled(flag: UnreleasedFlag): Boolean
+
+ /** Returns a boolean value for the given flag. */
+ fun isEnabled(flag: ReleasedFlag): Boolean
/** Returns a boolean value for the given flag. */
fun isEnabled(flag: ResourceBooleanFlag): Boolean
@@ -39,4 +42,4 @@
/** Returns a string value for the given flag. */
fun getString(flag: ResourceStringFlag): String
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
index f804325..b4b8795 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
@@ -48,6 +48,8 @@
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.settings.SecureSettings;
+import org.jetbrains.annotations.NotNull;
+
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
@@ -84,6 +86,7 @@
private final Resources mResources;
private final SystemPropertiesHelper mSystemProperties;
private final DeviceConfigProxy mDeviceConfigProxy;
+ private final ServerFlagReader mServerFlagReader;
private final Map<Integer, Flag<?>> mAllFlags;
private final Map<Integer, Boolean> mBooleanFlagCache = new TreeMap<>();
private final Map<Integer, String> mStringFlagCache = new TreeMap<>();
@@ -98,6 +101,7 @@
@Main Resources resources,
DumpManager dumpManager,
DeviceConfigProxy deviceConfigProxy,
+ ServerFlagReader serverFlagReader,
@Named(ALL_FLAGS) Map<Integer, Flag<?>> allFlags,
CommandRegistry commandRegistry,
IStatusBarService barService) {
@@ -106,6 +110,7 @@
mResources = resources;
mSystemProperties = systemProperties;
mDeviceConfigProxy = deviceConfigProxy;
+ mServerFlagReader = serverFlagReader;
mAllFlags = allFlags;
mBarService = barService;
@@ -121,7 +126,16 @@
}
@Override
- public boolean isEnabled(@NonNull BooleanFlag flag) {
+ public boolean isEnabled(@NotNull UnreleasedFlag flag) {
+ return isEnabledInternal(flag);
+ }
+
+ @Override
+ public boolean isEnabled(@NotNull ReleasedFlag flag) {
+ return isEnabledInternal(flag);
+ }
+
+ private boolean isEnabledInternal(@NotNull BooleanFlag flag) {
int id = flag.getId();
if (!mBooleanFlagCache.containsKey(id)) {
mBooleanFlagCache.put(id,
@@ -198,14 +212,17 @@
/** Specific override for Boolean flags that checks against the teamfood list.*/
private boolean readFlagValue(int id, boolean defaultValue) {
Boolean result = readBooleanFlagOverride(id);
- // Only check for teamfood if the default is false.
- if (!defaultValue && result == null && id != Flags.TEAMFOOD.getId()) {
+ boolean hasServerOverride = mServerFlagReader.hasOverride(id);
+
+ // Only check for teamfood if the default is false
+ // and there is no server override.
+ if (!hasServerOverride && !defaultValue && result == null && id != Flags.TEAMFOOD.getId()) {
if (mAllFlags.containsKey(id) && mAllFlags.get(id).getTeamfood()) {
return isEnabled(Flags.TEAMFOOD);
}
}
- return result == null ? defaultValue : result;
+ return result == null ? mServerFlagReader.readServerOverride(id, defaultValue) : result;
}
private Boolean readBooleanFlagOverride(int id) {
@@ -410,36 +427,38 @@
*/
@Nullable
private ParcelableFlag<?> toParcelableFlag(Flag<?> f) {
- if (f instanceof BooleanFlag) {
- return new BooleanFlag(
- f.getId(),
- isEnabled((BooleanFlag) f),
- f.getTeamfood(),
- readBooleanFlagOverride(f.getId()) != null);
- }
- if (f instanceof ResourceBooleanFlag) {
- return new BooleanFlag(
- f.getId(),
- isEnabled((ResourceBooleanFlag) f),
- f.getTeamfood(),
- readBooleanFlagOverride(f.getId()) != null);
- }
- if (f instanceof DeviceConfigBooleanFlag) {
- return new BooleanFlag(
- f.getId(), isEnabled((DeviceConfigBooleanFlag) f), f.getTeamfood());
- }
- if (f instanceof SysPropBooleanFlag) {
+ boolean enabled;
+ boolean teamfood = f.getTeamfood();
+ boolean overridden;
+
+ if (f instanceof ReleasedFlag) {
+ enabled = isEnabled((ReleasedFlag) f);
+ overridden = readBooleanFlagOverride(f.getId()) != null;
+ } else if (f instanceof UnreleasedFlag) {
+ enabled = isEnabled((UnreleasedFlag) f);
+ overridden = readBooleanFlagOverride(f.getId()) != null;
+ } else if (f instanceof ResourceBooleanFlag) {
+ enabled = isEnabled((ResourceBooleanFlag) f);
+ overridden = readBooleanFlagOverride(f.getId()) != null;
+ } else if (f instanceof DeviceConfigBooleanFlag) {
+ enabled = isEnabled((DeviceConfigBooleanFlag) f);
+ overridden = false;
+ } else if (f instanceof SysPropBooleanFlag) {
// TODO(b/223379190): Teamfood not supported for sysprop flags yet.
- return new BooleanFlag(
- f.getId(),
- ((SysPropBooleanFlag) f).getDefault(),
- false,
- !mSystemProperties.get(((SysPropBooleanFlag) f).getName()).isEmpty());
+ enabled = isEnabled((SysPropBooleanFlag) f);
+ teamfood = false;
+ overridden = !mSystemProperties.get(((SysPropBooleanFlag) f).getName()).isEmpty();
+ } else {
+ // TODO: add support for other flag types.
+ Log.w(TAG, "Unsupported Flag Type. Please file a bug.");
+ return null;
}
- // TODO: add support for other flag types.
- Log.w(TAG, "Unsupported Flag Type. Please file a bug.");
- return null;
+ if (enabled) {
+ return new ReleasedFlag(f.getId(), teamfood, overridden);
+ } else {
+ return new UnreleasedFlag(f.getId(), teamfood, overridden);
+ }
}
};
@@ -540,8 +559,10 @@
}
private boolean isBooleanFlagEnabled(Flag<?> flag) {
- if (flag instanceof BooleanFlag) {
- return isEnabled((BooleanFlag) flag);
+ if (flag instanceof ReleasedFlag) {
+ return isEnabled((ReleasedFlag) flag);
+ } else if (flag instanceof UnreleasedFlag) {
+ return isEnabled((UnreleasedFlag) flag);
} else if (flag instanceof ResourceBooleanFlag) {
return isEnabled((ResourceBooleanFlag) flag);
} else if (flag instanceof SysPropFlag) {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
index 1492a2b..049b17d 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
@@ -19,7 +19,6 @@
import static java.util.Objects.requireNonNull;
import android.content.res.Resources;
-import android.provider.DeviceConfig;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -31,6 +30,8 @@
import com.android.systemui.dump.DumpManager;
import com.android.systemui.util.DeviceConfigProxy;
+import org.jetbrains.annotations.NotNull;
+
import java.io.PrintWriter;
import java.util.Map;
@@ -47,18 +48,22 @@
private final Resources mResources;
private final SystemPropertiesHelper mSystemProperties;
private final DeviceConfigProxy mDeviceConfigProxy;
+ private final ServerFlagReader mServerFlagReader;
SparseBooleanArray mBooleanCache = new SparseBooleanArray();
SparseArray<String> mStringCache = new SparseArray<>();
+ private boolean mInited;
@Inject
public FeatureFlagsRelease(
@Main Resources resources,
SystemPropertiesHelper systemProperties,
DeviceConfigProxy deviceConfigProxy,
+ ServerFlagReader serverFlagReader,
DumpManager dumpManager) {
mResources = resources;
mSystemProperties = systemProperties;
mDeviceConfigProxy = deviceConfigProxy;
+ mServerFlagReader = serverFlagReader;
dumpManager.registerDumpable("SysUIFlags", this);
}
@@ -69,8 +74,13 @@
public void removeListener(@NonNull Listener listener) {}
@Override
- public boolean isEnabled(BooleanFlag flag) {
- return flag.getDefault();
+ public boolean isEnabled(@NotNull UnreleasedFlag flag) {
+ return false;
+ }
+
+ @Override
+ public boolean isEnabled(@NotNull ReleasedFlag flag) {
+ return mServerFlagReader.readServerOverride(flag.getId(), true);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index c92cf54..e4fc88b 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -32,7 +32,7 @@
*
* Flag Ids are integers.
* Ids must be unique. This is enforced in a unit test.
- * Ids need not be sequential. Flags can "claim" a chunk of ids for flags in related featurs with
+ * Ids need not be sequential. Flags can "claim" a chunk of ids for flags in related features with
* a comment. This is purely for organizational purposes.
*
* On public release builds, flags will always return their default value. There is no way to
@@ -41,30 +41,30 @@
* See {@link FeatureFlagsDebug} for instructions on flipping the flags via adb.
*/
public class Flags {
- public static final BooleanFlag TEAMFOOD = new BooleanFlag(1, false);
+ public static final UnreleasedFlag TEAMFOOD = new UnreleasedFlag(1);
/***************************************/
// 100 - notification
- public static final BooleanFlag NOTIFICATION_PIPELINE_DEVELOPER_LOGGING =
- new BooleanFlag(103, false);
+ public static final UnreleasedFlag NOTIFICATION_PIPELINE_DEVELOPER_LOGGING =
+ new UnreleasedFlag(103);
- public static final BooleanFlag NSSL_DEBUG_LINES =
- new BooleanFlag(105, false);
+ public static final UnreleasedFlag NSSL_DEBUG_LINES =
+ new UnreleasedFlag(105);
- public static final BooleanFlag NSSL_DEBUG_REMOVE_ANIMATION =
- new BooleanFlag(106, false);
+ public static final UnreleasedFlag NSSL_DEBUG_REMOVE_ANIMATION =
+ new UnreleasedFlag(106);
- public static final BooleanFlag NEW_PIPELINE_CRASH_ON_CALL_TO_OLD_PIPELINE =
- new BooleanFlag(107, false);
+ public static final UnreleasedFlag NEW_PIPELINE_CRASH_ON_CALL_TO_OLD_PIPELINE =
+ new UnreleasedFlag(107);
public static final ResourceBooleanFlag NOTIFICATION_DRAG_TO_CONTENTS =
new ResourceBooleanFlag(108, R.bool.config_notificationToContents);
- public static final BooleanFlag REMOVE_UNRANKED_NOTIFICATIONS =
- new BooleanFlag(109, false, true);
+ public static final UnreleasedFlag REMOVE_UNRANKED_NOTIFICATIONS =
+ new UnreleasedFlag(109, true);
- public static final BooleanFlag FSI_REQUIRES_KEYGUARD =
- new BooleanFlag(110, false, true);
+ public static final UnreleasedFlag FSI_REQUIRES_KEYGUARD =
+ new UnreleasedFlag(110, true);
/***************************************/
// 200 - keyguard/lockscreen
@@ -73,11 +73,11 @@
// public static final BooleanFlag KEYGUARD_LAYOUT =
// new BooleanFlag(200, true);
- public static final BooleanFlag LOCKSCREEN_ANIMATIONS =
- new BooleanFlag(201, true);
+ public static final ReleasedFlag LOCKSCREEN_ANIMATIONS =
+ new ReleasedFlag(201);
- public static final BooleanFlag NEW_UNLOCK_SWIPE_ANIMATION =
- new BooleanFlag(202, true);
+ public static final ReleasedFlag NEW_UNLOCK_SWIPE_ANIMATION =
+ new ReleasedFlag(202);
public static final ResourceBooleanFlag CHARGING_RIPPLE =
new ResourceBooleanFlag(203, R.bool.flag_charging_ripple);
@@ -92,31 +92,28 @@
* Whether the KeyguardBottomArea(View|Controller) should use the modern architecture or the old
* one.
*/
- public static final BooleanFlag MODERN_BOTTOM_AREA = new BooleanFlag(
- 206,
- /* default= */ false,
- /* teamfood= */ true);
+ public static final UnreleasedFlag MODERN_BOTTOM_AREA = new UnreleasedFlag(206, true);
- public static final BooleanFlag LOCKSCREEN_CUSTOM_CLOCKS = new BooleanFlag(207, false);
-
+ public static final UnreleasedFlag LOCKSCREEN_CUSTOM_CLOCKS = new UnreleasedFlag(207);
+
/**
* Flag to enable the usage of the new bouncer data source. This is a refactor of and
* eventual replacement of KeyguardBouncer.java.
*/
- public static final BooleanFlag MODERN_BOUNCER = new BooleanFlag(208, true);
+ public static final ReleasedFlag MODERN_BOUNCER = new ReleasedFlag(208);
/***************************************/
// 300 - power menu
- public static final BooleanFlag POWER_MENU_LITE =
- new BooleanFlag(300, true);
+ public static final ReleasedFlag POWER_MENU_LITE =
+ new ReleasedFlag(300);
/***************************************/
// 400 - smartspace
- public static final BooleanFlag SMARTSPACE_DEDUPING =
- new BooleanFlag(400, true);
+ public static final ReleasedFlag SMARTSPACE_DEDUPING =
+ new ReleasedFlag(400);
- public static final BooleanFlag SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED =
- new BooleanFlag(401, true);
+ public static final ReleasedFlag SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED =
+ new ReleasedFlag(401);
public static final ResourceBooleanFlag SMARTSPACE =
new ResourceBooleanFlag(402, R.bool.flag_smartspace);
@@ -127,11 +124,11 @@
* @deprecated Not needed anymore
*/
@Deprecated
- public static final BooleanFlag NEW_USER_SWITCHER =
- new BooleanFlag(500, true);
+ public static final ReleasedFlag NEW_USER_SWITCHER =
+ new ReleasedFlag(500);
- public static final BooleanFlag COMBINED_QS_HEADERS =
- new BooleanFlag(501, false, true);
+ public static final UnreleasedFlag COMBINED_QS_HEADERS =
+ new UnreleasedFlag(501, true);
public static final ResourceBooleanFlag PEOPLE_TILE =
new ResourceBooleanFlag(502, R.bool.flag_conversations);
@@ -143,9 +140,9 @@
* @deprecated Not needed anymore
*/
@Deprecated
- public static final BooleanFlag NEW_FOOTER = new BooleanFlag(504, true);
+ public static final ReleasedFlag NEW_FOOTER = new ReleasedFlag(504);
- public static final BooleanFlag NEW_HEADER = new BooleanFlag(505, false, true);
+ public static final UnreleasedFlag NEW_HEADER = new UnreleasedFlag(505, true);
public static final ResourceBooleanFlag FULL_SCREEN_USER_SWITCHER =
new ResourceBooleanFlag(506, R.bool.config_enableFullscreenUserSwitcher);
@@ -154,21 +151,21 @@
public static final ResourceBooleanFlag STATUS_BAR_USER_SWITCHER =
new ResourceBooleanFlag(602, R.bool.flag_user_switcher_chip);
- public static final BooleanFlag STATUS_BAR_LETTERBOX_APPEARANCE =
- new BooleanFlag(603, false);
+ public static final UnreleasedFlag STATUS_BAR_LETTERBOX_APPEARANCE =
+ new UnreleasedFlag(603, false);
- public static final BooleanFlag NEW_STATUS_BAR_PIPELINE = new BooleanFlag(604, false);
+ public static final UnreleasedFlag NEW_STATUS_BAR_PIPELINE = new UnreleasedFlag(604, true);
/***************************************/
// 700 - dialer/calls
- public static final BooleanFlag ONGOING_CALL_STATUS_BAR_CHIP =
- new BooleanFlag(700, true);
+ public static final ReleasedFlag ONGOING_CALL_STATUS_BAR_CHIP =
+ new ReleasedFlag(700);
- public static final BooleanFlag ONGOING_CALL_IN_IMMERSIVE =
- new BooleanFlag(701, true);
+ public static final ReleasedFlag ONGOING_CALL_IN_IMMERSIVE =
+ new ReleasedFlag(701);
- public static final BooleanFlag ONGOING_CALL_IN_IMMERSIVE_CHIP_TAP =
- new BooleanFlag(702, true);
+ public static final ReleasedFlag ONGOING_CALL_IN_IMMERSIVE_CHIP_TAP =
+ new ReleasedFlag(702);
/***************************************/
// 800 - general visual/theme
@@ -177,20 +174,19 @@
/***************************************/
// 801 - region sampling
- public static final BooleanFlag REGION_SAMPLING =
- new BooleanFlag(801, false);
+ public static final UnreleasedFlag REGION_SAMPLING = new UnreleasedFlag(801);
/***************************************/
// 900 - media
- public static final BooleanFlag MEDIA_TAP_TO_TRANSFER = new BooleanFlag(900, true);
- public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, false);
- public static final BooleanFlag MEDIA_NEARBY_DEVICES = new BooleanFlag(903, true);
- public static final BooleanFlag MEDIA_MUTE_AWAIT = new BooleanFlag(904, true);
+ public static final ReleasedFlag MEDIA_TAP_TO_TRANSFER = new ReleasedFlag(900);
+ public static final UnreleasedFlag MEDIA_SESSION_ACTIONS = new UnreleasedFlag(901);
+ public static final ReleasedFlag MEDIA_NEARBY_DEVICES = new ReleasedFlag(903);
+ public static final ReleasedFlag MEDIA_MUTE_AWAIT = new ReleasedFlag(904);
// 1000 - dock
- public static final BooleanFlag SIMULATE_DOCK_THROUGH_CHARGING =
- new BooleanFlag(1000, true);
- public static final BooleanFlag DOCK_SETUP_ENABLED = new BooleanFlag(1001, true);
+ public static final ReleasedFlag SIMULATE_DOCK_THROUGH_CHARGING =
+ new ReleasedFlag(1000);
+ public static final ReleasedFlag DOCK_SETUP_ENABLED = new ReleasedFlag(1001);
// 1100 - windowing
@@ -214,6 +210,14 @@
public static final SysPropBooleanFlag HIDE_NAVBAR_WINDOW =
new SysPropBooleanFlag(1103, "persist.wm.debug.hide_navbar_window", false);
+ @Keep
+ public static final SysPropBooleanFlag WM_DESKTOP_WINDOWING =
+ new SysPropBooleanFlag(1104, "persist.wm.debug.desktop_mode", false);
+
+ @Keep
+ public static final SysPropBooleanFlag WM_CAPTION_ON_SHELL =
+ new SysPropBooleanFlag(1105, "persist.wm.debug.caption_on_shell", false);
+
// 1200 - predictive back
@Keep
public static final SysPropBooleanFlag WM_ENABLE_PREDICTIVE_BACK = new SysPropBooleanFlag(
@@ -225,12 +229,12 @@
public static final SysPropBooleanFlag WM_ALWAYS_ENFORCE_PREDICTIVE_BACK =
new SysPropBooleanFlag(1202, "persist.wm.debug.predictive_back_always_enforce", false);
- public static final BooleanFlag NEW_BACK_AFFORDANCE =
- new BooleanFlag(1203, false /* default */, false /* teamfood */);
+ public static final UnreleasedFlag NEW_BACK_AFFORDANCE =
+ new UnreleasedFlag(1203, false /* teamfood */);
// 1300 - screenshots
- public static final BooleanFlag SCREENSHOT_REQUEST_PROCESSOR = new BooleanFlag(1300, false);
+ public static final UnreleasedFlag SCREENSHOT_REQUEST_PROCESSOR = new UnreleasedFlag(1300);
// Pay no attention to the reflection behind the curtain.
// ========================== Curtain ==========================
diff --git a/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
new file mode 100644
index 0000000..fc5b9f4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.flags
+
+import com.android.systemui.util.DeviceConfigProxy
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
+
+interface ServerFlagReader {
+ /** Returns true if there is a server-side setting stored. */
+ fun hasOverride(flagId: Int): Boolean
+
+ /** Returns any stored server-side setting or the default if not set. */
+ fun readServerOverride(flagId: Int, default: Boolean): Boolean
+}
+
+class ServerFlagReaderImpl @Inject constructor(
+ private val deviceConfig: DeviceConfigProxy
+) : ServerFlagReader {
+ override fun hasOverride(flagId: Int): Boolean =
+ deviceConfig.getProperty(
+ SYSUI_NAMESPACE,
+ getServerOverrideName(flagId)
+ ) != null
+
+ override fun readServerOverride(flagId: Int, default: Boolean): Boolean {
+ return deviceConfig.getBoolean(
+ SYSUI_NAMESPACE,
+ getServerOverrideName(flagId),
+ default
+ )
+ }
+
+ private fun getServerOverrideName(flagId: Int): String {
+ return "flag_override_$flagId"
+ }
+}
+
+private val SYSUI_NAMESPACE = "systemui"
+
+@Module
+interface ServerFlagReaderModule {
+ @Binds
+ fun bindsReader(impl: ServerFlagReaderImpl): ServerFlagReader
+}
+
+class ServerFlagReaderFake : ServerFlagReader {
+ private val flagMap: MutableMap<Int, Boolean> = mutableMapOf()
+
+ override fun hasOverride(flagId: Int): Boolean {
+ return flagMap.containsKey(flagId)
+ }
+
+ override fun readServerOverride(flagId: Int, default: Boolean): Boolean {
+ return flagMap.getOrDefault(flagId, default)
+ }
+
+ fun setFlagValue(flagId: Int, value: Boolean) {
+ flagMap.put(flagId, value)
+ }
+
+ fun eraseFlag(flagId: Int) {
+ flagMap.remove(flagId)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
index dc23684d..6124e10 100644
--- a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
@@ -22,17 +22,11 @@
import com.android.systemui.util.collection.RingBuffer
import com.google.errorprone.annotations.CompileTimeConstant
import java.io.PrintWriter
-import java.text.SimpleDateFormat
-import java.util.Arrays.stream
-import java.util.Locale
import java.util.concurrent.ArrayBlockingQueue
import java.util.concurrent.BlockingQueue
import kotlin.concurrent.thread
import kotlin.math.max
-const val UNBOUNDED_STACK_TRACE = -1
-const val NESTED_TRACE_DEPTH = 10
-
/**
* A simple ring buffer of recyclable log messages
*
@@ -74,18 +68,12 @@
* @param maxSize The maximum number of messages to keep in memory at any one time. Buffers start
* out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches
* the maximum, it behaves like a ring buffer.
- * @param rootStackTraceDepth The number of stack trace elements to be logged for an exception when
- * the logBuffer is dumped. Defaulted to -1 [UNBOUNDED_STACK_TRACE] to print the entire stack trace.
- * @param nestedStackTraceDepth The number of stack trace elements to be logged for any nested
- * exceptions present in [Throwable.cause] or [Throwable.suppressedExceptions].
*/
class LogBuffer @JvmOverloads constructor(
private val name: String,
private val maxSize: Int,
private val logcatEchoTracker: LogcatEchoTracker,
private val systrace: Boolean = true,
- private val rootStackTraceDepth: Int = UNBOUNDED_STACK_TRACE,
- private val nestedStackTraceDepth: Int = NESTED_TRACE_DEPTH,
) {
private val buffer = RingBuffer(maxSize) { LogMessageImpl.create() }
@@ -236,7 +224,7 @@
val iterationStart = if (tailLength <= 0) { 0 } else { max(0, buffer.size - tailLength) }
for (i in iterationStart until buffer.size) {
- dumpMessage(buffer[i], pw)
+ buffer[i].dump(pw)
}
}
@@ -264,76 +252,6 @@
}
}
- private fun dumpMessage(
- message: LogMessage,
- pw: PrintWriter
- ) {
- val formattedTimestamp = DATE_FORMAT.format(message.timestamp)
- val shortLevel = message.level.shortString
- val messageToPrint = message.messagePrinter(message)
- val tag = message.tag
- printLikeLogcat(pw, formattedTimestamp, shortLevel, tag, messageToPrint)
- message.exception?.let { ex ->
- printException(
- pw,
- formattedTimestamp,
- shortLevel,
- ex,
- tag,
- stackTraceDepth = rootStackTraceDepth)
- }
- }
-
- private fun printException(
- pw: PrintWriter,
- timestamp: String,
- level: String,
- exception: Throwable,
- tag: String,
- exceptionMessagePrefix: String = "",
- stackTraceDepth: Int = UNBOUNDED_STACK_TRACE
- ) {
- val message = "$exceptionMessagePrefix$exception"
- printLikeLogcat(pw, timestamp, level, tag, message)
- var stacktraceStream = stream(exception.stackTrace)
- if (stackTraceDepth != UNBOUNDED_STACK_TRACE) {
- stacktraceStream = stacktraceStream.limit(stackTraceDepth.toLong())
- }
- stacktraceStream.forEach { line ->
- printLikeLogcat(pw, timestamp, level, tag, "\tat $line")
- }
- exception.cause?.let { cause ->
- printException(pw, timestamp, level, cause, tag, "Caused by: ", nestedStackTraceDepth)
- }
- exception.suppressedExceptions.forEach { suppressed ->
- printException(
- pw,
- timestamp,
- level,
- suppressed,
- tag,
- "Suppressed: ",
- nestedStackTraceDepth
- )
- }
- }
-
- private fun printLikeLogcat(
- pw: PrintWriter,
- formattedTimestamp: String,
- shortLogLevel: String,
- tag: String,
- message: String
- ) {
- pw.print(formattedTimestamp)
- pw.print(" ")
- pw.print(shortLogLevel)
- pw.print(" ")
- pw.print(tag)
- pw.print(": ")
- pw.println(message)
- }
-
private fun echo(message: LogMessage, toLogcat: Boolean, toSystrace: Boolean) {
if (toLogcat || toSystrace) {
val strMessage = message.messagePrinter(message)
@@ -370,5 +288,4 @@
typealias MessageInitializer = LogMessage.() -> Unit
private const val TAG = "LogBuffer"
-private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
private val FROZEN_MESSAGE = LogMessageImpl.create()
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt b/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
index 987aea8..dae2592 100644
--- a/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
@@ -16,6 +16,10 @@
package com.android.systemui.log
+import java.io.PrintWriter
+import java.text.SimpleDateFormat
+import java.util.Locale
+
/**
* Generic data class for storing messages logged to a [LogBuffer]
*
@@ -50,6 +54,17 @@
var bool2: Boolean
var bool3: Boolean
var bool4: Boolean
+
+ /**
+ * Function that dumps the [LogMessage] to the provided [writer].
+ */
+ fun dump(writer: PrintWriter) {
+ val formattedTimestamp = DATE_FORMAT.format(timestamp)
+ val shortLevel = level.shortString
+ val messageToPrint = messagePrinter(this)
+ printLikeLogcat(writer, formattedTimestamp, shortLevel, tag, messageToPrint)
+ exception?.printStackTrace(writer)
+ }
}
/**
@@ -61,3 +76,21 @@
* of the printer for each call, thwarting our attempts at avoiding any sort of allocation.
*/
typealias MessagePrinter = LogMessage.() -> String
+
+private fun printLikeLogcat(
+ pw: PrintWriter,
+ formattedTimestamp: String,
+ shortLogLevel: String,
+ tag: String,
+ message: String
+) {
+ pw.print(formattedTimestamp)
+ pw.print(" ")
+ pw.print(shortLogLevel)
+ pw.print(" ")
+ pw.print(tag)
+ pw.print(": ")
+ pw.println(message)
+}
+
+private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 2d7a809..3789cbb 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -302,10 +302,6 @@
*/
@VisibleForTesting
void createNavigationBar(Display display, Bundle savedState, RegisterStatusBarResult result) {
- if (initializeTaskbarIfNecessary()) {
- return;
- }
-
if (display == null) {
return;
}
@@ -315,7 +311,7 @@
// We may show TaskBar on the default display for large screen device. Don't need to create
// navigation bar for this case.
- if (mIsTablet && isOnDefaultDisplay) {
+ if (isOnDefaultDisplay && initializeTaskbarIfNecessary()) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
index b44b4de..6e927b0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
@@ -42,7 +42,6 @@
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.ViewController
-import com.android.wm.shell.back.BackAnimation
import java.io.PrintWriter
import javax.inject.Inject
import kotlin.math.abs
@@ -119,7 +118,7 @@
private val latencyTracker: LatencyTracker
) {
/** Construct a [BackPanelController]. */
- fun create(context: Context, backAnimation: BackAnimation?): BackPanelController {
+ fun create(context: Context): BackPanelController {
val backPanelController = BackPanelController(
context,
windowManager,
@@ -418,6 +417,7 @@
stretchEntryBackIndicator(preThresholdStretchProgress(xTranslation))
GestureState.INACTIVE ->
mView.resetStretch()
+ else -> {}
}
// set y translation
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index fc6dcd3..6ac3ead 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -574,10 +574,10 @@
private void resetEdgeBackPlugin() {
if (mIsNewBackAffordanceEnabled) {
setEdgeBackPlugin(
- mBackPanelControllerFactory.create(mContext, mBackAnimation));
+ mBackPanelControllerFactory.create(mContext));
} else {
setEdgeBackPlugin(
- new NavigationBarEdgePanel(mContext, mBackAnimation, mLatencyTracker));
+ new NavigationBarEdgePanel(mContext, mLatencyTracker));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
index eba9d3f..122852f 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
@@ -43,7 +43,6 @@
import android.view.WindowManager;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
-import android.window.BackEvent;
import androidx.core.graphics.ColorUtils;
import androidx.dynamicanimation.animation.DynamicAnimation;
@@ -59,7 +58,6 @@
import com.android.systemui.plugins.NavigationEdgeBackPlugin;
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
import com.android.systemui.statusbar.VibratorHelper;
-import com.android.wm.shell.back.BackAnimation;
import java.io.PrintWriter;
import java.util.concurrent.Executor;
@@ -283,14 +281,11 @@
}
};
private BackCallback mBackCallback;
- private BackAnimation mBackAnimation;
- public NavigationBarEdgePanel(Context context,
- BackAnimation backAnimation, LatencyTracker latencyTracker) {
+ public NavigationBarEdgePanel(Context context, LatencyTracker latencyTracker) {
super(context);
mWindowManager = context.getSystemService(WindowManager.class);
- mBackAnimation = backAnimation;
mVibratorHelper = Dependency.get(VibratorHelper.class);
mDensity = context.getResources().getDisplayMetrics().density;
@@ -360,7 +355,6 @@
.getDimension(R.dimen.navigation_edge_action_drag_threshold);
mSwipeProgressThreshold = context.getResources()
.getDimension(R.dimen.navigation_edge_action_progress_threshold);
- initializeBackAnimation();
setVisibility(GONE);
@@ -388,17 +382,6 @@
mLatencyTracker = latencyTracker;
}
- public void setBackAnimation(BackAnimation backAnimation) {
- mBackAnimation = backAnimation;
- initializeBackAnimation();
- }
-
- private void initializeBackAnimation() {
- if (mBackAnimation != null) {
- mBackAnimation.setSwipeThresholds(mSwipeTriggerThreshold, mSwipeProgressThreshold);
- }
- }
-
@Override
public void onDestroy() {
cancelFailsafe();
@@ -484,12 +467,6 @@
@Override
public void onMotionEvent(MotionEvent event) {
- if (mBackAnimation != null) {
- mBackAnimation.onBackMotion(
- event.getX(), event.getY(),
- event.getActionMasked(),
- mIsLeftPanel ? BackEvent.EDGE_LEFT : BackEvent.EDGE_RIGHT);
- }
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
@@ -903,9 +880,6 @@
// Whenever the trigger back state changes the existing translation animation should be
// cancelled
mTranslationAnimation.cancel();
- if (mBackAnimation != null) {
- mBackAnimation.setTriggerBack(triggerBack);
- }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt b/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
index 1b74ac3..b02a45a 100644
--- a/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
@@ -18,7 +18,7 @@
import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.smartspace.SmartspacePrecondition
import com.android.systemui.smartspace.SmartspaceTargetFilter
-import com.android.systemui.smartspace.filters.LockscreenTargetFilter
+import com.android.systemui.smartspace.filters.LockscreenAndDreamTargetFilter
import com.android.systemui.smartspace.preconditions.LockscreenPrecondition
import dagger.Binds
import dagger.BindsOptionalOf
@@ -61,7 +61,7 @@
@Binds
@Named(LOCKSCREEN_SMARTSPACE_TARGET_FILTER)
abstract fun provideLockscreenSmartspaceTargetFilter(
- filter: LockscreenTargetFilter?
+ filter: LockscreenAndDreamTargetFilter?
): SmartspaceTargetFilter?
@Binds
@@ -69,4 +69,4 @@
abstract fun bindSmartspacePrecondition(
lockscreenPrecondition: LockscreenPrecondition?
): SmartspacePrecondition?
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenTargetFilter.kt b/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenTargetFilter.kt
rename to packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt
index 6ad4901..aa4cf75 100644
--- a/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenTargetFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt
@@ -32,9 +32,9 @@
import javax.inject.Inject
/**
- * {@link SmartspaceTargetFilter} for smartspace targets that show above the lockscreen.
+ * {@link SmartspaceTargetFilter} for smartspace targets that show above the lockscreen and dreams.
*/
-class LockscreenTargetFilter @Inject constructor(
+class LockscreenAndDreamTargetFilter @Inject constructor(
private val secureSettings: SecureSettings,
private val userTracker: UserTracker,
private val execution: Execution,
@@ -149,4 +149,4 @@
listeners.forEach { it.onCriteriaChanged() }
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
index 48e3450..0951e82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
@@ -19,7 +19,9 @@
import android.app.IActivityManager;
import android.content.Context;
import android.os.Handler;
+import android.os.RemoteException;
import android.service.dreams.IDreamManager;
+import android.util.Log;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.statusbar.IStatusBarService;
@@ -60,10 +62,12 @@
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
import com.android.systemui.statusbar.phone.StatusBarIconList;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallFlags;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLogger;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.window.StatusBarWindowController;
import com.android.systemui.tracing.ProtoTracer;
@@ -274,7 +278,30 @@
@Provides
@SysUISingleton
static DialogLaunchAnimator provideDialogLaunchAnimator(IDreamManager dreamManager,
+ KeyguardStateController keyguardStateController,
+ Lazy<StatusBarKeyguardViewManager> statusBarKeyguardViewManager,
InteractionJankMonitor interactionJankMonitor) {
- return new DialogLaunchAnimator(dreamManager, interactionJankMonitor);
+ DialogLaunchAnimator.Callback callback = new DialogLaunchAnimator.Callback() {
+ @Override
+ public boolean isDreaming() {
+ try {
+ return dreamManager.isDreaming();
+ } catch (RemoteException e) {
+ Log.e("DialogLaunchAnimator.Callback", "dreamManager.isDreaming failed", e);
+ return false;
+ }
+ }
+
+ @Override
+ public boolean isUnlocked() {
+ return keyguardStateController.isUnlocked();
+ }
+
+ @Override
+ public boolean isShowingAlternateAuthOnUnlock() {
+ return statusBarKeyguardViewManager.get().shouldShowAltAuth();
+ }
+ };
+ return new DialogLaunchAnimator(callback, interactionJankMonitor);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index dac532b..e9771d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -471,7 +471,8 @@
showBouncer(scrimmed);
}
- private boolean shouldShowAltAuth() {
+ /** Whether we should show the alternate authentication instead of the traditional bouncer. */
+ public boolean shouldShowAltAuth() {
return mAlternateAuthInterceptor != null
&& mKeyguardUpdateManager.isUnlockingWithBiometricAllowed(true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
index e22a896..4c76270 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
@@ -405,8 +405,8 @@
}
@Override
- public void onEntryUpdated(NotificationEntry entry) {
- BubblesManager.this.onEntryUpdated(entry);
+ public void onEntryUpdated(NotificationEntry entry, boolean fromSystem) {
+ BubblesManager.this.onEntryUpdated(entry, fromSystem);
}
@Override
@@ -444,9 +444,10 @@
}
}
- void onEntryUpdated(NotificationEntry entry) {
+ void onEntryUpdated(NotificationEntry entry, boolean fromSystem) {
+ boolean shouldBubble = mNotificationInterruptStateProvider.shouldBubbleUp(entry);
mBubbles.onEntryUpdated(notifToBubbleEntry(entry),
- mNotificationInterruptStateProvider.shouldBubbleUp(entry));
+ shouldBubble, fromSystem);
}
void onEntryRemoved(NotificationEntry entry) {
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 12597e0..eba2795 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -118,6 +118,33 @@
private final UserInfoController mUserInfoController;
private final Executor mSysUiMainExecutor;
+ // Listeners and callbacks. Note that we prefer member variable over anonymous class here to
+ // avoid the situation that some implementations, like KeyguardUpdateMonitor, use WeakReference
+ // internally and anonymous class could be released after registration.
+ private final ConfigurationController.ConfigurationListener mConfigurationListener =
+ new ConfigurationController.ConfigurationListener() {
+ @Override
+ public void onConfigChanged(Configuration newConfig) {
+ mShell.onConfigurationChanged(newConfig);
+ }
+ };
+ private final KeyguardStateController.Callback mKeyguardStateCallback =
+ new KeyguardStateController.Callback() {
+ @Override
+ public void onKeyguardShowingChanged() {
+ mShell.onKeyguardVisibilityChanged(mKeyguardStateController.isShowing(),
+ mKeyguardStateController.isOccluded(),
+ mKeyguardStateController.isAnimatingBetweenKeyguardAndSurfaceBehind());
+ }
+ };
+ private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
+ new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onKeyguardDismissAnimationFinished() {
+ mShell.onKeyguardDismissAnimationFinished();
+ }
+ };
+
private boolean mIsSysUiStateValid;
private KeyguardUpdateMonitorCallback mOneHandedKeyguardCallback;
private WakefulnessLifecycle.Observer mWakefulnessObserver;
@@ -159,28 +186,11 @@
public void start() {
// Notify with the initial configuration and subscribe for new config changes
mShell.onConfigurationChanged(mContext.getResources().getConfiguration());
- mConfigurationController.addCallback(new ConfigurationController.ConfigurationListener() {
- @Override
- public void onConfigChanged(Configuration newConfig) {
- mShell.onConfigurationChanged(newConfig);
- }
- });
+ mConfigurationController.addCallback(mConfigurationListener);
// Subscribe to keyguard changes
- mKeyguardStateController.addCallback(new KeyguardStateController.Callback() {
- @Override
- public void onKeyguardShowingChanged() {
- mShell.onKeyguardVisibilityChanged(mKeyguardStateController.isShowing(),
- mKeyguardStateController.isOccluded(),
- mKeyguardStateController.isAnimatingBetweenKeyguardAndSurfaceBehind());
- }
- });
- mKeyguardUpdateMonitor.registerCallback(new KeyguardUpdateMonitorCallback() {
- @Override
- public void onKeyguardDismissAnimationFinished() {
- mShell.onKeyguardDismissAnimationFinished();
- }
- });
+ mKeyguardStateController.addCallback(mKeyguardStateCallback);
+ mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
// TODO: Consider piping config change and other common calls to a shell component to
// delegate internally
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
index dffad6c..80385e6 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/AdminSecondaryLockScreenControllerTest.java
@@ -44,6 +44,7 @@
import androidx.test.filters.SmallTest;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.SysuiTestCase;
import org.junit.After;
@@ -190,7 +191,7 @@
private void verifyViewDismissed(SurfaceView v) throws Exception {
verify(mKeyguardSecurityContainer).removeView(v);
- verify(mKeyguardCallback).dismiss(true, TARGET_USER_ID, true);
+ verify(mKeyguardCallback).dismiss(true, TARGET_USER_ID, true, SecurityMode.Invalid);
assertThat(mContext.isBound(mComponentName)).isFalse();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
index ad6d146..bb455da 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
@@ -86,10 +86,11 @@
becauseCannotSkipBouncer = false,
biometricSettingEnabledForUser = false,
bouncerFullyShown = false,
+ onlyFaceEnrolled = false,
faceAuthenticated = false,
faceDisabled = false,
goingToSleep = false,
- keyguardAwake = false,
+ keyguardAwakeExcludingBouncerShowing = false,
keyguardGoingAway = false,
listeningForFaceAssistant = false,
occludingAppRequestingFaceAuth = false,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index dc87a6a..aecec9d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -21,7 +21,10 @@
import static com.android.keyguard.KeyguardSecurityContainer.MODE_DEFAULT;
import static com.android.keyguard.KeyguardSecurityContainer.MODE_ONE_HANDED;
+import static com.google.common.truth.Truth.assertThat;
+
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;
@@ -76,6 +79,8 @@
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper()
public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
+ private static final int TARGET_USER_ID = 100;
+
@Rule
public MockitoRule mRule = MockitoJUnit.rule();
@@ -381,6 +386,44 @@
verify(mSidefpsController, never()).show();
}
+ @Test
+ public void showNextSecurityScreenOrFinish_setsSecurityScreenToPinAfterSimPinUnlock() {
+ // GIVEN the current security method is SimPin
+ when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
+ when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(TARGET_USER_ID)).thenReturn(false);
+ mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.SimPin);
+
+ // WHEN a request is made from the SimPin screens to show the next security method
+ when(mKeyguardSecurityModel.getSecurityMode(TARGET_USER_ID)).thenReturn(SecurityMode.PIN);
+ mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
+ /* authenticated= */true,
+ TARGET_USER_ID,
+ /* bypassSecondaryLockScreen= */true,
+ SecurityMode.SimPin);
+
+ // THEN the next security method of PIN is set, and the keyguard is not marked as done
+ verify(mSecurityCallback, never()).finish(anyBoolean(), anyInt());
+ assertThat(mKeyguardSecurityContainerController.getCurrentSecurityMode())
+ .isEqualTo(SecurityMode.PIN);
+ }
+
+ @Test
+ public void showNextSecurityScreenOrFinish_ignoresCallWhenSecurityMethodHasChanged() {
+ //GIVEN current security mode has been set to PIN
+ mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.PIN);
+
+ //WHEN a request comes from SimPin to dismiss the security screens
+ boolean keyguardDone = mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
+ /* authenticated= */true,
+ TARGET_USER_ID,
+ /* bypassSecondaryLockScreen= */true,
+ SecurityMode.SimPin);
+
+ //THEN no action has happened, which will not dismiss the security screens
+ assertThat(keyguardDone).isEqualTo(false);
+ verify(mKeyguardUpdateMonitor, never()).getUserHasTrust(anyInt());
+ }
+
private void setupConditionsToEnableSideFpsHint() {
attachView();
setSideFpsHintEnabledFromResources(true);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 035404c..c677371 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -22,6 +22,7 @@
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
+import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
import static com.google.common.truth.Truth.assertThat;
@@ -109,6 +110,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
+import org.mockito.internal.util.reflection.FieldSetter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -196,11 +198,14 @@
mBiometricEnabledCallbackArgCaptor;
@Captor
private ArgumentCaptor<FaceManager.AuthenticationCallback> mAuthenticationCallbackCaptor;
+ @Captor
+ private ArgumentCaptor<CancellationSignal> mCancellationSignalCaptor;
// Direct executor
- private Executor mBackgroundExecutor = Runnable::run;
- private Executor mMainExecutor = Runnable::run;
+ private final Executor mBackgroundExecutor = Runnable::run;
+ private final Executor mMainExecutor = Runnable::run;
private TestableLooper mTestableLooper;
+ private Handler mHandler;
private TestableKeyguardUpdateMonitor mKeyguardUpdateMonitor;
private TestableContext mSpiedContext;
private MockitoSession mMockitoSession;
@@ -289,6 +294,13 @@
mBiometricEnabledOnKeyguardCallback = mBiometricEnabledCallbackArgCaptor.getValue();
biometricsEnabledForCurrentUser();
+ mHandler = spy(mKeyguardUpdateMonitor.getHandler());
+ try {
+ FieldSetter.setField(mKeyguardUpdateMonitor,
+ KeyguardUpdateMonitor.class.getDeclaredField("mHandler"), mHandler);
+ } catch (NoSuchFieldException e) {
+
+ }
verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
mStatusBarStateListener = mStatusBarStateListenerCaptor.getValue();
mKeyguardUpdateMonitor.registerCallback(mTestCallback);
@@ -328,7 +340,7 @@
when(mTelephonyManager.getActiveModemCount()).thenReturn(1);
when(mTelephonyManager.getSimState(anyInt())).thenReturn(state);
- when(mSubscriptionManager.getSubscriptionIds(anyInt())).thenReturn(new int[] { subId });
+ when(mSubscriptionManager.getSubscriptionIds(anyInt())).thenReturn(new int[]{subId});
KeyguardUpdateMonitor testKUM = new TestableKeyguardUpdateMonitor(mSpiedContext);
@@ -503,7 +515,7 @@
// Even SimState Loaded, still need ACTION_SERVICE_STATE turn on mTelephonyCapable
assertThat(mKeyguardUpdateMonitor.mTelephonyCapable).isFalse();
- Intent intentServiceState = new Intent(Intent.ACTION_SERVICE_STATE);
+ Intent intentServiceState = new Intent(Intent.ACTION_SERVICE_STATE);
intentSimState.putExtra(Intent.EXTRA_SIM_STATE
, Intent.SIM_STATE_LOADED);
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(getContext()
@@ -518,7 +530,7 @@
mTestableLooper.processAllMessages();
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
- anyInt());
+ anyInt());
verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt());
}
@@ -568,11 +580,12 @@
@Test
public void testTriesToAuthenticate_whenBouncer() {
+ fingerprintIsNotEnrolled();
setKeyguardBouncerVisibility(true);
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
- verify(mFaceManager).isHardwareDetected();
- verify(mFaceManager).hasEnrolledTemplates(anyInt());
+ verify(mFaceManager, atLeastOnce()).isHardwareDetected();
+ verify(mFaceManager, atLeastOnce()).hasEnrolledTemplates(anyInt());
}
@Test
@@ -788,7 +801,8 @@
public void testBiometricsCleared_whenUserSwitches() throws Exception {
final IRemoteCallback reply = new IRemoteCallback.Stub() {
@Override
- public void sendResult(Bundle data) {} // do nothing
+ public void sendResult(Bundle data) {
+ } // do nothing
};
final BiometricAuthenticated dummyAuthentication =
new BiometricAuthenticated(true /* authenticated */, true /* strong */);
@@ -806,7 +820,8 @@
public void testMultiUserJankMonitor_whenUserSwitches() throws Exception {
final IRemoteCallback reply = new IRemoteCallback.Stub() {
@Override
- public void sendResult(Bundle data) {} // do nothing
+ public void sendResult(Bundle data) {
+ } // do nothing
};
mKeyguardUpdateMonitor.handleUserSwitchComplete(10 /* user */);
verify(mInteractionJankMonitor).end(InteractionJankMonitor.CUJ_USER_SWITCH);
@@ -1204,6 +1219,7 @@
throws RemoteException {
// Face auth should run when the following is true.
bouncerFullyVisibleAndNotGoingToSleep();
+ fingerprintIsNotEnrolled();
keyguardNotGoingAway();
currentUserIsPrimary();
strongAuthNotRequired();
@@ -1229,7 +1245,7 @@
mKeyguardUpdateMonitor =
new TestableKeyguardUpdateMonitor(mSpiedContext);
- // Face auth should run when the following is true.
+ // Preconditions for face auth to run
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
strongAuthNotRequired();
@@ -1246,7 +1262,7 @@
@Test
public void testShouldListenForFace_whenStrongAuthDoesNotAllowScanning_returnsFalse()
throws RemoteException {
- // Face auth should run when the following is true.
+ // Preconditions for face auth to run
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
currentUserIsPrimary();
@@ -1267,9 +1283,10 @@
@Test
public void testShouldListenForFace_whenBiometricsDisabledForUser_returnsFalse()
throws RemoteException {
- // Face auth should run when the following is true.
+ // Preconditions for face auth to run
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
+ fingerprintIsNotEnrolled();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
@@ -1289,9 +1306,10 @@
@Test
public void testShouldListenForFace_whenUserCurrentlySwitching_returnsFalse()
throws RemoteException {
- // Face auth should run when the following is true.
+ // Preconditions for face auth to run
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
+ fingerprintIsNotEnrolled();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
@@ -1310,9 +1328,10 @@
@Test
public void testShouldListenForFace_whenSecureCameraLaunched_returnsFalse()
throws RemoteException {
- // Face auth should run when the following is true.
+ // Preconditions for face auth to run
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
+ fingerprintIsNotEnrolled();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
@@ -1331,7 +1350,7 @@
@Test
public void testShouldListenForFace_whenOccludingAppRequestsFaceAuth_returnsTrue()
throws RemoteException {
- // Face auth should run when the following is true.
+ // Preconditions for face auth to run
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
currentUserIsPrimary();
@@ -1354,7 +1373,7 @@
@Test
public void testShouldListenForFace_whenBouncerShowingAndDeviceIsAwake_returnsTrue()
throws RemoteException {
- // Face auth should run when the following is true.
+ // Preconditions for face auth to run
keyguardNotGoingAway();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
@@ -1366,6 +1385,7 @@
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
bouncerFullyVisibleAndNotGoingToSleep();
+ fingerprintIsNotEnrolled();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
@@ -1374,7 +1394,7 @@
@Test
public void testShouldListenForFace_whenAuthInterruptIsActive_returnsTrue()
throws RemoteException {
- // Face auth should run when the following is true.
+ // Preconditions for face auth to run
keyguardNotGoingAway();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
@@ -1391,6 +1411,150 @@
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
}
+ @Test
+ public void testShouldListenForFace_whenKeyguardIsAwake_returnsTrue() throws RemoteException {
+ // Preconditions for face auth to run
+ keyguardNotGoingAway();
+ currentUserIsPrimary();
+ currentUserDoesNotHaveTrust();
+ biometricsNotDisabledThroughDevicePolicyManager();
+ biometricsEnabledForCurrentUser();
+ userNotCurrentlySwitching();
+ bouncerFullyVisible();
+
+ statusBarShadeIsLocked();
+ mTestableLooper.processAllMessages();
+
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+
+ deviceNotGoingToSleep();
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+ deviceIsInteractive();
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+ keyguardIsVisible();
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+ statusBarShadeIsNotLocked();
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+ bouncerNotFullyVisible();
+
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
+ }
+
+ @Test
+ public void testShouldListenForFace_whenUdfpsFingerDown_returnsTrue() throws RemoteException {
+ // Preconditions for face auth to run
+ keyguardNotGoingAway();
+ currentUserIsPrimary();
+ currentUserDoesNotHaveTrust();
+ biometricsNotDisabledThroughDevicePolicyManager();
+ biometricsEnabledForCurrentUser();
+ userNotCurrentlySwitching();
+ when(mAuthController.isUdfpsFingerDown()).thenReturn(false);
+ mTestableLooper.processAllMessages();
+
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+
+ when(mAuthController.isUdfpsFingerDown()).thenReturn(true);
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
+ }
+
+ @Test
+ public void testShouldListenForFace_whenUdfpsBouncerIsShowing_returnsTrue()
+ throws RemoteException {
+ // Preconditions for face auth to run
+ keyguardNotGoingAway();
+ currentUserIsPrimary();
+ currentUserDoesNotHaveTrust();
+ biometricsNotDisabledThroughDevicePolicyManager();
+ biometricsEnabledForCurrentUser();
+ userNotCurrentlySwitching();
+ mTestableLooper.processAllMessages();
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
+
+ mKeyguardUpdateMonitor.setUdfpsBouncerShowing(true);
+
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
+ }
+
+ @Test
+ public void testBouncerVisibility_whenBothFingerprintAndFaceIsEnrolled_stopsFaceAuth()
+ throws RemoteException {
+ // Both fingerprint and face are enrolled by default
+ // Preconditions for face auth to run
+ keyguardNotGoingAway();
+ currentUserIsPrimary();
+ currentUserDoesNotHaveTrust();
+ biometricsNotDisabledThroughDevicePolicyManager();
+ biometricsEnabledForCurrentUser();
+ userNotCurrentlySwitching();
+ deviceNotGoingToSleep();
+ deviceIsInteractive();
+ statusBarShadeIsNotLocked();
+ keyguardIsVisible();
+
+ mTestableLooper.processAllMessages();
+
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
+
+ mKeyguardUpdateMonitor.requestFaceAuth(true);
+ verify(mFaceManager).authenticate(any(),
+ mCancellationSignalCaptor.capture(),
+ mAuthenticationCallbackCaptor.capture(),
+ any(),
+ anyInt(),
+ anyBoolean());
+ CancellationSignal cancelSignal = mCancellationSignalCaptor.getValue();
+
+ bouncerFullyVisible();
+ mTestableLooper.processAllMessages();
+
+ assertThat(cancelSignal.isCanceled()).isTrue();
+ }
+
+ @Test
+ public void testFingerprintCanAuth_whenCancellationNotReceivedAndAuthFailed() {
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp();
+ mTestableLooper.processAllMessages();
+ mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
+
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
+ anyInt());
+
+ mKeyguardUpdateMonitor.onFaceAuthenticated(0, false);
+ // Make sure keyguard is going away after face auth attempt, and that it calls
+ // updateBiometricStateListeningState.
+ mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(false);
+ mTestableLooper.processAllMessages();
+
+ verify(mHandler).postDelayed(mKeyguardUpdateMonitor.mFpCancelNotReceived,
+ DEFAULT_CANCEL_SIGNAL_TIMEOUT);
+
+ mKeyguardUpdateMonitor.onFingerprintAuthenticated(0, true);
+ mTestableLooper.processAllMessages();
+
+ verify(mHandler, times(1)).removeCallbacks(mKeyguardUpdateMonitor.mFpCancelNotReceived);
+ mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
+ mTestableLooper.processAllMessages();
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(anyBoolean())).isEqualTo(true);
+ }
+
+ private void fingerprintIsNotEnrolled() {
+ when(mFingerprintManager.hasEnrolledTemplates(mCurrentUserId)).thenReturn(false);
+ }
+
+ private void statusBarShadeIsNotLocked() {
+ mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
+ }
+
+ private void statusBarShadeIsLocked() {
+ mStatusBarStateListener.onStateChanged(StatusBarState.SHADE_LOCKED);
+ }
+
+ private void keyguardIsVisible() {
+ mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true);
+ }
+
private void triggerAuthInterrupt() {
mKeyguardUpdateMonitor.onAuthInterruptDetected(true);
}
@@ -1468,10 +1632,26 @@
}
private void bouncerFullyVisibleAndNotGoingToSleep() {
- mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true, true);
+ bouncerFullyVisible();
+ deviceNotGoingToSleep();
+ }
+
+ private void deviceNotGoingToSleep() {
mKeyguardUpdateMonitor.dispatchFinishedGoingToSleep(/* value doesn't matter */1);
}
+ private void deviceIsInteractive() {
+ mKeyguardUpdateMonitor.dispatchStartedWakingUp();
+ }
+
+ private void bouncerNotFullyVisible() {
+ setKeyguardBouncerVisibility(false);
+ }
+
+ private void bouncerFullyVisible() {
+ setKeyguardBouncerVisibility(true);
+ }
+
private void setKeyguardBouncerVisibility(boolean isVisible) {
mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(isVisible, isVisible);
mTestableLooper.processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
index c48cbb1..0f11241 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
@@ -26,6 +26,7 @@
import junit.framework.Assert.assertNull
import junit.framework.Assert.assertTrue
import junit.framework.AssertionFailedError
+import kotlin.concurrent.thread
import org.junit.After
import org.junit.Before
import org.junit.Rule
@@ -34,19 +35,18 @@
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.Spy
import org.mockito.junit.MockitoJUnit
-import kotlin.concurrent.thread
@SmallTest
@RunWith(AndroidTestingRunner::class)
@RunWithLooper
class ActivityLaunchAnimatorTest : SysuiTestCase() {
private val launchContainer = LinearLayout(mContext)
- private val testLaunchAnimator = LaunchAnimator(TEST_TIMINGS, TEST_INTERPOLATORS)
+ private val testLaunchAnimator = fakeLaunchAnimator()
@Mock lateinit var callback: ActivityLaunchAnimator.Callback
@Mock lateinit var listener: ActivityLaunchAnimator.Listener
@Spy private val controller = TestLaunchAnimatorController(launchContainer)
@@ -77,12 +77,13 @@
// We start in a new thread so that we can ensure that the callbacks are called in the main
// thread.
thread {
- animator.startIntentWithAnimation(
+ animator.startIntentWithAnimation(
controller = controller,
animate = animate,
intentStarter = intentStarter
- )
- }.join()
+ )
+ }
+ .join()
}
@Test
@@ -197,14 +198,25 @@
val bounds = Rect(10 /* left */, 20 /* top */, 30 /* right */, 40 /* bottom */)
val taskInfo = ActivityManager.RunningTaskInfo()
taskInfo.topActivity = ComponentName("com.android.systemui", "FakeActivity")
- taskInfo.topActivityInfo = ActivityInfo().apply {
- applicationInfo = ApplicationInfo()
- }
+ taskInfo.topActivityInfo = ActivityInfo().apply { applicationInfo = ApplicationInfo() }
return RemoteAnimationTarget(
- 0, RemoteAnimationTarget.MODE_OPENING, SurfaceControl(), false, Rect(), Rect(), 0,
- Point(), Rect(), bounds, WindowConfiguration(), false, SurfaceControl(), Rect(),
- taskInfo, false
+ 0,
+ RemoteAnimationTarget.MODE_OPENING,
+ SurfaceControl(),
+ false,
+ Rect(),
+ Rect(),
+ 0,
+ Point(),
+ Rect(),
+ bounds,
+ WindowConfiguration(),
+ false,
+ SurfaceControl(),
+ Rect(),
+ taskInfo,
+ false
)
}
}
@@ -213,17 +225,17 @@
* A simple implementation of [ActivityLaunchAnimator.Controller] which throws if it is called
* outside of the main thread.
*/
-private class TestLaunchAnimatorController(
- override var launchContainer: ViewGroup
-) : ActivityLaunchAnimator.Controller {
- override fun createAnimatorState() = LaunchAnimator.State(
+private class TestLaunchAnimatorController(override var launchContainer: ViewGroup) :
+ ActivityLaunchAnimator.Controller {
+ override fun createAnimatorState() =
+ LaunchAnimator.State(
top = 100,
bottom = 200,
left = 300,
right = 400,
topCornerRadius = 10f,
bottomCornerRadius = 20f
- )
+ )
private fun assertOnMainThread() {
if (Looper.myLooper() != Looper.getMainLooper()) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
index 4218e09..7c1e384 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
@@ -5,7 +5,6 @@
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
-import android.service.dreams.IDreamManager
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.ViewUtils
@@ -38,19 +37,16 @@
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper
class DialogLaunchAnimatorTest : SysuiTestCase() {
- private val launchAnimator = LaunchAnimator(TEST_TIMINGS, TEST_INTERPOLATORS)
private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
private val attachedViews = mutableSetOf<View>()
- @Mock lateinit var dreamManager: IDreamManager
@Mock lateinit var interactionJankMonitor: InteractionJankMonitor
@get:Rule val rule = MockitoJUnit.rule()
@Before
fun setUp() {
- dialogLaunchAnimator = DialogLaunchAnimator(
- dreamManager, interactionJankMonitor, launchAnimator, isForTesting = true
- )
+ dialogLaunchAnimator =
+ fakeDialogLaunchAnimator(interactionJankMonitor = interactionJankMonitor)
}
@After
@@ -153,6 +149,22 @@
}
@Test
+ fun testActivityLaunchWhenLockedWithoutAlternateAuth() {
+ val dialogLaunchAnimator =
+ fakeDialogLaunchAnimator(isUnlocked = false, isShowingAlternateAuthOnUnlock = false)
+ val dialog = createAndShowDialog(dialogLaunchAnimator)
+ assertNull(dialogLaunchAnimator.createActivityLaunchController(dialog.contentView))
+ }
+
+ @Test
+ fun testActivityLaunchWhenLockedWithAlternateAuth() {
+ val dialogLaunchAnimator =
+ fakeDialogLaunchAnimator(isUnlocked = false, isShowingAlternateAuthOnUnlock = true)
+ val dialog = createAndShowDialog(dialogLaunchAnimator)
+ assertNotNull(dialogLaunchAnimator.createActivityLaunchController(dialog.contentView))
+ }
+
+ @Test
fun testDialogAnimationIsChangedByAnimator() {
// Important: the power menu animation relies on this behavior to know when to animate (see
// http://ag/16774605).
@@ -193,11 +205,13 @@
verify(interactionJankMonitor).end(InteractionJankMonitor.CUJ_USER_DIALOG_OPEN)
}
- private fun createAndShowDialog(): TestDialog {
+ private fun createAndShowDialog(
+ animator: DialogLaunchAnimator = dialogLaunchAnimator,
+ ): TestDialog {
val touchSurface = createTouchSurface()
return runOnMainThreadAndWaitForIdleSync {
val dialog = TestDialog(context)
- dialogLaunchAnimator.showFromView(dialog, touchSurface)
+ animator.showFromView(dialog, touchSurface)
dialog
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/TestValues.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/TestValues.kt
deleted file mode 100644
index dadf94e..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/TestValues.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.android.systemui.animation
-
-/**
- * A [LaunchAnimator.Timings] to be used in tests.
- *
- * Note that all timings except the total duration are non-zero to avoid divide-by-zero exceptions
- * when computing the progress of a sub-animation (the contents fade in/out).
- */
-val TEST_TIMINGS = LaunchAnimator.Timings(
- totalDuration = 0L,
- contentBeforeFadeOutDelay = 1L,
- contentBeforeFadeOutDuration = 1L,
- contentAfterFadeInDelay = 1L,
- contentAfterFadeInDuration = 1L
-)
-
-/** A [LaunchAnimator.Interpolators] to be used in tests. */
-val TEST_INTERPOLATORS = LaunchAnimator.Interpolators(
- positionInterpolator = Interpolators.STANDARD,
- positionXInterpolator = Interpolators.STANDARD,
- contentBeforeFadeOutInterpolator = Interpolators.STANDARD,
- contentAfterFadeInInterpolator = Interpolators.STANDARD
-)
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationUtilsTest.java
index 2915f5a..e099c92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationUtilsTest.java
@@ -20,6 +20,7 @@
import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_CAST_INFO;
import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_DATE;
import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_HOME_CONTROLS;
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_SMARTSPACE;
import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_TIME;
import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_WEATHER;
import static com.android.systemui.dreams.complication.ComplicationUtils.convertComplicationType;
@@ -60,6 +61,8 @@
.isEqualTo(COMPLICATION_TYPE_CAST_INFO);
assertThat(convertComplicationType(DreamBackend.COMPLICATION_TYPE_HOME_CONTROLS))
.isEqualTo(COMPLICATION_TYPE_HOME_CONTROLS);
+ assertThat(convertComplicationType(DreamBackend.COMPLICATION_TYPE_SMARTSPACE))
+ .isEqualTo(COMPLICATION_TYPE_SMARTSPACE);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlags.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlags.kt
index b2a4e33..7b1455c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlags.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlags.kt
@@ -19,7 +19,6 @@
import android.util.SparseArray
import android.util.SparseBooleanArray
import androidx.core.util.containsKey
-import java.lang.IllegalStateException
class FakeFeatureFlags : FeatureFlags {
private val booleanFlags = SparseBooleanArray()
@@ -57,7 +56,10 @@
stringFlags.put(flag.id, value)
}
- override fun isEnabled(flag: BooleanFlag): Boolean = requireBooleanValue(flag.id)
+
+ override fun isEnabled(flag: UnreleasedFlag): Boolean = requireBooleanValue(flag.id)
+
+ override fun isEnabled(flag: ReleasedFlag): Boolean = requireBooleanValue(flag.id)
override fun isEnabled(flag: ResourceBooleanFlag): Boolean = requireBooleanValue(flag.id)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt
index 7d4b4f5..ff579a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FakeFeatureFlagsTest.kt
@@ -29,11 +29,12 @@
@RunWith(AndroidTestingRunner::class)
class FakeFeatureFlagsTest : SysuiTestCase() {
- private val booleanFlag = BooleanFlag(-1000)
- private val stringFlag = StringFlag(-1001)
- private val resourceBooleanFlag = ResourceBooleanFlag(-1002, resourceId = -1)
- private val resourceStringFlag = ResourceStringFlag(-1003, resourceId = -1)
- private val sysPropBooleanFlag = SysPropBooleanFlag(-1004, name = "test")
+ private val unreleasedFlag = UnreleasedFlag(-1000)
+ private val releasedFlag = ReleasedFlag(-1001)
+ private val stringFlag = StringFlag(-1002)
+ private val resourceBooleanFlag = ResourceBooleanFlag(-1003, resourceId = -1)
+ private val resourceStringFlag = ResourceStringFlag(-1004, resourceId = -1)
+ private val sysPropBooleanFlag = SysPropBooleanFlag(-1005, name = "test")
/**
* FakeFeatureFlags does not honor any default values. All flags which are accessed must be
@@ -49,56 +50,66 @@
assertThat(ex.message).contains("TEAMFOOD")
}
try {
- assertThat(flags.isEnabled(booleanFlag)).isFalse()
+ assertThat(flags.isEnabled(unreleasedFlag)).isFalse()
fail("Expected an exception when accessing an unspecified flag.")
} catch (ex: IllegalStateException) {
assertThat(ex.message).contains("UNKNOWN(id=-1000)")
}
try {
- assertThat(flags.isEnabled(resourceBooleanFlag)).isFalse()
- fail("Expected an exception when accessing an unspecified flag.")
- } catch (ex: IllegalStateException) {
- assertThat(ex.message).contains("UNKNOWN(id=-1002)")
- }
- try {
- assertThat(flags.isEnabled(sysPropBooleanFlag)).isFalse()
- fail("Expected an exception when accessing an unspecified flag.")
- } catch (ex: IllegalStateException) {
- assertThat(ex.message).contains("UNKNOWN(id=-1004)")
- }
- try {
- assertThat(flags.getString(stringFlag)).isEmpty()
+ assertThat(flags.isEnabled(releasedFlag)).isFalse()
fail("Expected an exception when accessing an unspecified flag.")
} catch (ex: IllegalStateException) {
assertThat(ex.message).contains("UNKNOWN(id=-1001)")
}
try {
- assertThat(flags.getString(resourceStringFlag)).isEmpty()
+ assertThat(flags.isEnabled(resourceBooleanFlag)).isFalse()
fail("Expected an exception when accessing an unspecified flag.")
} catch (ex: IllegalStateException) {
assertThat(ex.message).contains("UNKNOWN(id=-1003)")
}
+ try {
+ assertThat(flags.isEnabled(sysPropBooleanFlag)).isFalse()
+ fail("Expected an exception when accessing an unspecified flag.")
+ } catch (ex: IllegalStateException) {
+ assertThat(ex.message).contains("UNKNOWN(id=-1005)")
+ }
+ try {
+ assertThat(flags.getString(stringFlag)).isEmpty()
+ fail("Expected an exception when accessing an unspecified flag.")
+ } catch (ex: IllegalStateException) {
+ assertThat(ex.message).contains("UNKNOWN(id=-1002)")
+ }
+ try {
+ assertThat(flags.getString(resourceStringFlag)).isEmpty()
+ fail("Expected an exception when accessing an unspecified flag.")
+ } catch (ex: IllegalStateException) {
+ assertThat(ex.message).contains("UNKNOWN(id=-1004)")
+ }
}
@Test
fun specifiedFlagsReturnCorrectValues() {
val flags = FakeFeatureFlags()
- flags.set(booleanFlag, false)
+ flags.set(unreleasedFlag, false)
+ flags.set(releasedFlag, false)
flags.set(resourceBooleanFlag, false)
flags.set(sysPropBooleanFlag, false)
flags.set(resourceStringFlag, "")
- assertThat(flags.isEnabled(booleanFlag)).isFalse()
+ assertThat(flags.isEnabled(unreleasedFlag)).isFalse()
+ assertThat(flags.isEnabled(releasedFlag)).isFalse()
assertThat(flags.isEnabled(resourceBooleanFlag)).isFalse()
assertThat(flags.isEnabled(sysPropBooleanFlag)).isFalse()
assertThat(flags.getString(resourceStringFlag)).isEmpty()
- flags.set(booleanFlag, true)
+ flags.set(unreleasedFlag, true)
+ flags.set(releasedFlag, true)
flags.set(resourceBooleanFlag, true)
flags.set(sysPropBooleanFlag, true)
flags.set(resourceStringFlag, "Android")
- assertThat(flags.isEnabled(booleanFlag)).isTrue()
+ assertThat(flags.isEnabled(unreleasedFlag)).isTrue()
+ assertThat(flags.isEnabled(releasedFlag)).isTrue()
assertThat(flags.isEnabled(resourceBooleanFlag)).isTrue()
assertThat(flags.isEnabled(sysPropBooleanFlag)).isTrue()
assertThat(flags.getString(resourceStringFlag)).isEqualTo("Android")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
index 51f3404..4511193 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
@@ -35,6 +35,10 @@
import com.android.systemui.util.mockito.withArgCaptor
import com.android.systemui.util.settings.SecureSettings
import com.google.common.truth.Truth.assertThat
+import java.io.PrintWriter
+import java.io.Serializable
+import java.io.StringWriter
+import java.util.function.Consumer
import org.junit.Assert
import org.junit.Before
import org.junit.Test
@@ -48,12 +52,8 @@
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.MockitoAnnotations
-import java.io.PrintWriter
-import java.io.Serializable
-import java.io.StringWriter
-import java.util.function.Consumer
import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
/**
* NOTE: This test is for the version of FeatureFlagManager in src-release, which should not allow
@@ -75,10 +75,11 @@
private val flagMap = mutableMapOf<Int, Flag<*>>()
private lateinit var broadcastReceiver: BroadcastReceiver
private lateinit var clearCacheAction: Consumer<Int>
+ private val serverFlagReader = ServerFlagReaderFake()
private val deviceConfig = DeviceConfigProxyFake()
- private val teamfoodableFlagA = BooleanFlag(500, false, true)
- private val teamfoodableFlagB = BooleanFlag(501, true, true)
+ private val teamfoodableFlagA = UnreleasedFlag(500, true)
+ private val teamfoodableFlagB = ReleasedFlag(501, true)
@Before
fun setup() {
@@ -93,6 +94,7 @@
resources,
dumpManager,
deviceConfig,
+ serverFlagReader,
flagMap,
commandRegistry,
barService
@@ -109,40 +111,41 @@
}
@Test
- fun testReadBooleanFlag() {
+ fun readBooleanFlag() {
// Remember that the TEAMFOOD flag is id#1 and has special behavior.
whenever(flagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true)
whenever(flagManager.readFlagValue<Boolean>(eq(4), any())).thenReturn(false)
- assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(2, true))).isTrue()
- assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(3, false))).isTrue()
- assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(4, true))).isFalse()
- assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(5, false))).isFalse()
+
+ assertThat(mFeatureFlagsDebug.isEnabled(ReleasedFlag(2))).isTrue()
+ assertThat(mFeatureFlagsDebug.isEnabled(UnreleasedFlag(3))).isTrue()
+ assertThat(mFeatureFlagsDebug.isEnabled(ReleasedFlag(4))).isFalse()
+ assertThat(mFeatureFlagsDebug.isEnabled(UnreleasedFlag(5))).isFalse()
}
@Test
- fun testTeamFoodFlag_False() {
+ fun teamFoodFlag_False() {
whenever(flagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(false)
assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isFalse()
assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isTrue()
// Regular boolean flags should still test the same.
// Only our teamfoodableFlag should change.
- testReadBooleanFlag()
+ readBooleanFlag()
}
@Test
- fun testTeamFoodFlag_True() {
+ fun teamFoodFlag_True() {
whenever(flagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true)
assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isTrue()
assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isTrue()
// Regular boolean flags should still test the same.
// Only our teamfoodableFlag should change.
- testReadBooleanFlag()
+ readBooleanFlag()
}
@Test
- fun testTeamFoodFlag_Overridden() {
+ fun teamFoodFlag_Overridden() {
whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagA.id), any()))
.thenReturn(true)
whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagB.id), any()))
@@ -153,11 +156,11 @@
// Regular boolean flags should still test the same.
// Only our teamfoodableFlag should change.
- testReadBooleanFlag()
+ readBooleanFlag()
}
@Test
- fun testReadResourceBooleanFlag() {
+ fun readResourceBooleanFlag() {
whenever(resources.getBoolean(1001)).thenReturn(false)
whenever(resources.getBoolean(1002)).thenReturn(true)
whenever(resources.getBoolean(1003)).thenReturn(false)
@@ -182,7 +185,7 @@
}
@Test
- fun testReadSysPropBooleanFlag() {
+ fun readSysPropBooleanFlag() {
whenever(systemProperties.getBoolean(anyString(), anyBoolean())).thenAnswer {
if ("b".equals(it.getArgument<String?>(0))) {
return@thenAnswer true
@@ -198,7 +201,7 @@
}
@Test
- fun testReadDeviceConfigBooleanFlag() {
+ fun readDeviceConfigBooleanFlag() {
val namespace = "test_namespace"
deviceConfig.setProperty(namespace, "a", "true", false)
deviceConfig.setProperty(namespace, "b", "false", false)
@@ -213,7 +216,7 @@
}
@Test
- fun testReadStringFlag() {
+ fun readStringFlag() {
whenever(flagManager.readFlagValue<String>(eq(3), any())).thenReturn("foo")
whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("bar")
assertThat(mFeatureFlagsDebug.getString(StringFlag(1, "biz"))).isEqualTo("biz")
@@ -223,7 +226,7 @@
}
@Test
- fun testReadResourceStringFlag() {
+ fun readResourceStringFlag() {
whenever(resources.getString(1001)).thenReturn("")
whenever(resources.getString(1002)).thenReturn("resource2")
whenever(resources.getString(1003)).thenReturn("resource3")
@@ -253,8 +256,8 @@
}
@Test
- fun testBroadcastReceiverIgnoresInvalidData() {
- addFlag(BooleanFlag(1, false))
+ fun broadcastReceiver_IgnoresInvalidData() {
+ addFlag(UnreleasedFlag(1))
addFlag(ResourceBooleanFlag(2, 1002))
addFlag(StringFlag(3, "flag3"))
addFlag(ResourceStringFlag(4, 1004))
@@ -272,10 +275,10 @@
}
@Test
- fun testIntentWithIdButNoValueKeyClears() {
- addFlag(BooleanFlag(1, false))
+ fun intentWithId_NoValueKeyClears() {
+ addFlag(UnreleasedFlag(1))
- // trying to erase an id not in the map does noting
+ // trying to erase an id not in the map does nothing
broadcastReceiver.onReceive(
mockContext,
Intent(FlagManager.ACTION_SET_FLAG).putExtra(FlagManager.EXTRA_ID, 0)
@@ -291,9 +294,9 @@
}
@Test
- fun testSetBooleanFlag() {
- addFlag(BooleanFlag(1, false))
- addFlag(BooleanFlag(2, false))
+ fun setBooleanFlag() {
+ addFlag(UnreleasedFlag(1))
+ addFlag(UnreleasedFlag(2))
addFlag(ResourceBooleanFlag(3, 1003))
addFlag(ResourceBooleanFlag(4, 1004))
@@ -311,7 +314,7 @@
}
@Test
- fun testSetStringFlag() {
+ fun setStringFlag() {
addFlag(StringFlag(1, "flag1"))
addFlag(ResourceStringFlag(2, 1002))
@@ -323,7 +326,7 @@
}
@Test
- fun testSetFlagClearsCache() {
+ fun setFlag_ClearsCache() {
val flag1 = addFlag(StringFlag(1, "flag1"))
whenever(flagManager.readFlagValue<String>(eq(1), any())).thenReturn("original")
@@ -345,12 +348,30 @@
}
@Test
- fun testRegisterCommand() {
+ fun serverSide_Overrides_MakesFalse() {
+ val flag = ReleasedFlag(100)
+
+ serverFlagReader.setFlagValue(flag.id, false)
+
+ assertThat(mFeatureFlagsDebug.isEnabled(flag)).isFalse()
+ }
+
+ @Test
+ fun serverSide_Overrides_MakesTrue() {
+ val flag = UnreleasedFlag(100)
+
+ serverFlagReader.setFlagValue(flag.id, true)
+
+ assertThat(mFeatureFlagsDebug.isEnabled(flag)).isTrue()
+ }
+
+ @Test
+ fun statusBarCommand_IsRegistered() {
verify(commandRegistry).registerCommand(anyString(), any())
}
@Test
- fun testNoOpCommand() {
+ fun noOpCommand() {
val cmd = captureCommand()
cmd.execute(pw, ArrayList())
@@ -360,37 +381,73 @@
}
@Test
- fun testReadFlagCommand() {
- addFlag(BooleanFlag(1, false))
+ fun readFlagCommand() {
+ addFlag(UnreleasedFlag(1))
val cmd = captureCommand()
cmd.execute(pw, listOf("1"))
verify(flagManager).readFlagValue<Boolean>(eq(1), any())
}
@Test
- fun testSetFlagCommand() {
- addFlag(BooleanFlag(1, false))
+ fun setFlagCommand() {
+ addFlag(UnreleasedFlag(1))
val cmd = captureCommand()
cmd.execute(pw, listOf("1", "on"))
verifyPutData(1, "{\"type\":\"boolean\",\"value\":true}")
}
@Test
- fun testToggleFlagCommand() {
- addFlag(BooleanFlag(1, true))
+ fun toggleFlagCommand() {
+ addFlag(ReleasedFlag(1))
val cmd = captureCommand()
cmd.execute(pw, listOf("1", "toggle"))
verifyPutData(1, "{\"type\":\"boolean\",\"value\":false}", 2)
}
@Test
- fun testEraseFlagCommand() {
- addFlag(BooleanFlag(1, true))
+ fun eraseFlagCommand() {
+ addFlag(ReleasedFlag(1))
val cmd = captureCommand()
cmd.execute(pw, listOf("1", "erase"))
verify(secureSettings).putStringForUser(eq("key-1"), eq(""), anyInt())
}
+ @Test
+ fun dumpFormat() {
+ val flag1 = ReleasedFlag(1)
+ val flag2 = ResourceBooleanFlag(2, 1002)
+ val flag3 = UnreleasedFlag(3)
+ val flag4 = StringFlag(4, "")
+ val flag5 = StringFlag(5, "flag5default")
+ val flag6 = ResourceStringFlag(6, 1006)
+ val flag7 = ResourceStringFlag(7, 1007)
+
+ whenever(resources.getBoolean(1002)).thenReturn(true)
+ whenever(resources.getString(1006)).thenReturn("resource1006")
+ whenever(resources.getString(1007)).thenReturn("resource1007")
+ whenever(flagManager.readFlagValue(eq(7), eq(StringFlagSerializer)))
+ .thenReturn("override7")
+
+ // WHEN the flags have been accessed
+ assertThat(mFeatureFlagsDebug.isEnabled(flag1)).isTrue()
+ assertThat(mFeatureFlagsDebug.isEnabled(flag2)).isTrue()
+ assertThat(mFeatureFlagsDebug.isEnabled(flag3)).isFalse()
+ assertThat(mFeatureFlagsDebug.getString(flag4)).isEmpty()
+ assertThat(mFeatureFlagsDebug.getString(flag5)).isEqualTo("flag5default")
+ assertThat(mFeatureFlagsDebug.getString(flag6)).isEqualTo("resource1006")
+ assertThat(mFeatureFlagsDebug.getString(flag7)).isEqualTo("override7")
+
+ // THEN the dump contains the flags and the default values
+ val dump = dumpToString()
+ assertThat(dump).contains(" sysui_flag_1: true\n")
+ assertThat(dump).contains(" sysui_flag_2: true\n")
+ assertThat(dump).contains(" sysui_flag_3: false\n")
+ assertThat(dump).contains(" sysui_flag_4: [length=0] \"\"\n")
+ assertThat(dump).contains(" sysui_flag_5: [length=12] \"flag5default\"\n")
+ assertThat(dump).contains(" sysui_flag_6: [length=12] \"resource1006\"\n")
+ assertThat(dump).contains(" sysui_flag_7: [length=9] \"override7\"\n")
+ }
+
private fun verifyPutData(id: Int, data: String, numReads: Int = 1) {
inOrder(flagManager, secureSettings).apply {
verify(flagManager, times(numReads)).readFlagValue(eq(id), any<FlagSerializer<*>>())
@@ -421,42 +478,6 @@
return captor.value.invoke()
}
- @Test
- fun testDump() {
- val flag1 = BooleanFlag(1, true)
- val flag2 = ResourceBooleanFlag(2, 1002)
- val flag3 = BooleanFlag(3, false)
- val flag4 = StringFlag(4, "")
- val flag5 = StringFlag(5, "flag5default")
- val flag6 = ResourceStringFlag(6, 1006)
- val flag7 = ResourceStringFlag(7, 1007)
-
- whenever(resources.getBoolean(1002)).thenReturn(true)
- whenever(resources.getString(1006)).thenReturn("resource1006")
- whenever(resources.getString(1007)).thenReturn("resource1007")
- whenever(flagManager.readFlagValue(eq(7), eq(StringFlagSerializer)))
- .thenReturn("override7")
-
- // WHEN the flags have been accessed
- assertThat(mFeatureFlagsDebug.isEnabled(flag1)).isTrue()
- assertThat(mFeatureFlagsDebug.isEnabled(flag2)).isTrue()
- assertThat(mFeatureFlagsDebug.isEnabled(flag3)).isFalse()
- assertThat(mFeatureFlagsDebug.getString(flag4)).isEmpty()
- assertThat(mFeatureFlagsDebug.getString(flag5)).isEqualTo("flag5default")
- assertThat(mFeatureFlagsDebug.getString(flag6)).isEqualTo("resource1006")
- assertThat(mFeatureFlagsDebug.getString(flag7)).isEqualTo("override7")
-
- // THEN the dump contains the flags and the default values
- val dump = dumpToString()
- assertThat(dump).contains(" sysui_flag_1: true\n")
- assertThat(dump).contains(" sysui_flag_2: true\n")
- assertThat(dump).contains(" sysui_flag_3: false\n")
- assertThat(dump).contains(" sysui_flag_4: [length=0] \"\"\n")
- assertThat(dump).contains(" sysui_flag_5: [length=12] \"flag5default\"\n")
- assertThat(dump).contains(" sysui_flag_6: [length=12] \"resource1006\"\n")
- assertThat(dump).contains(" sysui_flag_7: [length=9] \"override7\"\n")
- }
-
private fun dumpToString(): String {
val sw = StringWriter()
val pw = PrintWriter(sw)
@@ -464,4 +485,4 @@
pw.flush()
return sw.toString()
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
index 6b683f4..e94b520 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
@@ -30,8 +30,8 @@
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.MockitoAnnotations
import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
/**
* NOTE: This test is for the version of FeatureFlagManager in src-release, which should not allow
@@ -44,13 +44,18 @@
@Mock private lateinit var mResources: Resources
@Mock private lateinit var mSystemProperties: SystemPropertiesHelper
@Mock private lateinit var mDumpManager: DumpManager
+ private val serverFlagReader = ServerFlagReaderFake()
private val deviceConfig = DeviceConfigProxyFake()
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- mFeatureFlagsRelease = FeatureFlagsRelease(mResources, mSystemProperties, deviceConfig,
+ mFeatureFlagsRelease = FeatureFlagsRelease(
+ mResources,
+ mSystemProperties,
+ deviceConfig,
+ serverFlagReader,
mDumpManager)
}
@@ -113,4 +118,22 @@
whenever(mSystemProperties.getBoolean(flagName, flagDefault)).thenReturn(flagDefault)
assertThat(mFeatureFlagsRelease.isEnabled(flag)).isEqualTo(flagDefault)
}
-}
\ No newline at end of file
+
+ @Test
+ fun serverSide_OverridesReleased_MakesFalse() {
+ val flag = ReleasedFlag(100)
+
+ serverFlagReader.setFlagValue(flag.id, false)
+
+ assertThat(mFeatureFlagsRelease.isEnabled(flag)).isFalse()
+ }
+
+ @Test
+ fun serverSide_OverridesUnreleased_Ignored() {
+ val flag = UnreleasedFlag(100)
+
+ serverFlagReader.setFlagValue(flag.id, true)
+
+ assertThat(mFeatureFlagsRelease.isEnabled(flag)).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
index a2eca81..17324a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
@@ -26,6 +26,7 @@
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.withArgCaptor
import com.google.common.truth.Truth.assertThat
+import java.util.function.Consumer
import org.junit.Assert.assertThrows
import org.junit.Before
import org.junit.Test
@@ -33,9 +34,8 @@
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.MockitoAnnotations
-import java.util.function.Consumer
import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
/**
* NOTE: This test is for the version of FeatureFlagManager in src-release, which should not allow
@@ -64,14 +64,14 @@
verifyNoMoreInteractions(mFlagSettingsHelper)
// adding the first listener registers the observer
- mFlagManager.addListener(BooleanFlag(1, true), listener1)
+ mFlagManager.addListener(ReleasedFlag(1), listener1)
val observer = withArgCaptor<ContentObserver> {
verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture())
}
verifyNoMoreInteractions(mFlagSettingsHelper)
// adding another listener does nothing
- mFlagManager.addListener(BooleanFlag(2, true), listener2)
+ mFlagManager.addListener(ReleasedFlag(2), listener2)
verifyNoMoreInteractions(mFlagSettingsHelper)
// removing the original listener does nothing with second one still present
@@ -89,7 +89,7 @@
val listener = mock<FlagListenable.Listener>()
val clearCacheAction = mock<Consumer<Int>>()
mFlagManager.clearCacheAction = clearCacheAction
- mFlagManager.addListener(BooleanFlag(1, true), listener)
+ mFlagManager.addListener(ReleasedFlag(1), listener)
val observer = withArgCaptor<ContentObserver> {
verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture())
}
@@ -101,8 +101,8 @@
fun testObserverInvokesListeners() {
val listener1 = mock<FlagListenable.Listener>()
val listener10 = mock<FlagListenable.Listener>()
- mFlagManager.addListener(BooleanFlag(1, true), listener1)
- mFlagManager.addListener(BooleanFlag(10, true), listener10)
+ mFlagManager.addListener(ReleasedFlag(1), listener1)
+ mFlagManager.addListener(ReleasedFlag(10), listener10)
val observer = withArgCaptor<ContentObserver> {
verify(mFlagSettingsHelper).registerContentObserver(any(), any(), capture())
}
@@ -127,8 +127,8 @@
fun testOnlySpecificFlagListenerIsInvoked() {
val listener1 = mock<FlagListenable.Listener>()
val listener10 = mock<FlagListenable.Listener>()
- mFlagManager.addListener(BooleanFlag(1, true), listener1)
- mFlagManager.addListener(BooleanFlag(10, true), listener10)
+ mFlagManager.addListener(ReleasedFlag(1), listener1)
+ mFlagManager.addListener(ReleasedFlag(10), listener10)
mFlagManager.dispatchListenersAndMaybeRestart(1, null)
val flagEvent1 = withArgCaptor<FlagListenable.FlagEvent> {
@@ -148,8 +148,8 @@
@Test
fun testSameListenerCanBeUsedForMultipleFlags() {
val listener = mock<FlagListenable.Listener>()
- mFlagManager.addListener(BooleanFlag(1, true), listener)
- mFlagManager.addListener(BooleanFlag(10, true), listener)
+ mFlagManager.addListener(ReleasedFlag(1), listener)
+ mFlagManager.addListener(ReleasedFlag(10), listener)
mFlagManager.dispatchListenersAndMaybeRestart(1, null)
val flagEvent1 = withArgCaptor<FlagListenable.FlagEvent> {
@@ -177,7 +177,7 @@
@Test
fun testListenerCanSuppressRestart() {
val restartAction = mock<Consumer<Boolean>>()
- mFlagManager.addListener(BooleanFlag(1, true)) { event ->
+ mFlagManager.addListener(ReleasedFlag(1)) { event ->
event.requestNoRestart()
}
mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction)
@@ -188,7 +188,7 @@
@Test
fun testListenerOnlySuppressesRestartForOwnFlag() {
val restartAction = mock<Consumer<Boolean>>()
- mFlagManager.addListener(BooleanFlag(10, true)) { event ->
+ mFlagManager.addListener(ReleasedFlag(10)) { event ->
event.requestNoRestart()
}
mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction)
@@ -199,10 +199,10 @@
@Test
fun testRestartWhenNotAllListenersRequestSuppress() {
val restartAction = mock<Consumer<Boolean>>()
- mFlagManager.addListener(BooleanFlag(10, true)) { event ->
+ mFlagManager.addListener(ReleasedFlag(10)) { event ->
event.requestNoRestart()
}
- mFlagManager.addListener(BooleanFlag(10, true)) {
+ mFlagManager.addListener(ReleasedFlag(10)) {
// do not request
}
mFlagManager.dispatchListenersAndMaybeRestart(1, restartAction)
@@ -295,4 +295,4 @@
assertThat(StringFlagSerializer.toSettingsData("foo"))
.isEqualTo("{\"type\":\"string\",\"value\":\"foo\"}")
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.java b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.java
index 25c3028..250cc48 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FlagsTest.java
@@ -107,11 +107,11 @@
}
private static class DuplicateFlagContainer {
- public static final BooleanFlag A_FLAG = new BooleanFlag(0);
- public static final BooleanFlag B_FLAG = new BooleanFlag(0);
+ public static final BooleanFlag A_FLAG = new UnreleasedFlag(0);
+ public static final BooleanFlag B_FLAG = new UnreleasedFlag(0);
public static final StringFlag C_FLAG = new StringFlag(0);
- public static final BooleanFlag D_FLAG = new BooleanFlag(1);
+ public static final BooleanFlag D_FLAG = new UnreleasedFlag(1);
public static final DoubleFlag E_FLAG = new DoubleFlag(3);
public static final DoubleFlag F_FLAG = new DoubleFlag(3);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
index 4abb973..56aff3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
@@ -24,16 +24,11 @@
@Before
fun setup() {
outputWriter = StringWriter()
- buffer = createBuffer(UNBOUNDED_STACK_TRACE, NESTED_TRACE_DEPTH)
+ buffer = createBuffer()
}
- private fun createBuffer(rootTraceDepth: Int, nestedTraceDepth: Int): LogBuffer {
- return LogBuffer("TestBuffer",
- 1,
- logcatEchoTracker,
- false,
- rootStackTraceDepth = rootTraceDepth,
- nestedStackTraceDepth = nestedTraceDepth)
+ private fun createBuffer(): LogBuffer {
+ return LogBuffer("TestBuffer", 1, logcatEchoTracker, false)
}
@Test
@@ -56,95 +51,83 @@
}
@Test
- fun dump_writesExceptionAndStacktraceLimitedToGivenDepth() {
- buffer = createBuffer(rootTraceDepth = 2, nestedTraceDepth = -1)
- // stack trace depth of 5
- val exception = createTestException("Exception message", "TestClass", 5)
+ fun dump_writesExceptionAndStacktrace() {
+ buffer = createBuffer()
+ val exception = createTestException("Exception message", "TestClass")
buffer.log("Tag", LogLevel.ERROR, { str1 = "Extra message" }, { str1!! }, exception)
val dumpedString = dumpBuffer()
- // logs are limited to depth 2
- assertThat(dumpedString).contains("E Tag: Extra message")
- assertThat(dumpedString).contains("E Tag: java.lang.RuntimeException: Exception message")
- assertThat(dumpedString).contains("E Tag: \tat TestClass.TestMethod(TestClass.java:1)")
- assertThat(dumpedString).contains("E Tag: \tat TestClass.TestMethod(TestClass.java:2)")
- assertThat(dumpedString)
- .doesNotContain("E Tag: \tat TestClass.TestMethod(TestClass.java:3)")
+ assertThat(dumpedString).contains("Extra message")
+ assertThat(dumpedString).contains("java.lang.RuntimeException: Exception message")
+ assertThat(dumpedString).contains("at TestClass.TestMethod(TestClass.java:1)")
+ assertThat(dumpedString).contains("at TestClass.TestMethod(TestClass.java:2)")
}
@Test
- fun dump_writesCauseAndStacktraceLimitedToGivenDepth() {
- buffer = createBuffer(rootTraceDepth = 0, nestedTraceDepth = 2)
+ fun dump_writesCauseAndStacktrace() {
+ buffer = createBuffer()
val exception = createTestException("Exception message",
"TestClass",
- 1,
- cause = createTestException("The real cause!", "TestClass", 5))
+ cause = createTestException("The real cause!", "TestClass"))
buffer.log("Tag", LogLevel.ERROR, { str1 = "Extra message" }, { str1!! }, exception)
val dumpedString = dumpBuffer()
- // logs are limited to depth 2
assertThat(dumpedString)
- .contains("E Tag: Caused by: java.lang.RuntimeException: The real cause!")
- assertThat(dumpedString).contains("E Tag: \tat TestClass.TestMethod(TestClass.java:1)")
- assertThat(dumpedString).contains("E Tag: \tat TestClass.TestMethod(TestClass.java:2)")
- assertThat(dumpedString)
- .doesNotContain("E Tag: \tat TestClass.TestMethod(TestClass.java:3)")
+ .contains("Caused by: java.lang.RuntimeException: The real cause!")
+ assertThat(dumpedString).contains("at TestClass.TestMethod(TestClass.java:1)")
+ assertThat(dumpedString).contains("at TestClass.TestMethod(TestClass.java:2)")
}
@Test
- fun dump_writesSuppressedExceptionAndStacktraceLimitedToGivenDepth() {
- buffer = createBuffer(rootTraceDepth = 0, nestedTraceDepth = 2)
+ fun dump_writesSuppressedExceptionAndStacktrace() {
+ buffer = createBuffer()
val exception = RuntimeException("Root exception message")
exception.addSuppressed(
createTestException(
"First suppressed exception",
"FirstClass",
- 5,
- createTestException("Cause of suppressed exp", "ThirdClass", 5)
+ createTestException("Cause of suppressed exp", "ThirdClass")
))
exception.addSuppressed(
- createTestException("Second suppressed exception", "SecondClass", 5))
+ createTestException("Second suppressed exception", "SecondClass"))
buffer.log("Tag", LogLevel.ERROR, { str1 = "Extra message" }, { str1!! }, exception)
val dumpedStr = dumpBuffer()
- // logs are limited to depth 2
// first suppressed exception
assertThat(dumpedStr)
- .contains("E Tag: Suppressed: " +
+ .contains("Suppressed: " +
"java.lang.RuntimeException: First suppressed exception")
- assertThat(dumpedStr).contains("E Tag: \tat FirstClass.TestMethod(FirstClass.java:1)")
- assertThat(dumpedStr).contains("E Tag: \tat FirstClass.TestMethod(FirstClass.java:2)")
- assertThat(dumpedStr)
- .doesNotContain("E Tag: \tat FirstClass.TestMethod(FirstClass.java:3)")
+ assertThat(dumpedStr).contains("at FirstClass.TestMethod(FirstClass.java:1)")
+ assertThat(dumpedStr).contains("at FirstClass.TestMethod(FirstClass.java:2)")
assertThat(dumpedStr)
- .contains("E Tag: Caused by: java.lang.RuntimeException: Cause of suppressed exp")
- assertThat(dumpedStr).contains("E Tag: \tat ThirdClass.TestMethod(ThirdClass.java:1)")
- assertThat(dumpedStr).contains("E Tag: \tat ThirdClass.TestMethod(ThirdClass.java:2)")
- assertThat(dumpedStr)
- .doesNotContain("E Tag: \tat ThirdClass.TestMethod(ThirdClass.java:3)")
+ .contains("Caused by: java.lang.RuntimeException: Cause of suppressed exp")
+ assertThat(dumpedStr).contains("at ThirdClass.TestMethod(ThirdClass.java:1)")
+ assertThat(dumpedStr).contains("at ThirdClass.TestMethod(ThirdClass.java:2)")
// second suppressed exception
assertThat(dumpedStr)
- .contains("E Tag: Suppressed: " +
+ .contains("Suppressed: " +
"java.lang.RuntimeException: Second suppressed exception")
- assertThat(dumpedStr).contains("E Tag: \tat SecondClass.TestMethod(SecondClass.java:1)")
- assertThat(dumpedStr).contains("E Tag: \tat SecondClass.TestMethod(SecondClass.java:2)")
- assertThat(dumpedStr)
- .doesNotContain("E Tag: \tat SecondClass.TestMethod(SecondClass.java:3)")
+ assertThat(dumpedStr).contains("at SecondClass.TestMethod(SecondClass.java:1)")
+ assertThat(dumpedStr).contains("at SecondClass.TestMethod(SecondClass.java:2)")
}
private fun createTestException(
- message: String,
- errorClass: String,
- stackTraceLength: Int,
- cause: Throwable? = null
+ message: String,
+ errorClass: String,
+ cause: Throwable? = null,
): Exception {
val exception = RuntimeException(message, cause)
- exception.stackTrace = createStackTraceElements(errorClass, stackTraceLength)
+ exception.stackTrace = (1..5).map { lineNumber ->
+ StackTraceElement(errorClass,
+ "TestMethod",
+ "$errorClass.java",
+ lineNumber)
+ }.toTypedArray()
return exception
}
@@ -152,16 +135,4 @@
buffer.dump(PrintWriter(outputWriter), tailLength = 100)
return outputWriter.toString()
}
-
- private fun createStackTraceElements(
- errorClass: String,
- stackTraceLength: Int
- ): Array<StackTraceElement> {
- return (1..stackTraceLength).map { lineNumber ->
- StackTraceElement(errorClass,
- "TestMethod",
- "$errorClass.java",
- lineNumber)
- }.toTypedArray()
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
index 3d3ac83..83168cb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
@@ -305,7 +305,7 @@
// Then we save an update with the current time
verify(sharedPrefsEditor).putString(any(), (capture(componentCaptor)))
componentCaptor.value.split(ResumeMediaBrowser.DELIMITER.toRegex())
- ?.dropLastWhile { it.isEmpty() }.forEach {
+ .dropLastWhile { it.isEmpty() }.forEach {
val result = it.split("/")
assertThat(result.size).isEqualTo(3)
assertThat(result[2].toLong()).isEqualTo(currentTime)
@@ -392,7 +392,7 @@
// Then we store the new lastPlayed time
verify(sharedPrefsEditor).putString(any(), (capture(componentCaptor)))
componentCaptor.value.split(ResumeMediaBrowser.DELIMITER.toRegex())
- ?.dropLastWhile { it.isEmpty() }.forEach {
+ .dropLastWhile { it.isEmpty() }.forEach {
val result = it.split("/")
assertThat(result.size).isEqualTo(3)
assertThat(result[2].toLong()).isEqualTo(currentTime)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenTargetFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
similarity index 93%
rename from packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenTargetFilterTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
index 185a838..6b34ca7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenTargetFilterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
@@ -27,13 +27,14 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.UserTracker
-import com.android.systemui.smartspace.filters.LockscreenTargetFilter
+import com.android.systemui.smartspace.filters.LockscreenAndDreamTargetFilter
import com.android.systemui.util.concurrency.Execution
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.withArgCaptor
import com.android.systemui.util.settings.SecureSettings
import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.Executor
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -41,18 +42,17 @@
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.atLeast
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
-import java.util.concurrent.Executor
@SmallTest
@TestableLooper.RunWithLooper
@RunWith(AndroidTestingRunner::class)
-class LockscreenTargetFilterTest : SysuiTestCase() {
+class LockscreenAndDreamTargetFilterTest : SysuiTestCase() {
@Mock
private lateinit var secureSettings: SecureSettings
@@ -99,7 +99,7 @@
`when`(secureSettings
.getIntForUser(eq(setting) ?: setting, anyInt(), anyInt()))
.thenReturn(0)
- var filter = LockscreenTargetFilter(secureSettings, userTracker, execution, handler,
+ var filter = LockscreenAndDreamTargetFilter(secureSettings, userTracker, execution, handler,
contentResolver, uiExecution)
filter.addListener(listener)
@@ -132,7 +132,7 @@
`when`(secureSettings
.getIntForUser(eq(setting) ?: setting, anyInt(), anyInt()))
.thenReturn(0)
- var filter = LockscreenTargetFilter(secureSettings, userTracker, execution, handler,
+ var filter = LockscreenAndDreamTargetFilter(secureSettings, userTracker, execution, handler,
contentResolver, uiExecution)
filter.addListener(listener)
@@ -146,4 +146,4 @@
verify(listener).onCriteriaChanged()
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index fee17c7..18acf3f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -33,6 +33,7 @@
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.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -621,7 +622,7 @@
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
// Send update
- mEntryListener.onEntryUpdated(mRow);
+ mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ true);
// Nothing should have changed
// Notif is suppressed after expansion
@@ -789,7 +790,7 @@
@Test
public void testAddNotif_notBubble() {
mEntryListener.onEntryAdded(mNonBubbleNotifRow.getEntry());
- mEntryListener.onEntryUpdated(mNonBubbleNotifRow.getEntry());
+ mEntryListener.onEntryUpdated(mNonBubbleNotifRow.getEntry(), /* fromSystem= */ true);
assertThat(mBubbleController.hasBubbles()).isFalse();
}
@@ -827,7 +828,7 @@
NotificationListenerService.Ranking ranking = new RankingBuilder(
mRow.getRanking()).setCanBubble(false).build();
mRow.setRanking(ranking);
- mEntryListener.onEntryUpdated(mRow);
+ mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ true);
assertFalse(mBubbleController.hasBubbles());
verify(mDeleteIntent, never()).send();
@@ -1432,6 +1433,100 @@
assertThat(mBubbleData.hasBubbleInStackWithKey(mBubbleEntry.getKey())).isFalse();
}
+ /**
+ * Verifies that if a bubble is in the overflow and a non-interruptive notification update
+ * comes in for it, it stays in the overflow but the entry is updated.
+ */
+ @Test
+ public void testNonInterruptiveUpdate_doesntBubbleFromOverflow() {
+ mEntryListener.onEntryAdded(mRow);
+ mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ true);
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
+
+ // Dismiss the bubble so it's in the overflow
+ mBubbleController.removeBubble(
+ mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
+ assertThat(mBubbleData.hasOverflowBubbleWithKey(mRow.getKey())).isTrue();
+
+ // Update the entry to not show in shade
+ setMetadataFlags(mRow,
+ Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION, /* enableFlag= */ true);
+ mBubbleController.updateBubble(mBubbleEntry,
+ /* suppressFlyout= */ false, /* showInShade= */ true);
+
+ // Check that the update was applied - shouldn't be show in shade
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
+ // Check that it wasn't inflated (1 because it would've been inflated via onEntryAdded)
+ verify(mBubbleController, times(1)).inflateAndAdd(
+ any(Bubble.class), anyBoolean(), anyBoolean());
+ }
+
+ /**
+ * Verifies that if a bubble is active, and a non-interruptive notification update comes in for
+ * it, it doesn't trigger a new inflate and add for that bubble.
+ */
+ @Test
+ public void testNonInterruptiveUpdate_doesntTriggerInflate() {
+ mEntryListener.onEntryAdded(mRow);
+ mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ true);
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
+
+ // Update the entry to not show in shade
+ setMetadataFlags(mRow,
+ Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION, /* enableFlag= */ true);
+ mBubbleController.updateBubble(mBubbleEntry,
+ /* suppressFlyout= */ false, /* showInShade= */ true);
+
+ // Check that the update was applied - shouldn't be show in shade
+ assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
+ // Check that it wasn't inflated (1 because it would've been inflated via onEntryAdded)
+ verify(mBubbleController, times(1)).inflateAndAdd(
+ any(Bubble.class), anyBoolean(), anyBoolean());
+ }
+
+ /**
+ * Verifies that if a bubble is in the overflow and a non-interruptive notification update
+ * comes in for it with FLAG_BUBBLE that the flag is removed.
+ */
+ @Test
+ public void testNonInterruptiveUpdate_doesntOverrideOverflowFlagBubble() {
+ mEntryListener.onEntryAdded(mRow);
+ mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ true);
+ assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
+
+ // Dismiss the bubble so it's in the overflow
+ mBubbleController.removeBubble(
+ mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
+ assertThat(mBubbleData.hasOverflowBubbleWithKey(mRow.getKey())).isTrue();
+ // Once it's in the overflow it's not actively a bubble (doesn't have FLAG_BUBBLE)
+ Bubble b = mBubbleData.getOverflowBubbleWithKey(mBubbleEntry.getKey());
+ assertThat(b.isBubble()).isFalse();
+
+ // Send a non-notifying update that has FLAG_BUBBLE
+ mRow.getSbn().getNotification().flags = FLAG_BUBBLE;
+ assertThat(mRow.getSbn().getNotification().isBubbleNotification()).isTrue();
+ mBubbleController.updateBubble(mBubbleEntry,
+ /* suppressFlyout= */ false, /* showInShade= */ true);
+
+ // Verify that it still doesn't have FLAG_BUBBLE because it's in the overflow.
+ b = mBubbleData.getOverflowBubbleWithKey(mBubbleEntry.getKey());
+ assertThat(b.isBubble()).isFalse();
+ }
+
+ @Test
+ public void testNonSystemUpdatesIgnored() {
+ mEntryListener.onEntryAdded(mRow);
+ assertThat(mBubbleController.hasBubbles()).isTrue();
+
+ mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ false);
+ mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ false);
+ mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ false);
+
+ // Check that it wasn't inflated (1 because it would've been inflated via onEntryAdded)
+ verify(mBubbleController, times(1)).inflateAndAdd(
+ any(Bubble.class), anyBoolean(), anyBoolean());
+ }
+
/** Creates a bubble using the userId and package. */
private Bubble createBubble(int userId, String pkg) {
final UserHandle userHandle = new UserHandle(userId);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
index c52ea60f..c83189d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
@@ -15,6 +15,8 @@
*/
package com.android.systemui;
+import static com.android.systemui.animation.FakeDialogLaunchAnimatorKt.fakeDialogLaunchAnimator;
+
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -34,6 +36,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.broadcast.FakeBroadcastDispatcher;
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger;
@@ -119,6 +122,7 @@
// is missing (constructing the actual one would throw).
// TODO(b/219008720): Remove this.
mDependency.injectMockDependency(SystemUIDialogManager.class);
+ mDependency.injectTestDependency(DialogLaunchAnimator.class, fakeDialogLaunchAnimator());
}
@After
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogLaunchAnimator.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogLaunchAnimator.kt
new file mode 100644
index 0000000..990db77
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeDialogLaunchAnimator.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.animation
+
+import com.android.internal.jank.InteractionJankMonitor
+import org.mockito.Mockito.mock
+
+/** A [DialogLaunchAnimator] to be used in tests. */
+@JvmOverloads
+fun fakeDialogLaunchAnimator(
+ isUnlocked: Boolean = true,
+ isShowingAlternateAuthOnUnlock: Boolean = false,
+ interactionJankMonitor: InteractionJankMonitor = mock(InteractionJankMonitor::class.java),
+): DialogLaunchAnimator {
+ return DialogLaunchAnimator(
+ FakeCallback(
+ isUnlocked = isUnlocked,
+ isShowingAlternateAuthOnUnlock = isShowingAlternateAuthOnUnlock,
+ ),
+ interactionJankMonitor,
+ fakeLaunchAnimator(),
+ isForTesting = true,
+ )
+}
+
+private class FakeCallback(
+ private val isDreaming: Boolean = false,
+ private val isUnlocked: Boolean = true,
+ private val isShowingAlternateAuthOnUnlock: Boolean = false,
+) : DialogLaunchAnimator.Callback {
+ override fun isDreaming(): Boolean = isDreaming
+ override fun isUnlocked(): Boolean = isUnlocked
+ override fun isShowingAlternateAuthOnUnlock() = isShowingAlternateAuthOnUnlock
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeLaunchAnimator.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeLaunchAnimator.kt
new file mode 100644
index 0000000..5b431e7
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/FakeLaunchAnimator.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.animation
+
+/** A [LaunchAnimator] to be used in tests. */
+fun fakeLaunchAnimator(): LaunchAnimator {
+ return LaunchAnimator(TEST_TIMINGS, TEST_INTERPOLATORS)
+}
+
+/**
+ * A [LaunchAnimator.Timings] to be used in tests.
+ *
+ * Note that all timings except the total duration are non-zero to avoid divide-by-zero exceptions
+ * when computing the progress of a sub-animation (the contents fade in/out).
+ */
+private val TEST_TIMINGS =
+ LaunchAnimator.Timings(
+ totalDuration = 0L,
+ contentBeforeFadeOutDelay = 1L,
+ contentBeforeFadeOutDuration = 1L,
+ contentAfterFadeInDelay = 1L,
+ contentAfterFadeInDuration = 1L
+ )
+
+/** A [LaunchAnimator.Interpolators] to be used in tests. */
+private val TEST_INTERPOLATORS =
+ LaunchAnimator.Interpolators(
+ positionInterpolator = Interpolators.STANDARD,
+ positionXInterpolator = Interpolators.STANDARD,
+ contentBeforeFadeOutInterpolator = Interpolators.STANDARD,
+ contentAfterFadeInInterpolator = Interpolators.STANDARD
+ )
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 9b11a68..a185b58 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1115,10 +1115,7 @@
registerForBroadcastsLocked(provider, getWidgetIds(provider.widgets));
saveGroupStateAsync(userId);
-
- if (DEBUG) {
- Slog.i(TAG, "Bound widget " + appWidgetId + " to provider " + provider.id);
- }
+ Slog.i(TAG, "Bound widget " + appWidgetId + " to provider " + provider.id);
}
return true;
@@ -4251,6 +4248,10 @@
IAppWidgetHost callbacks;
boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
+ private static final boolean DEBUG = true;
+
+ private static final String TAG = "AppWidgetServiceHost";
+
int tag = TAG_UNDEFINED; // for use while saving state (the index)
// Sequence no for the last update successfully sent. This is updated whenever a
// widget update is successfully sent to the host callbacks. As all new/undelivered updates
@@ -4321,6 +4322,11 @@
final SparseArray<String> uids = new SparseArray<>();
for (int i = widgets.size() - 1; i >= 0; i--) {
final Widget widget = widgets.get(i);
+ if (widget.provider == null) {
+ if (DEBUG) {
+ Slog.e(TAG, "Widget with no provider " + widget.toString());
+ }
+ }
final ProviderId providerId = widget.provider.id;
uids.put(providerId.uid, providerId.componentName.getPackageName());
}
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index c9a420e..32dc470 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -138,6 +138,12 @@
INetd netd, int userId) {
return new Vpn(looper, context, nms, netd, userId, new VpnProfileStore());
}
+
+ /** Create a LockDownVpnTracker. */
+ public LockdownVpnTracker createLockDownVpnTracker(Context context, Handler handler,
+ Vpn vpn, VpnProfile profile) {
+ return new LockdownVpnTracker(context, handler, vpn, profile);
+ }
}
public VpnManagerService(Context context, Dependencies deps) {
@@ -502,8 +508,7 @@
logw("VPN for user " + user + " not ready yet. Skipping lockdown");
return false;
}
- setLockdownTracker(
- new LockdownVpnTracker(mContext, mHandler, vpn, profile));
+ setLockdownTracker(mDeps.createLockDownVpnTracker(mContext, mHandler, vpn, profile));
}
return true;
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 002aa77..e7ea903 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3595,11 +3595,12 @@
/**
* Bump the given service record into executing state.
- * @param oomAdjReason The caller requests it to perform the oomAdjUpdate if it's not null.
+ * @param oomAdjReason The caller requests it to perform the oomAdjUpdate not {@link
+ * OomAdjuster#OOM_ADJ_REASON_NONE}.
* @return {@code true} if it performed oomAdjUpdate.
*/
- private boolean bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why,
- @Nullable String oomAdjReason) {
+ private boolean bumpServiceExecutingLocked(
+ ServiceRecord r, boolean fg, String why, @OomAdjuster.OomAdjReason int oomAdjReason) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING "
+ why + " of " + r + " in app " + r.app);
else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, ">>> EXECUTING "
@@ -3651,7 +3652,7 @@
}
}
boolean oomAdjusted = false;
- if (oomAdjReason != null && r.app != null
+ if (oomAdjReason != OomAdjuster.OOM_ADJ_REASON_NONE && r.app != null
&& r.app.mState.getCurProcState() > ActivityManager.PROCESS_STATE_SERVICE) {
// Force an immediate oomAdjUpdate, so the client app could be in the correct process
// state before doing any service related transactions
@@ -4385,7 +4386,7 @@
final ProcessServiceRecord psr = app.mServices;
final boolean newService = psr.startService(r);
- bumpServiceExecutingLocked(r, execInFg, "create", null /* oomAdjReason */);
+ bumpServiceExecutingLocked(r, execInFg, "create", OomAdjuster.OOM_ADJ_REASON_NONE);
mAm.updateLruProcessLocked(app, false, null);
updateServiceForegroundLocked(psr, /* oomAdj= */ false);
// Force an immediate oomAdjUpdate, so the client app could be in the correct process state
@@ -4511,7 +4512,7 @@
mAm.grantImplicitAccess(r.userId, si.intent, si.callingId,
UserHandle.getAppId(r.appInfo.uid)
);
- bumpServiceExecutingLocked(r, execInFg, "start", null /* oomAdjReason */);
+ bumpServiceExecutingLocked(r, execInFg, "start", OomAdjuster.OOM_ADJ_REASON_NONE);
if (r.fgRequired && !r.fgWaiting) {
if (!r.isForeground) {
if (DEBUG_BACKGROUND_CHECK) {
@@ -4780,7 +4781,7 @@
updateServiceForegroundLocked(r.app.mServices, false);
try {
oomAdjusted |= bumpServiceExecutingLocked(r, false, "destroy",
- oomAdjusted ? null : OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
+ oomAdjusted ? 0 : OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
mDestroyingServices.add(r);
r.destroying = true;
r.app.getThread().scheduleStopService(r);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5729a06..744ec9d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -14692,6 +14692,17 @@
}
}
+ if (!Build.IS_DEBUGGABLE && callingUid != ROOT_UID && callingUid != SHELL_UID
+ && callingUid != SYSTEM_UID) {
+ // If it's not debug build and not called from root/shell/system uid, reject it.
+ String msg = "Permission Denial: instrumentation test "
+ + className + " from pid=" + callingPid + ", uid=" + callingUid
+ + " not allowed because target package " + ii.targetPackage
+ + " is not debuggable.";
+ reportStartInstrumentationFailureLocked(watcher, className, msg);
+ throw new SecurityException(msg);
+ }
+
boolean disableHiddenApiChecks = ai.usesNonSdkApi()
|| (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
boolean disableTestApiChecks = disableHiddenApiChecks
@@ -15598,7 +15609,7 @@
* {@link #enqueueOomAdjTargetLocked}.
*/
@GuardedBy("this")
- void updateOomAdjPendingTargetsLocked(String oomAdjReason) {
+ void updateOomAdjPendingTargetsLocked(@OomAdjuster.OomAdjReason int oomAdjReason) {
mOomAdjuster.updateOomAdjPendingTargetsLocked(oomAdjReason);
}
@@ -15617,7 +15628,7 @@
}
@GuardedBy("this")
- final void updateOomAdjLocked(String oomAdjReason) {
+ final void updateOomAdjLocked(@OomAdjuster.OomAdjReason int oomAdjReason) {
mOomAdjuster.updateOomAdjLocked(oomAdjReason);
}
@@ -15629,7 +15640,8 @@
* @return whether updateOomAdjLocked(app) was successful.
*/
@GuardedBy("this")
- final boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
+ final boolean updateOomAdjLocked(
+ ProcessRecord app, @OomAdjuster.OomAdjReason int oomAdjReason) {
return mOomAdjuster.updateOomAdjLocked(app, oomAdjReason);
}
@@ -15862,14 +15874,16 @@
mOomAdjuster.setUidTempAllowlistStateLSP(uid, onAllowlist);
}
- private void trimApplications(boolean forceFullOomAdj, String oomAdjReason) {
+ private void trimApplications(
+ boolean forceFullOomAdj, @OomAdjuster.OomAdjReason int oomAdjReason) {
synchronized (this) {
trimApplicationsLocked(forceFullOomAdj, oomAdjReason);
}
}
@GuardedBy("this")
- private void trimApplicationsLocked(boolean forceFullOomAdj, String oomAdjReason) {
+ private void trimApplicationsLocked(
+ boolean forceFullOomAdj, @OomAdjuster.OomAdjReason int oomAdjReason) {
// First remove any unused application processes whose package
// has been removed.
boolean didSomething = false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 6609d4a..dbabe99 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -989,26 +989,40 @@
@NeverCompile
int runCompact(PrintWriter pw) {
- String processName = getNextArgRequired();
- String uid = getNextArgRequired();
- String op = getNextArgRequired();
ProcessRecord app;
- synchronized (mInternal.mProcLock) {
- app = mInternal.getProcessRecordLocked(processName, Integer.parseInt(uid));
- }
- pw.println("Process record found pid: " + app.mPid);
- if (op.equals("full")) {
- pw.println("Executing full compaction for " + app.mPid);
+ String op = getNextArgRequired();
+ boolean isFullCompact = op.equals("full");
+ boolean isSomeCompact = op.equals("some");
+ if (isFullCompact || isSomeCompact) {
+ String processName = getNextArgRequired();
+ String uid = getNextArgRequired();
synchronized (mInternal.mProcLock) {
- mInternal.mOomAdjuster.mCachedAppOptimizer.compactAppFull(app, true);
+ app = mInternal.getProcessRecordLocked(processName, Integer.parseInt(uid));
}
- pw.println("Finished full compaction for " + app.mPid);
- } else if (op.equals("some")) {
- pw.println("Executing some compaction for " + app.mPid);
+ pw.println("Process record found pid: " + app.mPid);
+ if (isFullCompact) {
+ pw.println("Executing full compaction for " + app.mPid);
+ synchronized (mInternal.mProcLock) {
+ mInternal.mOomAdjuster.mCachedAppOptimizer.compactApp(app,
+ CachedAppOptimizer.CompactProfile.FULL,
+ CachedAppOptimizer.CompactSource.APP, true);
+ }
+ pw.println("Finished full compaction for " + app.mPid);
+ } else if (isSomeCompact) {
+ pw.println("Executing some compaction for " + app.mPid);
+ synchronized (mInternal.mProcLock) {
+ mInternal.mOomAdjuster.mCachedAppOptimizer.compactApp(app,
+ CachedAppOptimizer.CompactProfile.SOME,
+ CachedAppOptimizer.CompactSource.APP, true);
+ }
+ pw.println("Finished some compaction for " + app.mPid);
+ }
+ } else if (op.equals("system")) {
+ pw.println("Executing system compaction");
synchronized (mInternal.mProcLock) {
- mInternal.mOomAdjuster.mCachedAppOptimizer.compactAppSome(app, true);
+ mInternal.mOomAdjuster.mCachedAppOptimizer.compactAllSystem();
}
- pw.println("Finished some compaction for " + app.mPid);
+ pw.println("Finished system compaction");
} else {
getErrPrintWriter().println("Error: unknown compact command '" + op + "'");
return -1;
@@ -3570,10 +3584,11 @@
pw.println(" --allow-background-activity-starts: The receiver may start activities");
pw.println(" even if in the background.");
pw.println(" --async: Send without waiting for the completion of the receiver.");
- pw.println(" compact <process_name> <Package UID> [some|full]");
+ pw.println(" compact [some|full|system] <process_name> <Package UID>");
pw.println(" Force process compaction.");
pw.println(" some: execute file compaction.");
pw.println(" full: execute anon + file compaction.");
+ pw.println(" system: system compaction.");
pw.println(" instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]");
pw.println(" [--user <USER_ID> | current]");
pw.println(" [--no-hidden-api-checks [--no-test-api-access]]");
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index c88d82c..45265ac 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -25,7 +25,6 @@
import android.app.ApplicationExitInfo;
import android.database.ContentObserver;
import android.net.Uri;
-import android.os.Debug;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManagerInternal;
@@ -40,20 +39,21 @@
import android.util.EventLog;
import android.util.Slog;
import android.util.SparseArray;
-
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.ProcLocksReader;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.ServiceThread;
-
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
+import java.util.LinkedList;
import java.util.Map;
import java.util.Random;
import java.util.Set;
@@ -99,7 +99,7 @@
private static final int COMPACT_ACTION_NONE = 0;
private static final int COMPACT_ACTION_FILE = 1;
private static final int COMPACT_ACTION_ANON = 2;
- private static final int COMPACT_ACTION_FULL = 3;
+ private static final int COMPACT_ACTION_ALL = 3;
private static final String COMPACT_ACTION_STRING[] = {"", "file", "anon", "all"};
@@ -112,7 +112,7 @@
// Defaults for phenotype flags.
@VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = false;
@VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = true;
- @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_2 = COMPACT_ACTION_FULL;
+ @VisibleForTesting static final int DEFAULT_COMPACT_ACTION_2 = COMPACT_ACTION_ALL;
@VisibleForTesting static final int DEFAULT_COMPACT_ACTION_1 = COMPACT_ACTION_FILE;
@VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_1 = 5_000;
@VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000;
@@ -147,14 +147,33 @@
@VisibleForTesting
interface ProcessDependencies {
long[] getRss(int pid);
- void performCompaction(String action, int pid) throws IOException;
+ void performCompaction(CompactAction action, int pid) throws IOException;
+ }
+
+ // This indicates the compaction we want to perform
+ public enum CompactProfile {
+ SOME, // File compaction
+ FULL // File+anon compaction
+ }
+
+ // Low level actions that can be performed for compaction
+ // currently determined by the compaction profile
+ public enum CompactAction {
+ NONE, // No compaction
+ FILE, // File+anon compaction
+ ANON,
+ ALL
+ }
+
+ // This indicates the process OOM memory state that initiated the compaction request
+ public enum CompactSource { APP, PERSISTENT, BFGS }
+
+ public enum CancelCompactReason {
+ SCREEN_ON, // screen was turned on which cancels all compactions.
+ OOM_IMPROVEMENT // process moved out of cached state and into a more perceptible state.
}
// Handler constants.
- static final int COMPACT_PROCESS_SOME = 1;
- static final int COMPACT_PROCESS_FULL = 2;
- static final int COMPACT_PROCESS_PERSISTENT = 3;
- static final int COMPACT_PROCESS_BFGS = 4;
static final int COMPACT_PROCESS_MSG = 1;
static final int COMPACT_SYSTEM_MSG = 2;
static final int SET_FROZEN_PROCESS_MSG = 3;
@@ -165,6 +184,12 @@
// on swap resources as file.
static final double COMPACT_DOWNGRADE_FREE_SWAP_THRESHOLD = 0.2;
+ // Size of history for the last 20 compactions for any process
+ static final int LAST_COMPACTED_ANY_PROCESS_STATS_HISTORY_SIZE = 20;
+
+ // Amount of processes supported to record for their last compaction.
+ static final int LAST_COMPACTION_FOR_PROCESS_STATS_SIZE = 256;
+
static final int DO_FREEZE = 1;
static final int REPORT_UNFREEZE = 2;
@@ -273,15 +298,16 @@
private final SettingsContentObserver mSettingsObserver;
- private final Object mPhenotypeFlagLock = new Object();
+ @VisibleForTesting
+ final Object mPhenotypeFlagLock = new Object();
// Configured by phenotype. Updates from the server take effect immediately.
@GuardedBy("mPhenotypeFlagLock")
- @VisibleForTesting volatile String mCompactActionSome =
- compactActionIntToString(DEFAULT_COMPACT_ACTION_1);
+ @VisibleForTesting
+ volatile CompactAction mCompactActionSome = compactActionIntToAction(DEFAULT_COMPACT_ACTION_1);
@GuardedBy("mPhenotypeFlagLock")
- @VisibleForTesting volatile String mCompactActionFull =
- compactActionIntToString(DEFAULT_COMPACT_ACTION_2);
+ @VisibleForTesting
+ volatile CompactAction mCompactActionFull = compactActionIntToAction(DEFAULT_COMPACT_ACTION_2);
@GuardedBy("mPhenotypeFlagLock")
@VisibleForTesting volatile long mCompactThrottleSomeSome = DEFAULT_COMPACT_THROTTLE_1;
@GuardedBy("mPhenotypeFlagLock")
@@ -333,31 +359,139 @@
// facilitate removal of the oldest entry.
@VisibleForTesting
@GuardedBy("mProcLock")
- LinkedHashMap<Integer, LastCompactionStats> mLastCompactionStats =
- new LinkedHashMap<Integer, LastCompactionStats>() {
+ LinkedHashMap<Integer, SingleCompactionStats> mLastCompactionStats =
+ new LinkedHashMap<Integer, SingleCompactionStats>() {
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
- return size() > 100;
+ return size() > LAST_COMPACTION_FOR_PROCESS_STATS_SIZE;
}
- };
+ };
- // Compaction Stats
- private int mSomeCompactionCount;
- private int mFullCompactionCount;
- private int mPersistentCompactionCount;
- private int mBfgsCompactionCount;
- private long mSomeCompactRequest;
- private long mFullCompactRequest;
- private long mPersistentCompactRequest;
- private long mBfgsCompactRequest;
- private long mProcCompactionsRequested;
- private long mProcCompactionsPerformed;
- private long mProcCompactionsNoPidThrottled;
- private long mProcCompactionsOomAdjThrottled;
- private long mProcCompactionsTimeThrottled;
- private long mProcCompactionsRSSThrottled;
- private long mProcCompactionsMiscThrottled;
+ LinkedList<SingleCompactionStats> mCompactionStatsHistory =
+ new LinkedList<SingleCompactionStats>() {
+ @Override
+ public boolean add(SingleCompactionStats e) {
+ if (size() >= LAST_COMPACTED_ANY_PROCESS_STATS_HISTORY_SIZE) {
+ this.remove();
+ }
+ return super.add(e);
+ }
+ };
+
+ class AggregatedCompactionStats {
+ // Throttling stats
+ public long mFullCompactRequested;
+ public long mSomeCompactRequested;
+ public long mFullCompactPerformed;
+ public long mSomeCompactPerformed;
+ public long mProcCompactionsNoPidThrottled;
+ public long mProcCompactionsOomAdjThrottled;
+ public long mProcCompactionsTimeThrottled;
+ public long mProcCompactionsRSSThrottled;
+ public long mProcCompactionsMiscThrottled;
+
+ // Memory stats
+ public long mTotalDeltaAnonRssKBs;
+ public long mTotalZramConsumedKBs;
+ public long mTotalAnonMemFreedKBs;
+ public long mSumOrigAnonRss;
+ public double mMaxCompactEfficiency;
+
+ // Cpu time
+ public long mTotalCpuTimeMillis;
+
+ public long getThrottledSome() { return mSomeCompactRequested - mSomeCompactPerformed; }
+
+ public long getThrottledFull() { return mFullCompactRequested - mFullCompactPerformed; }
+
+ public void addMemStats(long anonRssSaved, long zramConsumed, long memFreed,
+ long origAnonRss, long totalCpuTimeMillis) {
+ final double compactEfficiency = memFreed / (double) origAnonRss;
+ if (compactEfficiency > mMaxCompactEfficiency) {
+ mMaxCompactEfficiency = compactEfficiency;
+ }
+ mTotalDeltaAnonRssKBs += anonRssSaved;
+ mTotalZramConsumedKBs += zramConsumed;
+ mTotalAnonMemFreedKBs += memFreed;
+ mSumOrigAnonRss += origAnonRss;
+ mTotalCpuTimeMillis += totalCpuTimeMillis;
+ }
+
+ public void dump(PrintWriter pw) {
+ long totalCompactRequested = mSomeCompactRequested + mFullCompactRequested;
+ long totalCompactPerformed = mSomeCompactPerformed + mFullCompactPerformed;
+ pw.println(" Performed / Requested:");
+ pw.println(" Some: (" + mSomeCompactPerformed + "/" + mSomeCompactRequested + ")");
+ pw.println(" Full: (" + mFullCompactPerformed + "/" + mFullCompactRequested + ")");
+
+ long throttledSome = getThrottledSome();
+ long throttledFull = getThrottledFull();
+
+ if (throttledSome > 0 || throttledFull > 0) {
+ pw.println(" Throttled:");
+ pw.println(" Some: " + throttledSome + " Full: " + throttledFull);
+ pw.println(" Throttled by Type:");
+ final long compactionsThrottled = totalCompactRequested - totalCompactPerformed;
+ // Any throttle that was not part of the previous categories
+ final long unaccountedThrottled = compactionsThrottled
+ - mProcCompactionsNoPidThrottled - mProcCompactionsOomAdjThrottled
+ - mProcCompactionsTimeThrottled - mProcCompactionsRSSThrottled
+ - mProcCompactionsMiscThrottled;
+ pw.println(" NoPid: " + mProcCompactionsNoPidThrottled
+ + " OomAdj: " + mProcCompactionsOomAdjThrottled + " Time: "
+ + mProcCompactionsTimeThrottled + " RSS: " + mProcCompactionsRSSThrottled
+ + " Misc: " + mProcCompactionsMiscThrottled
+ + " Unaccounted: " + unaccountedThrottled);
+ final double compactThrottlePercentage =
+ (compactionsThrottled / (double) totalCompactRequested) * 100.0;
+ pw.println(" Throttle Percentage: " + compactThrottlePercentage);
+ }
+
+ if (mFullCompactPerformed > 0) {
+ pw.println(" -----Memory Stats----");
+ pw.println(" Total Delta Anon RSS (KB) : " + mTotalDeltaAnonRssKBs);
+ pw.println(" Total Physical ZRAM Consumed (KB): " + mTotalZramConsumedKBs);
+ pw.println(" Total Anon Memory Freed (KB): " + mTotalAnonMemFreedKBs);
+ // This tells us how much anon memory we were able to free thanks to running
+ // compaction
+ pw.println(" Avg Compaction Efficiency (Anon Freed/Anon RSS): "
+ + (mTotalAnonMemFreedKBs / (double) mSumOrigAnonRss));
+ pw.println(" Max Compaction Efficiency: " + mMaxCompactEfficiency);
+ // This tells us how effective is the compression algorithm in physical memory
+ pw.println(" Avg Compression Ratio (1 - ZRAM Consumed/DeltaAnonRSS): "
+ + (1.0 - mTotalZramConsumedKBs / (double) mTotalDeltaAnonRssKBs));
+ long avgKBsPerProcCompact = mFullCompactPerformed > 0
+ ? (mTotalAnonMemFreedKBs / mFullCompactPerformed)
+ : 0;
+ pw.println(" Avg Anon Mem Freed/Compaction (KB) : " + avgKBsPerProcCompact);
+ double compactionCost =
+ mTotalCpuTimeMillis / (mTotalAnonMemFreedKBs / 1024.0); // ms/MB
+ pw.println(" Compaction Cost (ms/MB): " + compactionCost);
+ }
+ }
+ }
+
+ class AggregatedProcessCompactionStats extends AggregatedCompactionStats {
+ public final String processName;
+
+ AggregatedProcessCompactionStats(String processName) { this.processName = processName; }
+ }
+
+ class AggregatedSourceCompactionStats extends AggregatedCompactionStats {
+ public final CompactSource sourceType;
+
+ AggregatedSourceCompactionStats(CompactSource sourceType) { this.sourceType = sourceType; }
+ }
+
+ private final LinkedHashMap<String, AggregatedProcessCompactionStats> mPerProcessCompactStats =
+ new LinkedHashMap<>(256);
+ private final EnumMap<CompactSource, AggregatedSourceCompactionStats> mPerSourceCompactStats =
+ new EnumMap<>(CompactSource.class);
+ private long mTotalCompactionDowngrades;
private long mSystemCompactionsPerformed;
+ private long mSystemTotalMemFreed;
+ private EnumMap<CancelCompactReason, Integer> mTotalCompactionsCancelled =
+ new EnumMap<>(CancelCompactReason.class);
private final ProcessDependencies mProcessDependencies;
private final ProcLocksReader mProcLocksReader;
@@ -450,34 +584,61 @@
pw.println(" " + KEY_COMPACT_PROC_STATE_THROTTLE + "="
+ Arrays.toString(mProcStateThrottle.toArray(new Integer[0])));
- pw.println(" Requested: " + mSomeCompactRequest + " some, " + mFullCompactRequest
- + " full, " + mPersistentCompactRequest + " persistent, "
- + mBfgsCompactRequest + " BFGS compactions.");
- pw.println(" Performed: " + mSomeCompactionCount + " some, " + mFullCompactionCount
- + " full, " + mPersistentCompactionCount + " persistent, "
- + mBfgsCompactionCount + " BFGS compactions.");
- pw.println(" Process Compactions Requested: " + mProcCompactionsRequested);
- pw.println(" Process Compactions Performed: " + mProcCompactionsPerformed);
- long compactionsThrottled = mProcCompactionsRequested - mProcCompactionsPerformed;
- pw.println(" Process Compactions Throttled: " + compactionsThrottled);
- double compactThrottlePercentage =
- (compactionsThrottled / (double) mProcCompactionsRequested) * 100.0;
- pw.println(" Process Compactions Throttle Percentage: " + compactThrottlePercentage);
- pw.println(" NoPid Throttled: " + mProcCompactionsNoPidThrottled);
- pw.println(" OomAdj Throttled: " + mProcCompactionsOomAdjThrottled);
- pw.println(" Time Throttled: " + mProcCompactionsTimeThrottled);
- pw.println(" RSS Throttled: " + mProcCompactionsRSSThrottled);
- pw.println(" Misc Throttled: " + mProcCompactionsMiscThrottled);
- long unaccountedThrottled = compactionsThrottled - mProcCompactionsNoPidThrottled
- - mProcCompactionsOomAdjThrottled - mProcCompactionsTimeThrottled
- - mProcCompactionsRSSThrottled - mProcCompactionsMiscThrottled;
- // Any throttle that was not part of the previous categories
- pw.println(" Unaccounted Throttled: " + unaccountedThrottled);
+ pw.println(" Per-Process Compaction Stats");
+ long totalCompactPerformedSome = 0;
+ long totalCompactPerformedFull = 0;
+ for (AggregatedProcessCompactionStats stats : mPerProcessCompactStats.values()) {
+ pw.println("-----" + stats.processName + "-----");
+ totalCompactPerformedSome += stats.mSomeCompactPerformed;
+ totalCompactPerformedFull += stats.mFullCompactPerformed;
+ stats.dump(pw);
+ pw.println();
+ }
+ pw.println();
+ pw.println(" Per-Source Compaction Stats");
+ for (AggregatedSourceCompactionStats stats : mPerSourceCompactStats.values()) {
+ pw.println("-----" + stats.sourceType + "-----");
+ stats.dump(pw);
+ pw.println();
+ }
+ pw.println();
- pw.println(" System Compactions Performed: " + mSystemCompactionsPerformed);
+ pw.println("Total Compactions Performed by profile: " + totalCompactPerformedSome
+ + " some, " + totalCompactPerformedFull + " full");
+ pw.println("Total compactions downgraded: " + mTotalCompactionDowngrades);
+ pw.println("Total compactions cancelled by reason: ");
+ for (CancelCompactReason reason : mTotalCompactionsCancelled.keySet()) {
+ pw.println(" " + reason + ": " + mTotalCompactionsCancelled.get(reason));
+ }
+ pw.println();
+ pw.println(" System Compaction Memory Stats");
+ pw.println(" Compactions Performed: " + mSystemCompactionsPerformed);
+ pw.println(" Total Memory Freed (KB): " + mSystemTotalMemFreed);
+ double avgKBsPerSystemCompact = mSystemCompactionsPerformed > 0
+ ? mSystemTotalMemFreed / mSystemCompactionsPerformed
+ : 0;
+ pw.println(" Avg Mem Freed per Compact (KB): " + avgKBsPerSystemCompact);
+ pw.println();
pw.println(" Tracking last compaction stats for " + mLastCompactionStats.size()
+ " processes.");
+ pw.println("Last Compaction per process stats:");
+ pw.println(" (ProcessName,Source,DeltaAnonRssKBs,ZramConsumedKBs,AnonMemFreedKBs,"
+ + "CompactEfficiency,CompactCost(ms/MB),procState,oomAdj,oomAdjReason)");
+ for (Map.Entry<Integer, SingleCompactionStats> entry :
+ mLastCompactionStats.entrySet()) {
+ SingleCompactionStats stats = entry.getValue();
+ stats.dump(pw);
+ }
+ pw.println();
+ pw.println("Last 20 Compactions Stats:");
+ pw.println(" (ProcessName,Source,DeltaAnonRssKBs,ZramConsumedKBs,AnonMemFreedKBs,"
+ + "CompactEfficiency,CompactCost(ms/MB),procState,oomAdj,oomAdjReason)");
+ for (SingleCompactionStats stats : mCompactionStatsHistory) {
+ stats.dump(pw);
+ }
+ pw.println();
+
pw.println(" " + KEY_USE_FREEZER + "=" + mUseFreezer);
pw.println(" " + KEY_FREEZER_STATSD_SAMPLE_RATE + "=" + mFreezerStatsdSampleRate);
pw.println(" " + KEY_FREEZER_DEBOUNCE_TIMEOUT + "=" + mFreezerDebounceTimeout);
@@ -500,25 +661,9 @@
}
}
}
- if (DEBUG_COMPACTION) {
- for (Map.Entry<Integer, LastCompactionStats> entry
- : mLastCompactionStats.entrySet()) {
- int pid = entry.getKey();
- LastCompactionStats stats = entry.getValue();
- pw.println(" " + pid + ": "
- + Arrays.toString(stats.getRssAfterCompaction()));
- }
- }
}
}
- @GuardedBy("mProcLock")
- void compactAppSome(ProcessRecord app, boolean force) {
- app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_SOME);
- ++mSomeCompactRequest;
- compactApp(app, force, "some");
- }
-
// This method returns true only if requirements are met. Note, that requirements are different
// from throttles applied at the time a compaction is trying to be executed in the sense that
// these are not subject to change dependent on time or memory as throttles usually do.
@@ -546,46 +691,38 @@
}
@GuardedBy("mProcLock")
- void compactAppFull(ProcessRecord app, boolean force) {
- boolean oomAdjEnteredCached = (app.mState.getSetAdj() < mCompactThrottleMinOomAdj
- || app.mState.getSetAdj() > mCompactThrottleMaxOomAdj)
- && app.mState.getCurAdj() >= mCompactThrottleMinOomAdj
- && app.mState.getCurAdj() <= mCompactThrottleMaxOomAdj;
- if (DEBUG_COMPACTION) {
- Slog.d(TAG_AM,
- " compactAppFull requested for " + app.processName + " force: " + force
- + " oomAdjEnteredCached: " + oomAdjEnteredCached);
+ boolean compactApp(
+ ProcessRecord app, CompactProfile compactProfile, CompactSource source, boolean force) {
+ app.mOptRecord.setReqCompactSource(source);
+ app.mOptRecord.setReqCompactProfile(compactProfile);
+ AggregatedSourceCompactionStats perSourceStats = getPerSourceAggregatedCompactStat(source);
+ AggregatedCompactionStats perProcStats =
+ getPerProcessAggregatedCompactStat(app.processName);
+ switch (compactProfile) {
+ case SOME:
+ ++perProcStats.mSomeCompactRequested;
+ ++perSourceStats.mSomeCompactRequested;
+ break;
+ case FULL:
+ ++perProcStats.mFullCompactRequested;
+ ++perSourceStats.mFullCompactRequested;
+ break;
+ default:
+ Slog.e(TAG_AM,
+ "Unimplemented compaction type, consider adding it.");
+ return false;
}
- ++mFullCompactRequest;
- // Apply OOM adj score throttle for Full App Compaction.
- if (force || oomAdjEnteredCached) {
- app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_FULL);
- compactApp(app, force, "Full");
- } else {
- if (DEBUG_COMPACTION) {
- Slog.d(TAG_AM, "Skipping full compaction for " + app.processName
- + " oom adj score changed from " + app.mState.getSetAdj()
- + " to " + app.mState.getCurAdj());
- }
- }
- }
- @GuardedBy("mProcLock")
- void compactAppPersistent(ProcessRecord app) {
- app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_PERSISTENT);
- ++mPersistentCompactRequest;
- compactApp(app, false, "Persistent");
- }
-
- @GuardedBy("mProcLock")
- boolean compactApp(ProcessRecord app, boolean force, String compactRequestType) {
- if (!app.mOptRecord.hasPendingCompact() && meetsCompactionRequirements(app)) {
+ if (!app.mOptRecord.hasPendingCompact() && (meetsCompactionRequirements(app) || force)) {
final String processName = (app.processName != null ? app.processName : "");
if (DEBUG_COMPACTION) {
- Slog.d(TAG_AM, "compactApp " + compactRequestType + " " + processName);
+ Slog.d(TAG_AM,
+ "compactApp " + app.mOptRecord.getReqCompactSource().name() + " "
+ + app.mOptRecord.getReqCompactProfile().name() + " " + processName);
}
Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER, ATRACE_COMPACTION_TRACK,
- "compactApp " + compactRequestType + " " + processName);
+ "compactApp " + app.mOptRecord.getReqCompactSource().name() + " "
+ + app.mOptRecord.getReqCompactProfile().name() + " " + processName);
app.mOptRecord.setHasPendingCompact(true);
app.mOptRecord.setForceCompact(force);
mPendingCompactionProcesses.add(app);
@@ -596,14 +733,53 @@
if (DEBUG_COMPACTION) {
Slog.d(TAG_AM,
- " compactApp Skipped for " + app.processName
- + " pendingCompact= " + app.mOptRecord.hasPendingCompact()
- + " meetsCompactionRequirements=" + meetsCompactionRequirements(app)
- + ". Requested compact: " + app.mOptRecord.getReqCompactAction());
+ " compactApp Skipped for " + app.processName + " pendingCompact= "
+ + app.mOptRecord.hasPendingCompact() + " meetsCompactionRequirements="
+ + meetsCompactionRequirements(app) + ". Requested compact profile: "
+ + app.mOptRecord.getReqCompactProfile().name() + ". Compact source "
+ + app.mOptRecord.getReqCompactSource().name());
}
return false;
}
+ private CompactAction resolveCompactActionForProfile(CompactProfile profile) {
+ CompactAction action;
+ switch (profile) {
+ case SOME:
+ action = CompactAction.FILE;
+ break;
+ case FULL:
+ action = CompactAction.ALL;
+ break;
+ default:
+ action = CompactAction.NONE;
+ }
+ return action;
+ }
+
+ private AggregatedProcessCompactionStats getPerProcessAggregatedCompactStat(
+ String processName) {
+ if (processName == null) {
+ processName = "";
+ }
+ AggregatedProcessCompactionStats stats = mPerProcessCompactStats.get(processName);
+ if (stats == null) {
+ stats = new AggregatedProcessCompactionStats(processName);
+ mPerProcessCompactStats.put(processName, stats);
+ }
+ return stats;
+ }
+
+ private AggregatedSourceCompactionStats getPerSourceAggregatedCompactStat(
+ CompactSource source) {
+ AggregatedSourceCompactionStats stats = mPerSourceCompactStats.get(source);
+ if (stats == null) {
+ stats = new AggregatedSourceCompactionStats(source);
+ mPerSourceCompactStats.put(source, stats);
+ }
+ return stats;
+ }
+
@GuardedBy("mProcLock")
boolean shouldCompactPersistent(ProcessRecord app, long now) {
return (app.mOptRecord.getLastCompactTime() == 0
@@ -611,13 +787,6 @@
}
@GuardedBy("mProcLock")
- void compactAppBfgs(ProcessRecord app) {
- ++mBfgsCompactRequest;
- app.mOptRecord.setReqCompactAction(COMPACT_PROCESS_BFGS);
- compactApp(app, false, " Bfgs");
- }
-
- @GuardedBy("mProcLock")
boolean shouldCompactBFGS(ProcessRecord app, long now) {
return (app.mOptRecord.getLastCompactTime() == 0
|| (now - app.mOptRecord.getLastCompactTime()) > mCompactThrottleBFGS);
@@ -648,11 +817,27 @@
static private native void cancelCompaction();
/**
+ * Returns the cpu time for the current thread
+ */
+ static private native long threadCpuTimeNs();
+
+ /**
* Retrieves the free swap percentage.
*/
static private native double getFreeSwapPercent();
/**
+ * Retrieves the total used physical ZRAM
+ */
+ static private native long getUsedZramMemory();
+
+ /**
+ * Amount of memory that has been made free due to compaction.
+ * It represents uncompressed memory size - compressed memory size.
+ */
+ static private native long getMemoryFreedCompaction();
+
+ /**
* Reads the flag value from DeviceConfig to determine whether app compaction
* should be enabled, and starts the freeze/compaction thread if needed.
*/
@@ -851,8 +1036,8 @@
int compactAction2 = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
KEY_COMPACT_ACTION_2, DEFAULT_COMPACT_ACTION_2);
- mCompactActionSome = compactActionIntToString(compactAction1);
- mCompactActionFull = compactActionIntToString(compactAction2);
+ mCompactActionSome = compactActionIntToAction(compactAction1);
+ mCompactActionFull = compactActionIntToAction(compactAction2);
}
@GuardedBy("mPhenotypeFlagLock")
@@ -1019,13 +1204,12 @@
return true;
}
- @VisibleForTesting
- static String compactActionIntToString(int action) {
- if (action < 0 || action >= COMPACT_ACTION_STRING.length) {
- return "";
+ static CompactAction compactActionIntToAction(int action) {
+ if (action < 0 || action >= CompactAction.values().length) {
+ return CompactAction.NONE;
}
- return COMPACT_ACTION_STRING[action];
+ return CompactAction.values()[action];
}
// This will ensure app will be out of the freezer for at least mFreezerDebounceTimeout.
@@ -1202,16 +1386,17 @@
if(wakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE) {
// Remove any pending compaction we may have scheduled to happen while screen was off
Slog.e(TAG_AM, "Cancel pending or running compactions as system is awake");
- cancelAllCompactions();
+ cancelAllCompactions(CancelCompactReason.SCREEN_ON);
}
}
- void cancelAllCompactions() {
+ void cancelAllCompactions(CancelCompactReason reason) {
synchronized (mProcLock) {
int size = mPendingCompactionProcesses.size();
ProcessRecord record;
for (int i=0; i < size; ++i) {
record = mPendingCompactionProcesses.get(i);
+ cancelCompactionForProcess(record, reason);
// The process record is kept alive after compactions are cleared,
// so make sure to reset the compaction state to avoid skipping any future
// compactions due to a stale value here.
@@ -1222,53 +1407,64 @@
cancelCompaction();
}
+ @GuardedBy("mProcLock")
+ void cancelCompactionForProcess(ProcessRecord app, CancelCompactReason cancelReason) {
+ boolean cancelled = false;
+ if (!mPendingCompactionProcesses.isEmpty() && mPendingCompactionProcesses.contains(app)) {
+ app.mOptRecord.setHasPendingCompact(false);
+ mPendingCompactionProcesses.remove(app);
+ cancelled = true;
+ }
+ if (DefaultProcessDependencies.mPidCompacting == app.mPid) {
+ cancelCompaction();
+ cancelled = true;
+ }
+ if (cancelled) {
+ if (mTotalCompactionsCancelled.containsKey(cancelReason)) {
+ int count = mTotalCompactionsCancelled.get(cancelReason);
+ mTotalCompactionsCancelled.put(cancelReason, count + 1);
+ } else {
+ mTotalCompactionsCancelled.put(cancelReason, 1);
+ }
+ if (DEBUG_COMPACTION) {
+ Slog.d(TAG_AM,
+ "Cancelled pending or running compactions for process: " +
+ app.processName != null ? app.processName : "" +
+ " reason: " + cancelReason.name());
+ }
+ }
+ }
+
@GuardedBy({"mService", "mProcLock"})
void onOomAdjustChanged(int oldAdj, int newAdj, ProcessRecord app) {
// Cancel any currently executing compactions
// if the process moved out of cached state
- if (DefaultProcessDependencies.mPidCompacting == app.mPid && newAdj < oldAdj
- && newAdj < ProcessList.CACHED_APP_MIN_ADJ) {
- cancelCompaction();
+ if (newAdj < oldAdj && newAdj < ProcessList.CACHED_APP_MIN_ADJ) {
+ cancelCompactionForProcess(app, CancelCompactReason.OOM_IMPROVEMENT);
}
if (oldAdj <= ProcessList.PERCEPTIBLE_APP_ADJ
&& (newAdj == ProcessList.PREVIOUS_APP_ADJ || newAdj == ProcessList.HOME_APP_ADJ)) {
// Perform a minor compaction when a perceptible app becomes the prev/home app
- compactAppSome(app, false);
+ compactApp(app, CompactProfile.SOME, CompactSource.APP, false);
} else if (oldAdj < ProcessList.CACHED_APP_MIN_ADJ
&& newAdj >= ProcessList.CACHED_APP_MIN_ADJ
&& newAdj <= ProcessList.CACHED_APP_MAX_ADJ) {
// Perform a major compaction when any app enters cached
- compactAppFull(app, false);
+ compactApp(app, CompactProfile.FULL, CompactSource.APP, false);
}
}
/**
- * This method resolves which compaction method we should use for the proposed compaction.
+ * Applies a compaction downgrade when swap is low.
*/
- int resolveCompactionAction(int pendingAction) {
- int resolvedAction;
-
- switch (pendingAction) {
- case COMPACT_PROCESS_SOME:
- resolvedAction = COMPACT_ACTION_FILE;
- break;
- // For the time being, treat these as equivalent.
- case COMPACT_PROCESS_FULL:
- case COMPACT_PROCESS_PERSISTENT:
- case COMPACT_PROCESS_BFGS:
- resolvedAction = COMPACT_ACTION_FULL;
- break;
- default:
- resolvedAction = COMPACT_ACTION_NONE;
- break;
- }
-
+ CompactProfile downgradeCompactionIfRequired(CompactProfile profile) {
// Downgrade compaction under swap memory pressure
- if (resolvedAction == COMPACT_ACTION_FULL) {
+ if (profile == CompactProfile.FULL) {
double swapFreePercent = getFreeSwapPercent();
if (swapFreePercent < COMPACT_DOWNGRADE_FREE_SWAP_THRESHOLD) {
- resolvedAction = COMPACT_ACTION_FILE;
+ profile = CompactProfile.SOME;
+ ++mTotalCompactionDowngrades;
if (DEBUG_COMPACTION) {
Slog.d(TAG_AM,
"Downgraded compaction to file only due to low swap."
@@ -1277,20 +1473,69 @@
}
}
- return resolvedAction;
+ return profile;
}
@VisibleForTesting
- static final class LastCompactionStats {
+ static final class SingleCompactionStats {
+ private static final float STATSD_SAMPLE_RATE = 0.1f;
+ private static final Random mRandom = new Random();
private final long[] mRssAfterCompaction;
+ public CompactSource mSourceType;
+ public String mProcessName;
+ public final int mUid;
+ public long mDeltaAnonRssKBs;
+ public long mZramConsumedKBs;
+ public long mAnonMemFreedKBs;
+ public float mCpuTimeMillis;
+ public long mOrigAnonRss;
+ public int mProcState;
+ public int mOomAdj;
+ public @OomAdjuster.OomAdjReason int mOomAdjReason;
- LastCompactionStats(long[] rss) {
+ SingleCompactionStats(long[] rss, CompactSource source, String processName,
+ long deltaAnonRss, long zramConsumed, long anonMemFreed, long origAnonRss,
+ long cpuTimeMillis, int procState, int oomAdj,
+ @OomAdjuster.OomAdjReason int oomAdjReason, int uid) {
mRssAfterCompaction = rss;
+ mSourceType = source;
+ mProcessName = processName;
+ mUid = uid;
+ mDeltaAnonRssKBs = deltaAnonRss;
+ mZramConsumedKBs = zramConsumed;
+ mAnonMemFreedKBs = anonMemFreed;
+ mCpuTimeMillis = cpuTimeMillis;
+ mOrigAnonRss = origAnonRss;
+ mProcState = procState;
+ mOomAdj = oomAdj;
+ mOomAdjReason = oomAdjReason;
+ }
+
+ double getCompactEfficiency() { return mAnonMemFreedKBs / (double) mOrigAnonRss; }
+
+ double getCompactCost() {
+ // mCpuTimeMillis / (anonMemFreedKBs/1024) and metric is in (ms/MB)
+ return mCpuTimeMillis / (double) mAnonMemFreedKBs * 1024;
}
long[] getRssAfterCompaction() {
return mRssAfterCompaction;
}
+
+ void dump(PrintWriter pw) {
+ pw.println(" (" + mProcessName + "," + mSourceType.name() + "," + mDeltaAnonRssKBs
+ + "," + mZramConsumedKBs + "," + mAnonMemFreedKBs + "," + getCompactEfficiency()
+ + "," + getCompactCost() + "," + mProcState + "," + mOomAdj + ","
+ + OomAdjuster.oomAdjReasonToString(mOomAdjReason) + ")");
+ }
+
+ void sendStat() {
+ if (mRandom.nextFloat() < STATSD_SAMPLE_RATE) {
+ FrameworkStatsLog.write(FrameworkStatsLog.APP_COMPACTED_V2, mUid, mProcState,
+ mOomAdj, mDeltaAnonRssKBs, mZramConsumedKBs, mCpuTimeMillis, mOrigAnonRss,
+ mOomAdjReason);
+ }
+ }
}
private final class MemCompactionHandler extends Handler {
@@ -1298,13 +1543,12 @@
super(mCachedAppOptimizerThread.getLooper());
}
- private boolean shouldOomAdjThrottleCompaction(ProcessRecord proc, int action) {
+ private boolean shouldOomAdjThrottleCompaction(ProcessRecord proc) {
final String name = proc.processName;
// don't compact if the process has returned to perceptible
// and this is only a cached/home/prev compaction
- if ((action == COMPACT_ACTION_FILE || action == COMPACT_ACTION_FULL)
- && (proc.mState.getSetAdj() <= ProcessList.PERCEPTIBLE_APP_ADJ)) {
+ if (proc.mState.getSetAdj() <= ProcessList.PERCEPTIBLE_APP_ADJ) {
if (DEBUG_COMPACTION) {
Slog.d(TAG_AM,
"Skipping compaction as process " + name + " is "
@@ -1316,51 +1560,52 @@
return false;
}
- private boolean shouldTimeThrottleCompaction(
- ProcessRecord proc, long start, int pendingAction) {
+ private boolean shouldTimeThrottleCompaction(ProcessRecord proc, long start,
+ CompactProfile pendingProfile, CompactSource source) {
final ProcessCachedOptimizerRecord opt = proc.mOptRecord;
final String name = proc.processName;
- int lastCompactAction = opt.getLastCompactAction();
+ CompactProfile lastCompactProfile = opt.getLastCompactProfile();
long lastCompactTime = opt.getLastCompactTime();
// basic throttling
- // use the Phenotype flag knobs to determine whether current/prevous
- // compaction combo should be throtted or not
-
+ // use the Phenotype flag knobs to determine whether current/previous
+ // compaction combo should be throttled or not.
// Note that we explicitly don't take mPhenotypeFlagLock here as the flags
// should very seldom change, and taking the risk of using the wrong action is
// preferable to taking the lock for every single compaction action.
if (lastCompactTime != 0) {
- if (pendingAction == COMPACT_PROCESS_SOME) {
- if ((lastCompactAction == COMPACT_PROCESS_SOME
- && (start - lastCompactTime < mCompactThrottleSomeSome))
- || (lastCompactAction == COMPACT_PROCESS_FULL
- && (start - lastCompactTime < mCompactThrottleSomeFull))) {
- if (DEBUG_COMPACTION) {
- Slog.d(TAG_AM,
- "Skipping some compaction for " + name
- + ": too soon. throttle=" + mCompactThrottleSomeSome
- + "/" + mCompactThrottleSomeFull
- + " last=" + (start - lastCompactTime) + "ms ago");
+ if (source == CompactSource.APP) {
+ if (pendingProfile == CompactProfile.SOME) {
+ if ((lastCompactProfile == CompactProfile.SOME
+ && (start - lastCompactTime < mCompactThrottleSomeSome))
+ || (lastCompactProfile == CompactProfile.FULL
+ && (start - lastCompactTime < mCompactThrottleSomeFull))) {
+ if (DEBUG_COMPACTION) {
+ Slog.d(TAG_AM,
+ "Skipping some compaction for " + name
+ + ": too soon. throttle=" + mCompactThrottleSomeSome
+ + "/" + mCompactThrottleSomeFull
+ + " last=" + (start - lastCompactTime) + "ms ago");
+ }
+ return true;
}
- return true;
- }
- } else if (pendingAction == COMPACT_PROCESS_FULL) {
- if ((lastCompactAction == COMPACT_PROCESS_SOME
- && (start - lastCompactTime < mCompactThrottleFullSome))
- || (lastCompactAction == COMPACT_PROCESS_FULL
- && (start - lastCompactTime < mCompactThrottleFullFull))) {
- if (DEBUG_COMPACTION) {
- Slog.d(TAG_AM,
- "Skipping full compaction for " + name
- + ": too soon. throttle=" + mCompactThrottleFullSome
- + "/" + mCompactThrottleFullFull
- + " last=" + (start - lastCompactTime) + "ms ago");
+ } else if (pendingProfile == CompactProfile.FULL) {
+ if ((lastCompactProfile == CompactProfile.SOME
+ && (start - lastCompactTime < mCompactThrottleFullSome))
+ || (lastCompactProfile == CompactProfile.FULL
+ && (start - lastCompactTime < mCompactThrottleFullFull))) {
+ if (DEBUG_COMPACTION) {
+ Slog.d(TAG_AM,
+ "Skipping full compaction for " + name
+ + ": too soon. throttle=" + mCompactThrottleFullSome
+ + "/" + mCompactThrottleFullFull
+ + " last=" + (start - lastCompactTime) + "ms ago");
+ }
+ return true;
}
- return true;
}
- } else if (pendingAction == COMPACT_PROCESS_PERSISTENT) {
+ } else if (source == CompactSource.PERSISTENT) {
if (start - lastCompactTime < mCompactThrottlePersistent) {
if (DEBUG_COMPACTION) {
Slog.d(TAG_AM,
@@ -1370,7 +1615,7 @@
}
return true;
}
- } else if (pendingAction == COMPACT_PROCESS_BFGS) {
+ } else if (source == CompactSource.BFGS) {
if (start - lastCompactTime < mCompactThrottleBFGS) {
if (DEBUG_COMPACTION) {
Slog.d(TAG_AM,
@@ -1386,11 +1631,10 @@
return false;
}
- private boolean shouldThrottleMiscCompaction(
- ProcessRecord proc, int procState, int action) {
- final String name = proc.processName;
+ private boolean shouldThrottleMiscCompaction(ProcessRecord proc, int procState) {
if (mProcStateThrottle.contains(procState)) {
if (DEBUG_COMPACTION) {
+ final String name = proc.processName;
Slog.d(TAG_AM,
"Skipping full compaction for process " + name + "; proc state is "
+ procState);
@@ -1398,21 +1642,13 @@
return true;
}
- if (COMPACT_ACTION_NONE == action) {
- if (DEBUG_COMPACTION) {
- Slog.d(TAG_AM,
- "Skipping compaction for process " + name + "since action is None");
- }
- return true;
- }
-
return false;
}
private boolean shouldRssThrottleCompaction(
- int action, int pid, String name, long[] rssBefore) {
+ CompactProfile profile, int pid, String name, long[] rssBefore) {
long anonRssBefore = rssBefore[RSS_ANON_INDEX];
- LastCompactionStats lastCompactionStats = mLastCompactionStats.get(pid);
+ SingleCompactionStats lastCompactionStats = mLastCompactionStats.get(pid);
if (rssBefore[RSS_TOTAL_INDEX] == 0 && rssBefore[RSS_FILE_INDEX] == 0
&& rssBefore[RSS_ANON_INDEX] == 0 && rssBefore[RSS_SWAP_INDEX] == 0) {
@@ -1424,7 +1660,7 @@
return true;
}
- if (action == COMPACT_ACTION_FULL || action == COMPACT_ACTION_ANON) {
+ if (profile == CompactProfile.FULL) {
if (mFullAnonRssThrottleKb > 0L && anonRssBefore < mFullAnonRssThrottleKb) {
if (DEBUG_COMPACTION) {
Slog.d(TAG_AM,
@@ -1461,13 +1697,16 @@
ProcessRecord proc;
final ProcessCachedOptimizerRecord opt;
int pid;
- String action;
+ CompactAction resolvedAction;
final String name;
- int requestedAction, lastCompactAction;
+ CompactProfile lastCompactProfile;
long lastCompactTime;
- int lastOomAdj = msg.arg1;
+ int newOomAdj = msg.arg1;
int procState = msg.arg2;
boolean forceCompaction;
+ CompactSource compactSource;
+ CompactProfile requestedProfile;
+ int oomAdjReason;
synchronized (mProcLock) {
if (mPendingCompactionProcesses.isEmpty()) {
if (DEBUG_COMPACTION) {
@@ -1479,42 +1718,53 @@
opt = proc.mOptRecord;
forceCompaction = opt.isForceCompact();
opt.setForceCompact(false); // since this is a one-shot operation
-
- requestedAction = opt.getReqCompactAction();
pid = proc.getPid();
name = proc.processName;
opt.setHasPendingCompact(false);
- lastCompactAction = opt.getLastCompactAction();
+ compactSource = opt.getReqCompactSource();
+ requestedProfile = opt.getReqCompactProfile();
+ lastCompactProfile = opt.getLastCompactProfile();
lastCompactTime = opt.getLastCompactTime();
+ oomAdjReason = opt.getLastOomAdjChangeReason();
}
- ++mProcCompactionsRequested;
+ AggregatedSourceCompactionStats perSourceStats =
+ getPerSourceAggregatedCompactStat(opt.getReqCompactSource());
+ AggregatedProcessCompactionStats perProcessStats =
+ getPerProcessAggregatedCompactStat(name);
+
long[] rssBefore;
if (pid == 0) {
// not a real process, either one being launched or one being killed
if (DEBUG_COMPACTION) {
Slog.d(TAG_AM, "Compaction failed, pid is 0");
}
- ++mProcCompactionsNoPidThrottled;
+ ++perSourceStats.mProcCompactionsNoPidThrottled;
+ ++perProcessStats.mProcCompactionsNoPidThrottled;
return;
}
if (!forceCompaction) {
- if (shouldOomAdjThrottleCompaction(proc, requestedAction)) {
- ++mProcCompactionsOomAdjThrottled;
+ if (shouldOomAdjThrottleCompaction(proc)) {
+ ++perProcessStats.mProcCompactionsOomAdjThrottled;
+ ++perSourceStats.mProcCompactionsOomAdjThrottled;
return;
}
- if (shouldTimeThrottleCompaction(proc, start, requestedAction)) {
- ++mProcCompactionsTimeThrottled;
+ if (shouldTimeThrottleCompaction(
+ proc, start, requestedProfile, compactSource)) {
+ ++perProcessStats.mProcCompactionsTimeThrottled;
+ ++perSourceStats.mProcCompactionsTimeThrottled;
return;
}
- if (shouldThrottleMiscCompaction(proc, procState, requestedAction)) {
- ++mProcCompactionsMiscThrottled;
+ if (shouldThrottleMiscCompaction(proc, procState)) {
+ ++perProcessStats.mProcCompactionsMiscThrottled;
+ ++perSourceStats.mProcCompactionsMiscThrottled;
return;
}
rssBefore = mProcessDependencies.getRss(pid);
- if (shouldRssThrottleCompaction(requestedAction, pid, name, rssBefore)) {
- ++mProcCompactionsRSSThrottled;
+ if (shouldRssThrottleCompaction(requestedProfile, pid, name, rssBefore)) {
+ ++perProcessStats.mProcCompactionsRSSThrottled;
+ ++perSourceStats.mProcCompactionsRSSThrottled;
return;
}
} else {
@@ -1524,71 +1774,78 @@
}
}
- // Now we've passed through all the throttles and are going to compact, update
- // bookkeeping.
- switch (requestedAction) {
- case COMPACT_PROCESS_SOME:
- mSomeCompactionCount++;
- break;
- case COMPACT_PROCESS_FULL:
- mFullCompactionCount++;
- break;
- case COMPACT_PROCESS_PERSISTENT:
- mPersistentCompactionCount++;
- break;
- case COMPACT_PROCESS_BFGS:
- mBfgsCompactionCount++;
- break;
- default:
- break;
- }
-
- int resolvedAction = resolveCompactionAction(requestedAction);
- action = compactActionIntToString(resolvedAction);
+ CompactProfile resolvedProfile =
+ downgradeCompactionIfRequired(requestedProfile);
+ resolvedAction = resolveCompactActionForProfile(resolvedProfile);
try {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
- "Compact " + action + ": " + name);
- ++mProcCompactionsPerformed;
- long zramFreeKbBefore = Debug.getZramFreeKb();
- mProcessDependencies.performCompaction(action, pid);
+ "Compact " + resolvedAction.name() + ": " + name
+ + " lastOomAdjReason: " + oomAdjReason);
+ long zramUsedKbBefore = getUsedZramMemory();
+ long startCpuTime = threadCpuTimeNs();
+ mProcessDependencies.performCompaction(resolvedAction, pid);
+ long endCpuTime = threadCpuTimeNs();
long[] rssAfter = mProcessDependencies.getRss(pid);
long end = SystemClock.uptimeMillis();
long time = end - start;
- long zramFreeKbAfter = Debug.getZramFreeKb();
+ long deltaCpuTimeNanos = endCpuTime - startCpuTime;
+ long zramUsedKbAfter = getUsedZramMemory();
long deltaTotalRss = rssAfter[RSS_TOTAL_INDEX] - rssBefore[RSS_TOTAL_INDEX];
long deltaFileRss = rssAfter[RSS_FILE_INDEX] - rssBefore[RSS_FILE_INDEX];
long deltaAnonRss = rssAfter[RSS_ANON_INDEX] - rssBefore[RSS_ANON_INDEX];
long deltaSwapRss = rssAfter[RSS_SWAP_INDEX] - rssBefore[RSS_SWAP_INDEX];
- EventLog.writeEvent(EventLogTags.AM_COMPACT, pid, name, action,
- rssBefore[RSS_TOTAL_INDEX], rssBefore[RSS_FILE_INDEX],
- rssBefore[RSS_ANON_INDEX], rssBefore[RSS_SWAP_INDEX], deltaTotalRss,
- deltaFileRss, deltaAnonRss, deltaSwapRss, time, lastCompactAction,
- lastCompactTime, lastOomAdj, procState, zramFreeKbBefore,
- zramFreeKbAfter - zramFreeKbBefore);
- // Note that as above not taking mPhenoTypeFlagLock here to avoid locking
- // on every single compaction for a flag that will seldom change and the
- // impact of reading the wrong value here is low.
- if (mRandom.nextFloat() < mCompactStatsdSampleRate) {
- FrameworkStatsLog.write(FrameworkStatsLog.APP_COMPACTED, pid, name,
- requestedAction, rssBefore[RSS_TOTAL_INDEX],
- rssBefore[RSS_FILE_INDEX], rssBefore[RSS_ANON_INDEX],
- rssBefore[RSS_SWAP_INDEX], rssAfter[RSS_TOTAL_INDEX],
- rssAfter[RSS_FILE_INDEX], rssAfter[RSS_ANON_INDEX],
- rssAfter[RSS_SWAP_INDEX], time, lastCompactAction,
- lastCompactTime, lastOomAdj,
- ActivityManager.processStateAmToProto(procState),
- zramFreeKbBefore, zramFreeKbAfter);
+ switch (opt.getReqCompactProfile()) {
+ case SOME:
+ ++perSourceStats.mSomeCompactPerformed;
+ ++perProcessStats.mSomeCompactPerformed;
+ break;
+ case FULL:
+ ++perSourceStats.mFullCompactPerformed;
+ ++perProcessStats.mFullCompactPerformed;
+ long anonRssSavings = -deltaAnonRss;
+ long zramConsumed = zramUsedKbAfter - zramUsedKbBefore;
+ long memFreed = anonRssSavings - zramConsumed;
+ long totalCpuTimeMillis = deltaCpuTimeNanos / 1000000;
+ long origAnonRss = rssBefore[RSS_ANON_INDEX];
+
+ // Negative stats would skew averages and will likely be due to
+ // noise of system doing other things so we put a floor at 0 to
+ // avoid negative values.
+ anonRssSavings = anonRssSavings > 0 ? anonRssSavings : 0;
+ zramConsumed = zramConsumed > 0 ? zramConsumed : 0;
+ memFreed = memFreed > 0 ? memFreed : 0;
+
+ perProcessStats.addMemStats(anonRssSavings, zramConsumed, memFreed,
+ origAnonRss, totalCpuTimeMillis);
+ perSourceStats.addMemStats(anonRssSavings, zramConsumed, memFreed,
+ origAnonRss, totalCpuTimeMillis);
+ SingleCompactionStats memStats = new SingleCompactionStats(rssAfter,
+ compactSource, name, anonRssSavings, zramConsumed, memFreed,
+ origAnonRss, totalCpuTimeMillis, procState, newOomAdj,
+ oomAdjReason, proc.uid);
+ mLastCompactionStats.remove(pid);
+ mLastCompactionStats.put(pid, memStats);
+ mCompactionStatsHistory.add(memStats);
+ memStats.sendStat();
+ break;
+ default:
+ // We likely missed adding this category, it needs to be added
+ // if we end up here. In the meantime, gracefully fallback to
+ // attribute to app.
+ Slog.wtf(TAG_AM, "Compaction: Unknown requested action");
+ return;
}
+ EventLog.writeEvent(EventLogTags.AM_COMPACT, pid, name,
+ resolvedAction.name(), rssBefore[RSS_TOTAL_INDEX],
+ rssBefore[RSS_FILE_INDEX], rssBefore[RSS_ANON_INDEX],
+ rssBefore[RSS_SWAP_INDEX], deltaTotalRss, deltaFileRss,
+ deltaAnonRss, deltaSwapRss, time, lastCompactProfile.name(),
+ lastCompactTime, newOomAdj, procState, zramUsedKbBefore,
+ zramUsedKbBefore - zramUsedKbAfter);
synchronized (mProcLock) {
opt.setLastCompactTime(end);
- opt.setLastCompactAction(resolvedAction);
- }
- if (resolvedAction == COMPACT_ACTION_FULL
- || resolvedAction == COMPACT_ACTION_ANON) {
- // Remove entry and insert again to update insertion order.
- mLastCompactionStats.remove(pid);
- mLastCompactionStats.put(pid, new LastCompactionStats(rssAfter));
+ opt.setLastCompactProfile(requestedProfile);
}
} catch (Exception e) {
// nothing to do, presumably the process died
@@ -1603,7 +1860,10 @@
case COMPACT_SYSTEM_MSG: {
++mSystemCompactionsPerformed;
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "compactSystem");
+ long memFreedBefore = getMemoryFreedCompaction();
compactSystem();
+ long memFreedAfter = getMemoryFreedCompaction();
+ mSystemTotalMemFreed += memFreedAfter - memFreedBefore;
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
@@ -1809,14 +2069,14 @@
// Compact process.
@Override
- public void performCompaction(String action, int pid) throws IOException {
+ public void performCompaction(CompactAction action, int pid) throws IOException {
mPidCompacting = pid;
- if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_FULL])) {
- compactProcess(pid, COMPACT_ACTION_FILE_FLAG | COMPACT_ACTION_ANON_FLAG);
- } else if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_FILE])) {
- compactProcess(pid, COMPACT_ACTION_FILE_FLAG);
- } else if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_ANON])) {
- compactProcess(pid, COMPACT_ACTION_ANON_FLAG);
+ if (action == CompactAction.ALL) {
+ compactProcess(pid, COMPACT_ACTION_FILE_FLAG | COMPACT_ACTION_ANON_FLAG);
+ } else if (action == CompactAction.FILE) {
+ compactProcess(pid, COMPACT_ACTION_FILE_FLAG);
+ } else if (action == CompactAction.ANON) {
+ compactProcess(pid, COMPACT_ACTION_ANON_FLAG);
}
mPidCompacting = -1;
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 9607e40..8759f230 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -76,9 +76,11 @@
import static com.android.server.am.ProcessList.TAG_PROCESS_OBSERVERS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityThread;
+import android.app.AppProtoEnums;
import android.app.ApplicationExitInfo;
import android.app.usage.UsageEvents;
import android.compat.annotation.ChangeId;
@@ -113,6 +115,8 @@
import com.android.server.wm.WindowProcessController;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
@@ -122,20 +126,97 @@
*/
public class OomAdjuster {
static final String TAG = "OomAdjuster";
- static final String OOM_ADJ_REASON_METHOD = "updateOomAdj";
- static final String OOM_ADJ_REASON_NONE = OOM_ADJ_REASON_METHOD + "_meh";
- static final String OOM_ADJ_REASON_ACTIVITY = OOM_ADJ_REASON_METHOD + "_activityChange";
- static final String OOM_ADJ_REASON_FINISH_RECEIVER = OOM_ADJ_REASON_METHOD + "_finishReceiver";
- static final String OOM_ADJ_REASON_START_RECEIVER = OOM_ADJ_REASON_METHOD + "_startReceiver";
- static final String OOM_ADJ_REASON_BIND_SERVICE = OOM_ADJ_REASON_METHOD + "_bindService";
- static final String OOM_ADJ_REASON_UNBIND_SERVICE = OOM_ADJ_REASON_METHOD + "_unbindService";
- static final String OOM_ADJ_REASON_START_SERVICE = OOM_ADJ_REASON_METHOD + "_startService";
- static final String OOM_ADJ_REASON_GET_PROVIDER = OOM_ADJ_REASON_METHOD + "_getProvider";
- static final String OOM_ADJ_REASON_REMOVE_PROVIDER = OOM_ADJ_REASON_METHOD + "_removeProvider";
- static final String OOM_ADJ_REASON_UI_VISIBILITY = OOM_ADJ_REASON_METHOD + "_uiVisibility";
- static final String OOM_ADJ_REASON_ALLOWLIST = OOM_ADJ_REASON_METHOD + "_allowlistChange";
- static final String OOM_ADJ_REASON_PROCESS_BEGIN = OOM_ADJ_REASON_METHOD + "_processBegin";
- static final String OOM_ADJ_REASON_PROCESS_END = OOM_ADJ_REASON_METHOD + "_processEnd";
+
+ static final int OOM_ADJ_REASON_NONE = 0;
+ static final int OOM_ADJ_REASON_ACTIVITY = 1;
+ static final int OOM_ADJ_REASON_FINISH_RECEIVER = 2;
+ static final int OOM_ADJ_REASON_START_RECEIVER = 3;
+ static final int OOM_ADJ_REASON_BIND_SERVICE = 4;
+ static final int OOM_ADJ_REASON_UNBIND_SERVICE = 5;
+ static final int OOM_ADJ_REASON_START_SERVICE = 6;
+ static final int OOM_ADJ_REASON_GET_PROVIDER = 7;
+ static final int OOM_ADJ_REASON_REMOVE_PROVIDER = 8;
+ static final int OOM_ADJ_REASON_UI_VISIBILITY = 9;
+ static final int OOM_ADJ_REASON_ALLOWLIST = 10;
+ static final int OOM_ADJ_REASON_PROCESS_BEGIN = 11;
+ static final int OOM_ADJ_REASON_PROCESS_END = 12;
+
+ @IntDef(prefix = {"OOM_ADJ_REASON_"},
+ value = {OOM_ADJ_REASON_NONE, OOM_ADJ_REASON_ACTIVITY, OOM_ADJ_REASON_FINISH_RECEIVER,
+ OOM_ADJ_REASON_START_RECEIVER, OOM_ADJ_REASON_BIND_SERVICE,
+ OOM_ADJ_REASON_UNBIND_SERVICE, OOM_ADJ_REASON_START_SERVICE,
+ OOM_ADJ_REASON_GET_PROVIDER, OOM_ADJ_REASON_REMOVE_PROVIDER,
+ OOM_ADJ_REASON_UI_VISIBILITY, OOM_ADJ_REASON_ALLOWLIST,
+ OOM_ADJ_REASON_PROCESS_BEGIN, OOM_ADJ_REASON_PROCESS_END})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface OomAdjReason {}
+
+ public static final int oomAdjReasonToProto(@OomAdjReason int oomReason) {
+ switch (oomReason) {
+ case OOM_ADJ_REASON_NONE:
+ return AppProtoEnums.OOM_ADJ_REASON_NONE;
+ case OOM_ADJ_REASON_ACTIVITY:
+ return AppProtoEnums.OOM_ADJ_REASON_ACTIVITY;
+ case OOM_ADJ_REASON_FINISH_RECEIVER:
+ return AppProtoEnums.OOM_ADJ_REASON_FINISH_RECEIVER;
+ case OOM_ADJ_REASON_START_RECEIVER:
+ return AppProtoEnums.OOM_ADJ_REASON_START_RECEIVER;
+ case OOM_ADJ_REASON_BIND_SERVICE:
+ return AppProtoEnums.OOM_ADJ_REASON_BIND_SERVICE;
+ case OOM_ADJ_REASON_UNBIND_SERVICE:
+ return AppProtoEnums.OOM_ADJ_REASON_UNBIND_SERVICE;
+ case OOM_ADJ_REASON_START_SERVICE:
+ return AppProtoEnums.OOM_ADJ_REASON_START_SERVICE;
+ case OOM_ADJ_REASON_GET_PROVIDER:
+ return AppProtoEnums.OOM_ADJ_REASON_GET_PROVIDER;
+ case OOM_ADJ_REASON_REMOVE_PROVIDER:
+ return AppProtoEnums.OOM_ADJ_REASON_REMOVE_PROVIDER;
+ case OOM_ADJ_REASON_UI_VISIBILITY:
+ return AppProtoEnums.OOM_ADJ_REASON_UI_VISIBILITY;
+ case OOM_ADJ_REASON_ALLOWLIST:
+ return AppProtoEnums.OOM_ADJ_REASON_ALLOWLIST;
+ case OOM_ADJ_REASON_PROCESS_BEGIN:
+ return AppProtoEnums.OOM_ADJ_REASON_PROCESS_BEGIN;
+ case OOM_ADJ_REASON_PROCESS_END:
+ return AppProtoEnums.OOM_ADJ_REASON_PROCESS_END;
+ default:
+ return AppProtoEnums.OOM_ADJ_REASON_UNKNOWN_TO_PROTO;
+ }
+ }
+
+ public static final String oomAdjReasonToString(@OomAdjReason int oomReason) {
+ final String OOM_ADJ_REASON_METHOD = "updateOomAdj";
+ switch (oomReason) {
+ case OOM_ADJ_REASON_NONE:
+ return OOM_ADJ_REASON_METHOD + "_meh";
+ case OOM_ADJ_REASON_ACTIVITY:
+ return OOM_ADJ_REASON_METHOD + "_activityChange";
+ case OOM_ADJ_REASON_FINISH_RECEIVER:
+ return OOM_ADJ_REASON_METHOD + "_finishReceiver";
+ case OOM_ADJ_REASON_START_RECEIVER:
+ return OOM_ADJ_REASON_METHOD + "_startReceiver";
+ case OOM_ADJ_REASON_BIND_SERVICE:
+ return OOM_ADJ_REASON_METHOD + "_bindService";
+ case OOM_ADJ_REASON_UNBIND_SERVICE:
+ return OOM_ADJ_REASON_METHOD + "_unbindService";
+ case OOM_ADJ_REASON_START_SERVICE:
+ return OOM_ADJ_REASON_METHOD + "_startService";
+ case OOM_ADJ_REASON_GET_PROVIDER:
+ return OOM_ADJ_REASON_METHOD + "_getProvider";
+ case OOM_ADJ_REASON_REMOVE_PROVIDER:
+ return OOM_ADJ_REASON_METHOD + "_removeProvider";
+ case OOM_ADJ_REASON_UI_VISIBILITY:
+ return OOM_ADJ_REASON_METHOD + "_uiVisibility";
+ case OOM_ADJ_REASON_ALLOWLIST:
+ return OOM_ADJ_REASON_METHOD + "_allowlistChange";
+ case OOM_ADJ_REASON_PROCESS_BEGIN:
+ return OOM_ADJ_REASON_METHOD + "_processBegin";
+ case OOM_ADJ_REASON_PROCESS_END:
+ return OOM_ADJ_REASON_METHOD + "_processEnd";
+ default:
+ return "_unknown";
+ }
+ }
/**
* Flag {@link android.content.Context#BIND_INCLUDE_CAPABILITIES} is used
@@ -418,14 +499,14 @@
* Update OomAdj for all processes in LRU list
*/
@GuardedBy("mService")
- void updateOomAdjLocked(String oomAdjReason) {
+ void updateOomAdjLocked(@OomAdjReason int oomAdjReason) {
synchronized (mProcLock) {
updateOomAdjLSP(oomAdjReason);
}
}
@GuardedBy({"mService", "mProcLock"})
- private void updateOomAdjLSP(String oomAdjReason) {
+ private void updateOomAdjLSP(@OomAdjReason int oomAdjReason) {
if (checkAndEnqueueOomAdjTargetLocked(null)) {
// Simply return as there is an oomAdjUpdate ongoing
return;
@@ -441,7 +522,7 @@
}
@GuardedBy({"mService", "mProcLock"})
- private void performUpdateOomAdjLSP(String oomAdjReason) {
+ private void performUpdateOomAdjLSP(@OomAdjReason int oomAdjReason) {
final ProcessRecord topApp = mService.getTopApp();
// Clear any pending ones because we are doing a full update now.
mPendingProcessSet.clear();
@@ -458,14 +539,14 @@
* @param oomAdjReason
*/
@GuardedBy("mService")
- boolean updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
+ boolean updateOomAdjLocked(ProcessRecord app, @OomAdjReason int oomAdjReason) {
synchronized (mProcLock) {
return updateOomAdjLSP(app, oomAdjReason);
}
}
@GuardedBy({"mService", "mProcLock"})
- private boolean updateOomAdjLSP(ProcessRecord app, String oomAdjReason) {
+ private boolean updateOomAdjLSP(ProcessRecord app, @OomAdjReason int oomAdjReason) {
if (app == null || !mConstants.OOMADJ_UPDATE_QUICK) {
updateOomAdjLSP(oomAdjReason);
return true;
@@ -487,10 +568,10 @@
}
@GuardedBy({"mService", "mProcLock"})
- private boolean performUpdateOomAdjLSP(ProcessRecord app, String oomAdjReason) {
+ private boolean performUpdateOomAdjLSP(ProcessRecord app, @OomAdjReason int oomAdjReason) {
final ProcessRecord topApp = mService.getTopApp();
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
mService.mOomAdjProfiler.oomAdjStarted();
mAdjSeq++;
@@ -509,6 +590,7 @@
state.setCurBoundByNonBgRestrictedApp(false);
// Check if this process is in the pending list too, remove from pending list if so.
mPendingProcessSet.remove(app);
+ app.mOptRecord.setLastOomAdjChangeReason(oomAdjReason);
boolean success = performUpdateOomAdjLSP(app, cachedAdj, topApp,
SystemClock.uptimeMillis());
// The 'app' here itself might or might not be in the cycle, for example,
@@ -688,7 +770,7 @@
* {@link #enqueueOomAdjTargetLocked}.
*/
@GuardedBy("mService")
- void updateOomAdjPendingTargetsLocked(String oomAdjReason) {
+ void updateOomAdjPendingTargetsLocked(@OomAdjReason int oomAdjReason) {
// First check if there is pending full update
if (mPendingFullOomAdjUpdate) {
mPendingFullOomAdjUpdate = false;
@@ -716,10 +798,11 @@
}
@GuardedBy("mService")
- private void performUpdateOomAdjPendingTargetsLocked(String oomAdjReason) {
+ private void performUpdateOomAdjPendingTargetsLocked(
+ @OomAdjuster.OomAdjReason int oomAdjReason) {
final ProcessRecord topApp = mService.getTopApp();
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
mService.mOomAdjProfiler.oomAdjStarted();
final ArrayList<ProcessRecord> processes = mTmpProcessList;
@@ -741,11 +824,11 @@
* get evaluated recursively here.
*/
@GuardedBy({"mService", "mProcLock"})
- private void updateOomAdjInnerLSP(String oomAdjReason, final ProcessRecord topApp,
+ private void updateOomAdjInnerLSP(@OomAdjReason int oomAdjReason, final ProcessRecord topApp,
ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,
boolean startProfiling) {
if (startProfiling) {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
mService.mOomAdjProfiler.oomAdjStarted();
}
final long now = SystemClock.uptimeMillis();
@@ -806,6 +889,7 @@
final ProcessStateRecord state = app.mState;
if (!app.isKilledByAm() && app.getThread() != null) {
state.setProcStateChanged(false);
+ app.mOptRecord.setLastOomAdjChangeReason(oomAdjReason);
computeOomAdjLSP(app, ProcessList.UNKNOWN_ADJ, topApp, fullUpdate, now, false,
computeClients); // It won't enter cycle if not computing clients.
// if any app encountered a cycle, we need to perform an additional loop later
@@ -2582,11 +2666,13 @@
// processing of the requests. As a result, there is throttling both here
// and in CachedAppOptimizer.
&& mCachedAppOptimizer.shouldCompactPersistent(app, now)) {
- mCachedAppOptimizer.compactAppPersistent(app);
+ mCachedAppOptimizer.compactApp(app, CachedAppOptimizer.CompactProfile.FULL,
+ CachedAppOptimizer.CompactSource.PERSISTENT, false);
} else if (state.getCurProcState()
== ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
&& mCachedAppOptimizer.shouldCompactBFGS(app, now)) {
- mCachedAppOptimizer.compactAppBfgs(app);
+ mCachedAppOptimizer.compactApp(app, CachedAppOptimizer.CompactProfile.FULL,
+ CachedAppOptimizer.CompactSource.BFGS, false);
}
}
}
diff --git a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
index a613729..fb41a39 100644
--- a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
+++ b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
@@ -39,16 +39,24 @@
private long mLastCompactTime;
/**
- * The most recent compaction action requested for this app.
+ * The most recent compaction profile requested for this app.
*/
- @GuardedBy("mProcLock")
- private int mReqCompactAction;
+ @GuardedBy("mProcLock") private CachedAppOptimizer.CompactProfile mReqCompactProfile;
+
+ /**
+ * Source that requested the latest compaction for this app.
+ */
+ @GuardedBy("mProcLock") private CachedAppOptimizer.CompactSource mReqCompactSource;
+
+ /**
+ * Last oom adjust change reason for this app.
+ */
+ @GuardedBy("mProcLock") private @OomAdjuster.OomAdjReason int mLastOomAdjChangeReason;
/**
* The most recent compaction action performed for this app.
*/
- @GuardedBy("mProcLock")
- private int mLastCompactAction;
+ @GuardedBy("mProcLock") private CachedAppOptimizer.CompactProfile mLastCompactProfile;
/**
* This process has been scheduled for a memory compaction.
@@ -105,23 +113,49 @@
}
@GuardedBy("mProcLock")
- int getReqCompactAction() {
- return mReqCompactAction;
+ CachedAppOptimizer.CompactProfile getReqCompactProfile() {
+ return mReqCompactProfile;
}
@GuardedBy("mProcLock")
- void setReqCompactAction(int reqCompactAction) {
- mReqCompactAction = reqCompactAction;
+ void setReqCompactProfile(CachedAppOptimizer.CompactProfile reqCompactProfile) {
+ mReqCompactProfile = reqCompactProfile;
}
@GuardedBy("mProcLock")
- int getLastCompactAction() {
- return mLastCompactAction;
+ CachedAppOptimizer.CompactSource getReqCompactSource() {
+ return mReqCompactSource;
}
@GuardedBy("mProcLock")
- void setLastCompactAction(int lastCompactAction) {
- mLastCompactAction = lastCompactAction;
+ void setReqCompactSource(CachedAppOptimizer.CompactSource stat) {
+ mReqCompactSource = stat;
+ }
+
+ @GuardedBy("mProcLock")
+ void setLastOomAdjChangeReason(@OomAdjuster.OomAdjReason int reason) {
+ mLastOomAdjChangeReason = reason;
+ }
+
+ @GuardedBy("mProcLock")
+ @OomAdjuster.OomAdjReason
+ int getLastOomAdjChangeReason() {
+ return mLastOomAdjChangeReason;
+ }
+
+ @GuardedBy("mProcLock")
+ CachedAppOptimizer.CompactProfile getLastCompactProfile() {
+ if (mLastCompactProfile == null) {
+ // The first compaction won't have a previous one, so assign one to avoid crashing.
+ mLastCompactProfile = CachedAppOptimizer.CompactProfile.SOME;
+ }
+
+ return mLastCompactProfile;
+ }
+
+ @GuardedBy("mProcLock")
+ void setLastCompactProfile(CachedAppOptimizer.CompactProfile lastCompactProfile) {
+ mLastCompactProfile = lastCompactProfile;
}
@GuardedBy("mProcLock")
@@ -216,7 +250,8 @@
@GuardedBy("mProcLock")
void dump(PrintWriter pw, String prefix, long nowUptime) {
pw.print(prefix); pw.print("lastCompactTime="); pw.print(mLastCompactTime);
- pw.print(" lastCompactAction="); pw.println(mLastCompactAction);
+ pw.print(" lastCompactProfile=");
+ pw.println(mLastCompactProfile);
pw.print(prefix);
pw.print("hasPendingCompaction=");
pw.print(mPendingCompact);
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index dd73cbe..854b818 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -25,20 +25,6 @@
import static com.android.internal.R.styleable.GameModeConfig_allowGameFpsOverride;
import static com.android.internal.R.styleable.GameModeConfig_supportsBatteryGameMode;
import static com.android.internal.R.styleable.GameModeConfig_supportsPerformanceGameMode;
-import static com.android.server.wm.CompatModePackages.DOWNSCALED;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_30;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_35;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_40;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_45;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_50;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_55;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_60;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_65;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_70;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_75;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_80;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_85;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_90;
import android.Manifest;
import android.annotation.NonNull;
@@ -48,10 +34,10 @@
import android.app.ActivityManager;
import android.app.GameManager;
import android.app.GameManager.GameMode;
+import android.app.GameManagerInternal;
import android.app.GameModeInfo;
import android.app.GameState;
import android.app.IGameManagerService;
-import android.app.compat.PackageOverride;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -75,9 +61,7 @@
import android.os.Message;
import android.os.PowerManagerInternal;
import android.os.Process;
-import android.os.RemoteException;
import android.os.ResultReceiver;
-import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.UserManager;
import android.provider.DeviceConfig;
@@ -92,8 +76,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.compat.CompatibilityOverrideConfig;
-import com.android.internal.compat.IPlatformCompat;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
@@ -140,10 +122,6 @@
static final int WRITE_SETTINGS_DELAY = 10 * 1000; // 10 seconds
static final int LOADING_BOOST_MAX_DURATION = 5 * 1000; // 5 seconds
- static final PackageOverride COMPAT_ENABLED = new PackageOverride.Builder().setEnabled(true)
- .build();
- static final PackageOverride COMPAT_DISABLED = new PackageOverride.Builder().setEnabled(false)
- .build();
private static final String PACKAGE_NAME_MSG_KEY = "packageName";
private static final String USER_ID_MSG_KEY = "userId";
private static final String GAME_MODE_INTERVENTION_LIST_FILE_NAME =
@@ -156,7 +134,6 @@
private final Handler mHandler;
private final PackageManager mPackageManager;
private final UserManager mUserManager;
- private final IPlatformCompat mPlatformCompat;
private final PowerManagerInternal mPowerManagerInternal;
private final File mSystemDir;
@VisibleForTesting
@@ -180,8 +157,6 @@
mHandler = new SettingsHandler(looper);
mPackageManager = mContext.getPackageManager();
mUserManager = mContext.getSystemService(UserManager.class);
- mPlatformCompat = IPlatformCompat.Stub.asInterface(
- ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mSystemDir = new File(Environment.getDataDirectory(), "system");
mSystemDir.mkdirs();
@@ -212,8 +187,6 @@
mHandler = new SettingsHandler(looper);
mPackageManager = mContext.getPackageManager();
mUserManager = mContext.getSystemService(UserManager.class);
- mPlatformCompat = IPlatformCompat.Stub.asInterface(
- ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mSystemDir = new File(dataDir, "system");
mSystemDir.mkdirs();
@@ -326,14 +299,10 @@
break;
}
case POPULATE_GAME_MODE_SETTINGS: {
- // Scan all game packages and re-enforce the configured compat mode overrides
- // as the DeviceConfig may have be wiped/since last reboot and we can't risk
- // having overrides configured for packages that no longer have any DeviceConfig
- // and thus any way to escape compat mode.
removeMessages(POPULATE_GAME_MODE_SETTINGS, msg.obj);
final int userId = (int) msg.obj;
final String[] packageNames = getInstalledGamePackageNames(userId);
- updateConfigsForUser(userId, packageNames);
+ updateConfigsForUser(userId, false /*checkGamePackage*/, packageNames);
break;
}
case SET_GAME_STATE: {
@@ -402,7 +371,8 @@
@Override
public void onPropertiesChanged(Properties properties) {
final String[] packageNames = properties.getKeyset().toArray(new String[0]);
- updateConfigsForUser(ActivityManager.getCurrentUser(), packageNames);
+ updateConfigsForUser(ActivityManager.getCurrentUser(), true /*checkGamePackage*/,
+ packageNames);
}
@Override
@@ -411,39 +381,6 @@
}
}
- // Turn the raw string to the corresponding CompatChange id.
- static long getCompatChangeId(String raw) {
- switch (raw) {
- case "0.3":
- return DOWNSCALE_30;
- case "0.35":
- return DOWNSCALE_35;
- case "0.4":
- return DOWNSCALE_40;
- case "0.45":
- return DOWNSCALE_45;
- case "0.5":
- return DOWNSCALE_50;
- case "0.55":
- return DOWNSCALE_55;
- case "0.6":
- return DOWNSCALE_60;
- case "0.65":
- return DOWNSCALE_65;
- case "0.7":
- return DOWNSCALE_70;
- case "0.75":
- return DOWNSCALE_75;
- case "0.8":
- return DOWNSCALE_80;
- case "0.85":
- return DOWNSCALE_85;
- case "0.9":
- return DOWNSCALE_90;
- }
- return 0;
- }
-
public enum FrameRate {
FPS_DEFAULT(0),
FPS_30(30),
@@ -553,7 +490,9 @@
private static final String GAME_MODE_CONFIG_NODE_NAME = "game-mode-config";
private final String mPackageName;
- private final ArrayMap<Integer, GameModeConfiguration> mModeConfigs;
+ private final Object mModeConfigLock = new Object();
+ @GuardedBy("mModeConfigLock")
+ private final ArrayMap<Integer, GameModeConfiguration> mModeConfigs = new ArrayMap<>();
private boolean mPerfModeOptedIn;
private boolean mBatteryModeOptedIn;
private boolean mAllowDownscale;
@@ -562,7 +501,6 @@
GamePackageConfiguration(String packageName, int userId) {
mPackageName = packageName;
- mModeConfigs = new ArrayMap<>();
try {
final ApplicationInfo ai = mPackageManager.getApplicationInfoAsUser(packageName,
PackageManager.GET_META_DATA, userId);
@@ -647,6 +585,13 @@
return xmlFound;
}
+ GameModeConfiguration getOrAddDefaultGameModeConfiguration(int gameMode) {
+ synchronized (mModeConfigLock) {
+ mModeConfigs.putIfAbsent(gameMode, new GameModeConfiguration(gameMode));
+ return mModeConfigs.get(gameMode);
+ }
+ }
+
/**
* GameModeConfiguration contains all the values for all the interventions associated with
* a game mode.
@@ -657,17 +602,26 @@
public static final String MODE_KEY = "mode";
public static final String SCALING_KEY = "downscaleFactor";
public static final String FPS_KEY = "fps";
- public static final String DEFAULT_SCALING = "1.0";
- public static final String DEFAULT_FPS = "";
public static final String ANGLE_KEY = "useAngle";
public static final String LOADING_BOOST_KEY = "loadingBoost";
+ public static final float DEFAULT_SCALING = -1f;
+ public static final String DEFAULT_FPS = "";
+ public static final boolean DEFAULT_USE_ANGLE = false;
+ public static final int DEFAULT_LOADING_BOOST_DURATION = -1;
+
private final @GameMode int mGameMode;
- private String mScaling;
- private String mFps;
+ private float mScaling = DEFAULT_SCALING;
+ private String mFps = DEFAULT_FPS;
private final boolean mUseAngle;
private final int mLoadingBoostDuration;
+ GameModeConfiguration(int gameMode) {
+ mGameMode = gameMode;
+ mUseAngle = DEFAULT_USE_ANGLE;
+ mLoadingBoostDuration = DEFAULT_LOADING_BOOST_DURATION;
+ }
+
GameModeConfiguration(KeyValueListParser parser) {
mGameMode = parser.getInt(MODE_KEY, GameManager.GAME_MODE_UNSUPPORTED);
// isGameModeOptedIn() returns if an app will handle all of the changes necessary
@@ -675,7 +629,7 @@
// GameManagerService) will not do anything for the app (like window scaling or
// using ANGLE).
mScaling = !mAllowDownscale || willGamePerformOptimizations(mGameMode)
- ? DEFAULT_SCALING : parser.getString(SCALING_KEY, DEFAULT_SCALING);
+ ? DEFAULT_SCALING : parser.getFloat(SCALING_KEY, DEFAULT_SCALING);
mFps = mAllowFpsOverride && !willGamePerformOptimizations(mGameMode)
? parser.getString(FPS_KEY, DEFAULT_FPS) : DEFAULT_FPS;
@@ -684,21 +638,22 @@
// - The app has not opted in to performing the work itself AND
// - The Phenotype config has enabled it.
mUseAngle = mAllowAngle && !willGamePerformOptimizations(mGameMode)
- && parser.getBoolean(ANGLE_KEY, false);
+ && parser.getBoolean(ANGLE_KEY, DEFAULT_USE_ANGLE);
- mLoadingBoostDuration = willGamePerformOptimizations(mGameMode) ? -1
- : parser.getInt(LOADING_BOOST_KEY, -1);
+ mLoadingBoostDuration = willGamePerformOptimizations(mGameMode)
+ ? DEFAULT_LOADING_BOOST_DURATION
+ : parser.getInt(LOADING_BOOST_KEY, DEFAULT_LOADING_BOOST_DURATION);
}
public int getGameMode() {
return mGameMode;
}
- public String getScaling() {
+ public synchronized float getScaling() {
return mScaling;
}
- public int getFps() {
+ public synchronized int getFps() {
return GameManagerService.getFpsInt(mFps);
}
@@ -710,15 +665,15 @@
return mLoadingBoostDuration;
}
- public void setScaling(String scaling) {
+ public synchronized void setScaling(float scaling) {
mScaling = scaling;
}
- public void setFpsStr(String fpsStr) {
+ public synchronized void setFpsStr(String fpsStr) {
mFps = fpsStr;
}
- public boolean isValid() {
+ public boolean isActive() {
return (mGameMode == GameManager.GAME_MODE_STANDARD
|| mGameMode == GameManager.GAME_MODE_PERFORMANCE
|| mGameMode == GameManager.GAME_MODE_BATTERY)
@@ -733,13 +688,6 @@
+ mUseAngle + ",Fps:" + mFps + ",Loading Boost Duration:"
+ mLoadingBoostDuration + "]";
}
-
- /**
- * Get the corresponding compat change id for the current scaling string.
- */
- public long getCompatChangeId() {
- return GameManagerService.getCompatChangeId(mScaling);
- }
}
public String getPackageName() {
@@ -761,8 +709,10 @@
private int getAvailableGameModesBitfield() {
int field = 0;
- for (final int mode : mModeConfigs.keySet()) {
- field |= modeToBitmask(mode);
+ synchronized (mModeConfigLock) {
+ for (final int mode : mModeConfigs.keySet()) {
+ field |= modeToBitmask(mode);
+ }
}
if (mBatteryModeOptedIn) {
field |= modeToBitmask(GameManager.GAME_MODE_BATTERY);
@@ -803,27 +753,43 @@
* @return The package's GameModeConfiguration for the provided mode or null if absent
*/
public GameModeConfiguration getGameModeConfiguration(@GameMode int gameMode) {
- return mModeConfigs.get(gameMode);
+ synchronized (mModeConfigLock) {
+ return mModeConfigs.get(gameMode);
+ }
}
/**
- * Insert a new GameModeConfiguration
+ * Inserts a new GameModeConfiguration
*/
public void addModeConfig(GameModeConfiguration config) {
- if (config.isValid()) {
- mModeConfigs.put(config.getGameMode(), config);
+ if (config.isActive()) {
+ synchronized (mModeConfigLock) {
+ mModeConfigs.put(config.getGameMode(), config);
+ }
} else {
- Slog.w(TAG, "Invalid game mode config for "
+ Slog.w(TAG, "Attempt to add inactive game mode config for "
+ mPackageName + ":" + config.toString());
}
}
- public boolean isValid() {
- return mModeConfigs.size() > 0 || mBatteryModeOptedIn || mPerfModeOptedIn;
+ public boolean isActive() {
+ synchronized (mModeConfigLock) {
+ return mModeConfigs.size() > 0 || mBatteryModeOptedIn || mPerfModeOptedIn;
+ }
}
public String toString() {
- return "[Name:" + mPackageName + " Modes: " + mModeConfigs.toString() + "]";
+ synchronized (mModeConfigLock) {
+ return "[Name:" + mPackageName + " Modes: " + mModeConfigs.toString() + "]";
+ }
+ }
+ }
+
+ private final class LocalService extends GameManagerInternal {
+ @Override
+ public float getResolutionScalingFactor(String packageName, int userId) {
+ final int gameMode = getGameModeFromSettings(packageName, userId);
+ return getResolutionScalingFactorInternal(packageName, gameMode, userId);
}
}
@@ -837,13 +803,13 @@
public Lifecycle(Context context) {
super(context);
+ mService = new GameManagerService(context);
}
@Override
public void onStart() {
- final Context context = getContext();
- mService = new GameManagerService(context);
publishBinderService(Context.GAME_SERVICE, mService);
+ mService.publishLocalService();
mService.registerDeviceConfigListener();
mService.registerPackageReceiver();
}
@@ -894,15 +860,7 @@
}
private @GameMode int[] getAvailableGameModesUnchecked(String packageName) {
- GamePackageConfiguration config = null;
- synchronized (mOverrideConfigLock) {
- config = mOverrideConfigs.get(packageName);
- }
- if (config == null) {
- synchronized (mDeviceConfigLock) {
- config = mConfigs.get(packageName);
- }
- }
+ final GamePackageConfiguration config = getConfig(packageName);
if (config == null) {
return new int[]{};
}
@@ -933,8 +891,8 @@
private @GameMode int getGameModeFromSettings(String packageName, @UserIdInt int userId) {
synchronized (mLock) {
if (!mSettings.containsKey(userId)) {
- Slog.w(TAG, "User ID '" + userId + "' does not have a Game Mode"
- + " selected for package: '" + packageName + "'");
+ Slog.d(TAG, "User ID '" + userId + "' does not have a Game Mode"
+ + " selected for package: '" + packageName + "'");
return GameManager.GAME_MODE_UNSUPPORTED;
}
@@ -1055,19 +1013,19 @@
if (gameMode == GameManager.GAME_MODE_UNSUPPORTED) {
return false;
}
-
+ final GamePackageConfiguration config;
synchronized (mDeviceConfigLock) {
- final GamePackageConfiguration config = mConfigs.get(packageName);
+ config = mConfigs.get(packageName);
if (config == null) {
return false;
}
- GamePackageConfiguration.GameModeConfiguration gameModeConfiguration =
- config.getGameModeConfiguration(gameMode);
- if (gameModeConfiguration == null) {
- return false;
- }
- return gameModeConfiguration.getUseAngle();
}
+ GamePackageConfiguration.GameModeConfiguration gameModeConfiguration =
+ config.getGameModeConfiguration(gameMode);
+ if (gameModeConfiguration == null) {
+ return false;
+ }
+ return gameModeConfiguration.getUseAngle();
}
/**
@@ -1082,19 +1040,19 @@
if (gameMode == GameManager.GAME_MODE_UNSUPPORTED) {
return -1;
}
-
+ final GamePackageConfiguration config;
synchronized (mDeviceConfigLock) {
- final GamePackageConfiguration config = mConfigs.get(packageName);
- if (config == null) {
- return -1;
- }
- GamePackageConfiguration.GameModeConfiguration gameModeConfiguration =
- config.getGameModeConfiguration(gameMode);
- if (gameModeConfiguration == null) {
- return -1;
- }
- return gameModeConfiguration.getLoadingBoostDuration();
+ config = mConfigs.get(packageName);
}
+ if (config == null) {
+ return -1;
+ }
+ GamePackageConfiguration.GameModeConfiguration gameModeConfiguration =
+ config.getGameModeConfiguration(gameMode);
+ if (gameModeConfiguration == null) {
+ return -1;
+ }
+ return gameModeConfiguration.getLoadingBoostDuration();
}
/**
@@ -1159,6 +1117,66 @@
mGameServiceController.setGameServiceProvider(packageName);
}
+
+ /**
+ * Updates the resolution scaling factor for the package's target game mode and activates it.
+ *
+ * @param scalingFactor enable scaling override over any other compat scaling if positive,
+ * or disable the override otherwise
+ * @throws SecurityException if caller doesn't have
+ * {@link android.Manifest.permission#MANAGE_GAME_MODE}
+ * permission.
+ * @throws IllegalArgumentException if the user ID provided doesn't exist.
+ */
+ @Override
+ @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
+ public void updateResolutionScalingFactor(String packageName, int gameMode, float scalingFactor,
+ int userId) throws SecurityException, IllegalArgumentException {
+ checkPermission(Manifest.permission.MANAGE_GAME_MODE);
+ synchronized (mLock) {
+ if (!mSettings.containsKey(userId)) {
+ throw new IllegalArgumentException("User " + userId + " wasn't started");
+ }
+ }
+ setGameModeConfigOverride(packageName, userId, gameMode, null /*fpsStr*/,
+ Float.toString(scalingFactor));
+ }
+
+ /**
+ * Gets the resolution scaling factor for the package's target game mode.
+ *
+ * @return scaling factor for the game mode if exists or negative value otherwise.
+ * @throws SecurityException if caller doesn't have
+ * {@link android.Manifest.permission#MANAGE_GAME_MODE}
+ * permission.
+ * @throws IllegalArgumentException if the user ID provided doesn't exist.
+ */
+ @Override
+ @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
+ public float getResolutionScalingFactor(String packageName, int gameMode, int userId)
+ throws SecurityException, IllegalArgumentException {
+ checkPermission(Manifest.permission.MANAGE_GAME_MODE);
+ synchronized (mLock) {
+ if (!mSettings.containsKey(userId)) {
+ throw new IllegalArgumentException("User " + userId + " wasn't started");
+ }
+ }
+ return getResolutionScalingFactorInternal(packageName, gameMode, userId);
+ }
+
+ float getResolutionScalingFactorInternal(String packageName, int gameMode, int userId) {
+ final GamePackageConfiguration packageConfig = getConfig(packageName);
+ if (packageConfig == null) {
+ return GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING;
+ }
+ final GamePackageConfiguration.GameModeConfiguration modeConfig =
+ packageConfig.getGameModeConfiguration(gameMode);
+ if (modeConfig != null) {
+ return modeConfig.getScaling();
+ }
+ return GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING;
+ }
+
/**
* Notified when boot is completed.
*/
@@ -1235,28 +1253,6 @@
}
/**
- * @hide
- */
- @VisibleForTesting
- public void disableCompatScale(String packageName) {
- final long uid = Binder.clearCallingIdentity();
- try {
- Slog.i(TAG, "Disabling downscale for " + packageName);
- final ArrayMap<Long, PackageOverride> overrides = new ArrayMap<>();
- overrides.put(DOWNSCALED, COMPAT_DISABLED);
- final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
- overrides);
- try {
- mPlatformCompat.putOverridesOnReleaseBuilds(changeConfig, packageName);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to call IPlatformCompat#putOverridesOnReleaseBuilds", e);
- }
- } finally {
- Binder.restoreCallingIdentity(uid);
- }
- }
-
- /**
* Remove frame rate override due to mode switch
*/
private void resetFps(String packageName, @UserIdInt int userId) {
@@ -1269,60 +1265,6 @@
}
}
- private void enableCompatScale(String packageName, long scaleId) {
- final long uid = Binder.clearCallingIdentity();
- try {
- Slog.i(TAG, "Enabling downscale: " + scaleId + " for " + packageName);
- final ArrayMap<Long, PackageOverride> overrides = new ArrayMap<>();
- overrides.put(DOWNSCALED, COMPAT_ENABLED);
- overrides.put(DOWNSCALE_30, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_35, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_40, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_45, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_50, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_55, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_60, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_65, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_70, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_75, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_80, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_85, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_90, COMPAT_DISABLED);
- overrides.put(scaleId, COMPAT_ENABLED);
- final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
- overrides);
- try {
- mPlatformCompat.putOverridesOnReleaseBuilds(changeConfig, packageName);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to call IPlatformCompat#putOverridesOnReleaseBuilds", e);
- }
- } finally {
- Binder.restoreCallingIdentity(uid);
- }
- }
-
- private void updateCompatModeDownscale(GamePackageConfiguration packageConfig,
- String packageName, @GameMode int gameMode) {
-
- if (DEBUG) {
- Slog.v(TAG, dumpDeviceConfigs());
- }
- final GamePackageConfiguration.GameModeConfiguration modeConfig =
- packageConfig.getGameModeConfiguration(gameMode);
- if (modeConfig == null) {
- Slog.i(TAG, "Game mode " + gameMode + " not found for " + packageName);
- return;
- }
- long scaleId = modeConfig.getCompatChangeId();
- if (scaleId == 0) {
- Slog.w(TAG, "Invalid downscaling change id " + scaleId + " for "
- + packageName);
- return;
- }
-
- enableCompatScale(packageName, scaleId);
- }
-
private int modeToBitmask(@GameMode int gameMode) {
return (1 << gameMode);
}
@@ -1360,31 +1302,17 @@
@GameMode int gameMode, @UserIdInt int userId) {
if (gameMode == GameManager.GAME_MODE_STANDARD
|| gameMode == GameManager.GAME_MODE_UNSUPPORTED) {
- disableCompatScale(packageName);
resetFps(packageName, userId);
return;
}
- GamePackageConfiguration packageConfig = null;
-
- synchronized (mOverrideConfigLock) {
- packageConfig = mOverrideConfigs.get(packageName);
- }
-
+ final GamePackageConfiguration packageConfig = getConfig(packageName);
if (packageConfig == null) {
- synchronized (mDeviceConfigLock) {
- packageConfig = mConfigs.get(packageName);
- }
- }
-
- if (packageConfig == null) {
- disableCompatScale(packageName);
Slog.v(TAG, "Package configuration not found for " + packageName);
return;
}
if (packageConfig.willGamePerformOptimizations(gameMode)) {
return;
}
- updateCompatModeDownscale(packageConfig, packageName, gameMode);
updateFps(packageConfig, packageName, gameMode, userId);
updateUseAngle(packageName, gameMode);
}
@@ -1404,34 +1332,31 @@
}
}
// Adding override game mode configuration of the given package name
+ GamePackageConfiguration overrideConfig;
synchronized (mOverrideConfigLock) {
// look for the existing override GamePackageConfiguration
- GamePackageConfiguration overrideConfig = mOverrideConfigs.get(packageName);
+ overrideConfig = mOverrideConfigs.get(packageName);
if (overrideConfig == null) {
overrideConfig = new GamePackageConfiguration(packageName, userId);
mOverrideConfigs.put(packageName, overrideConfig);
}
-
- // modify GameModeConfiguration intervention settings
- GamePackageConfiguration.GameModeConfiguration overrideModeConfig =
- overrideConfig.getGameModeConfiguration(gameMode);
-
- if (fpsStr != null) {
- overrideModeConfig.setFpsStr(fpsStr);
- } else {
- overrideModeConfig.setFpsStr(
- GamePackageConfiguration.GameModeConfiguration.DEFAULT_FPS);
- }
- if (scaling != null) {
- overrideModeConfig.setScaling(scaling);
- } else {
- overrideModeConfig.setScaling(
- GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING);
- }
- Slog.i(TAG, "Package Name: " + packageName
- + " FPS: " + String.valueOf(overrideModeConfig.getFps())
- + " Scaling: " + overrideModeConfig.getScaling());
}
+ // modify GameModeConfiguration intervention settings
+ GamePackageConfiguration.GameModeConfiguration overrideModeConfig =
+ overrideConfig.getOrAddDefaultGameModeConfiguration(gameMode);
+
+ if (fpsStr != null) {
+ overrideModeConfig.setFpsStr(fpsStr);
+ } else {
+ overrideModeConfig.setFpsStr(
+ GamePackageConfiguration.GameModeConfiguration.DEFAULT_FPS);
+ }
+ if (scaling != null) {
+ overrideModeConfig.setScaling(Float.parseFloat(scaling));
+ }
+ Slog.i(TAG, "Package Name: " + packageName
+ + " FPS: " + String.valueOf(overrideModeConfig.getFps())
+ + " Scaling: " + overrideModeConfig.getScaling());
setGameMode(packageName, gameMode, userId);
}
@@ -1477,7 +1402,7 @@
}
// If the game mode to reset is the only mode other than standard mode,
- // The override config is removed.
+ // the override config is removed.
if (modes.length <= 2) {
synchronized (mOverrideConfigLock) {
mOverrideConfigs.remove(packageName);
@@ -1497,15 +1422,7 @@
// If not, set the game mode to standard
int gameMode = getGameMode(packageName, userId);
- GamePackageConfiguration config = null;
- synchronized (mOverrideConfigLock) {
- config = mOverrideConfigs.get(packageName);
- }
- if (config == null) {
- synchronized (mDeviceConfigLock) {
- config = mConfigs.get(packageName);
- }
- }
+ final GamePackageConfiguration config = getConfig(packageName);
final int newGameMode = getNewGameMode(gameMode, config);
if (gameMode != newGameMode) {
setGameMode(packageName, GameManager.GAME_MODE_STANDARD, userId);
@@ -1544,18 +1461,8 @@
* Returns the string listing all the interventions currently set to a game.
*/
public String getInterventionList(String packageName) {
- GamePackageConfiguration packageConfig = null;
- synchronized (mOverrideConfigLock) {
- packageConfig = mOverrideConfigs.get(packageName);
- }
-
- if (packageConfig == null) {
- synchronized (mDeviceConfigLock) {
- packageConfig = mConfigs.get(packageName);
- }
- }
-
- StringBuilder listStrSb = new StringBuilder();
+ final GamePackageConfiguration packageConfig = getConfig(packageName);
+ final StringBuilder listStrSb = new StringBuilder();
if (packageConfig == null) {
listStrSb.append("\n No intervention found for package ")
.append(packageName);
@@ -1570,20 +1477,27 @@
* @hide
*/
@VisibleForTesting
- void updateConfigsForUser(@UserIdInt int userId, String... packageNames) {
+ void updateConfigsForUser(@UserIdInt int userId, boolean checkGamePackage,
+ String... packageNames) {
+ if (checkGamePackage) {
+ packageNames = Arrays.stream(packageNames).filter(
+ p -> isPackageGame(p, userId)).toArray(String[]::new);
+ }
try {
synchronized (mDeviceConfigLock) {
for (final String packageName : packageNames) {
final GamePackageConfiguration config =
new GamePackageConfiguration(packageName, userId);
- if (config.isValid()) {
+ if (config.isActive()) {
if (DEBUG) {
Slog.i(TAG, "Adding config: " + config.toString());
}
mConfigs.put(packageName, config);
} else {
- Slog.w(TAG, "Invalid package config for "
- + config.getPackageName() + ":" + config.toString());
+ if (DEBUG) {
+ Slog.w(TAG, "Inactive package config for "
+ + config.getPackageName() + ":" + config.toString());
+ }
mConfigs.remove(packageName);
}
}
@@ -1613,7 +1527,7 @@
}
}
} catch (Exception e) {
- Slog.e(TAG, "Failed to update compat modes for user " + userId + ": " + e);
+ Slog.e(TAG, "Failed to update configs for user " + userId + ": " + e);
}
final Message msg = mHandler.obtainMessage(WRITE_GAME_MODE_INTERVENTION_LIST_FILE);
@@ -1664,7 +1578,7 @@
final int useAngle = gameModeConfiguration.getUseAngle() ? 1 : 0;
sb.append(TextUtils.formatSimple("angle=%d", useAngle));
sb.append(",");
- final String scaling = gameModeConfiguration.getScaling();
+ final float scaling = gameModeConfiguration.getScaling();
sb.append("scaling=");
sb.append(scaling);
sb.append(",");
@@ -1761,17 +1675,9 @@
}
switch (intent.getAction()) {
case ACTION_PACKAGE_ADDED:
- updateConfigsForUser(userId, packageName);
+ updateConfigsForUser(userId, true /*checkGamePackage*/, packageName);
break;
case ACTION_PACKAGE_REMOVED:
- disableCompatScale(packageName);
- // If EXTRA_REPLACING is true, it means there will be an
- // ACTION_PACKAGE_ADDED triggered after this because this
- // is an updated package that gets installed. Hence, disable
- // resolution downscaling effort but avoid removing the server
- // or commandline overriding configurations because those will
- // not change but the package game mode configurations may change
- // which may opt in and/or opt out some game mode configurations.
if (!intent.getBooleanExtra(EXTRA_REPLACING, false)) {
synchronized (mOverrideConfigLock) {
mOverrideConfigs.remove(packageName);
@@ -1803,6 +1709,10 @@
mDeviceConfigListener = new DeviceConfigListener();
}
+ private void publishLocalService() {
+ LocalServices.addService(GameManagerInternal.class, new LocalService());
+ }
+
private String dumpDeviceConfigs() {
StringBuilder out = new StringBuilder();
for (String key : mConfigs.keySet()) {
diff --git a/services/core/java/com/android/server/app/GameManagerShellCommand.java b/services/core/java/com/android/server/app/GameManagerShellCommand.java
index 470c320..487d19a 100644
--- a/services/core/java/com/android/server/app/GameManagerShellCommand.java
+++ b/services/core/java/com/android/server/app/GameManagerShellCommand.java
@@ -16,21 +16,6 @@
package com.android.server.app;
-import static com.android.server.wm.CompatModePackages.DOWNSCALED;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_30;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_35;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_40;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_45;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_50;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_55;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_60;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_65;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_70;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_75;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_80;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_85;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_90;
-
import android.app.ActivityManager;
import android.app.GameManager;
import android.app.IGameManagerService;
@@ -39,7 +24,6 @@
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.ShellCommand;
-import android.util.ArraySet;
import java.io.PrintWriter;
import java.util.Locale;
@@ -53,23 +37,6 @@
public GameManagerShellCommand() {}
- private static final ArraySet<Long> DOWNSCALE_CHANGE_IDS = new ArraySet<>(new Long[]{
- DOWNSCALED,
- DOWNSCALE_90,
- DOWNSCALE_85,
- DOWNSCALE_80,
- DOWNSCALE_75,
- DOWNSCALE_70,
- DOWNSCALE_65,
- DOWNSCALE_60,
- DOWNSCALE_55,
- DOWNSCALE_50,
- DOWNSCALE_45,
- DOWNSCALE_40,
- DOWNSCALE_35,
- DOWNSCALE_30,
- });
-
@Override
public int onCommand(String cmd) {
if (cmd == null) {
@@ -212,11 +179,15 @@
case "--downscale":
if (downscaleRatio == null) {
downscaleRatio = getNextArgRequired();
- if (downscaleRatio != null
- && GameManagerService.getCompatChangeId(downscaleRatio) == 0
- && !downscaleRatio.equals("disable")) {
- pw.println("Invalid scaling ratio '" + downscaleRatio + "'");
- return -1;
+ if ("disable".equals(downscaleRatio)) {
+ downscaleRatio = "-1";
+ } else {
+ try {
+ Float.parseFloat(downscaleRatio);
+ } catch (NumberFormatException e) {
+ pw.println("Invalid scaling ratio '" + downscaleRatio + "'");
+ return -1;
+ }
}
} else {
pw.println("Duplicate option '" + option + "'");
@@ -249,40 +220,16 @@
final GameManagerService gameManagerService = (GameManagerService)
ServiceManager.getService(Context.GAME_SERVICE);
- boolean batteryModeSupported = false;
- boolean perfModeSupported = false;
- int [] modes = gameManagerService.getAvailableGameModes(packageName);
-
- for (int mode : modes) {
- if (mode == GameManager.GAME_MODE_PERFORMANCE) {
- perfModeSupported = true;
- } else if (mode == GameManager.GAME_MODE_BATTERY) {
- batteryModeSupported = true;
- }
- }
-
switch (gameMode.toLowerCase(Locale.getDefault())) {
case "2":
case "performance":
- if (perfModeSupported) {
- gameManagerService.setGameModeConfigOverride(packageName, userId,
- GameManager.GAME_MODE_PERFORMANCE, fpsStr, downscaleRatio);
- } else {
- pw.println("Game mode: " + gameMode + " not supported by "
- + packageName);
- return -1;
- }
+ gameManagerService.setGameModeConfigOverride(packageName, userId,
+ GameManager.GAME_MODE_PERFORMANCE, fpsStr, downscaleRatio);
break;
case "3":
case "battery":
- if (batteryModeSupported) {
- gameManagerService.setGameModeConfigOverride(packageName, userId,
- GameManager.GAME_MODE_BATTERY, fpsStr, downscaleRatio);
- } else {
- pw.println("Game mode: " + gameMode + " not supported by "
- + packageName);
- return -1;
- }
+ gameManagerService.setGameModeConfigOverride(packageName, userId,
+ GameManager.GAME_MODE_BATTERY, fpsStr, downscaleRatio);
break;
default:
pw.println("Invalid game mode: " + gameMode);
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 7bef6d5..a5bcb05 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -217,7 +217,7 @@
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Consumer;
-public class AppOpsService extends IAppOpsService.Stub {
+public class AppOpsService extends IAppOpsService.Stub implements PersistenceScheduler {
static final String TAG = "AppOps";
static final boolean DEBUG = false;
@@ -402,6 +402,9 @@
/** Package Manager internal. Access via {@link #getPackageManagerInternal()} */
private @Nullable PackageManagerInternal mPackageManagerInternal;
+ /** Interface for app-op modes.*/
+ @VisibleForTesting AppOpsServiceInterface mAppOpsServiceInterface;
+
/**
* An unsynchronized pool of {@link OpEventProxyInfo} objects.
*/
@@ -558,7 +561,6 @@
public boolean pendingAppWidgetVisible;
public ArrayMap<String, Ops> pkgOps;
- public SparseIntArray opModes;
// true indicates there is an interested observer, false there isn't but it has such an op
public SparseBooleanArray foregroundOps;
@@ -569,15 +571,43 @@
}
public void clear() {
+ mAppOpsServiceInterface.removeUid(uid);
+ if (pkgOps != null) {
+ for (String packageName : pkgOps.keySet()) {
+ mAppOpsServiceInterface.removePackage(packageName);
+ }
+ }
pkgOps = null;
- opModes = null;
}
public boolean isDefault() {
+ boolean areAllPackageModesDefault = true;
+ if (pkgOps != null) {
+ for (String packageName : pkgOps.keySet()) {
+ if (!mAppOpsServiceInterface.arePackageModesDefault(packageName)) {
+ areAllPackageModesDefault = false;
+ break;
+ }
+ }
+ }
return (pkgOps == null || pkgOps.isEmpty())
- && (opModes == null || opModes.size() <= 0)
&& (state == UID_STATE_CACHED
- && (pendingState == UID_STATE_CACHED));
+ && (pendingState == UID_STATE_CACHED))
+ && (mAppOpsServiceInterface.areUidModesDefault(uid)
+ && areAllPackageModesDefault);
+ }
+
+ // Functions for uid mode access and manipulation.
+ public SparseIntArray getNonDefaultUidModes() {
+ return mAppOpsServiceInterface.getNonDefaultUidModes(uid);
+ }
+
+ public int getUidMode(int op) {
+ return mAppOpsServiceInterface.getUidMode(uid, op);
+ }
+
+ public boolean setUidMode(int op, int mode) {
+ return mAppOpsServiceInterface.setUidMode(uid, op, mode);
}
int evalMode(int op, int mode) {
@@ -647,21 +677,20 @@
public void evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers) {
SparseBooleanArray which = null;
hasForegroundWatchers = false;
- if (opModes != null) {
- for (int i = opModes.size() - 1; i >= 0; i--) {
- if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) {
- if (which == null) {
- which = new SparseBooleanArray();
- }
- evalForegroundWatchers(opModes.keyAt(i), watchers, which);
+ final SparseIntArray opModes = getNonDefaultUidModes();
+ for (int i = opModes.size() - 1; i >= 0; i--) {
+ if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) {
+ if (which == null) {
+ which = new SparseBooleanArray();
}
+ evalForegroundWatchers(opModes.keyAt(i), watchers, which);
}
}
if (pkgOps != null) {
for (int i = pkgOps.size() - 1; i >= 0; i--) {
Ops ops = pkgOps.valueAt(i);
for (int j = ops.size() - 1; j >= 0; j--) {
- if (ops.valueAt(j).mode == AppOpsManager.MODE_FOREGROUND) {
+ if (ops.valueAt(j).getMode() == AppOpsManager.MODE_FOREGROUND) {
if (which == null) {
which = new SparseBooleanArray();
}
@@ -1451,8 +1480,6 @@
final UidState uidState;
final @NonNull String packageName;
- private @Mode int mode;
-
/** attributionTag -> AttributedOp */
final ArrayMap<String, AttributedOp> mAttributions = new ArrayMap<>(1);
@@ -1461,15 +1488,17 @@
this.uid = uid;
this.uidState = uidState;
this.packageName = packageName;
- this.mode = AppOpsManager.opToDefaultMode(op);
}
- int getMode() {
- return mode;
+ @Mode int getMode() {
+ return mAppOpsServiceInterface.getPackageMode(packageName, this.op);
+ }
+ void setMode(@Mode int mode) {
+ mAppOpsServiceInterface.setPackageMode(packageName, this.op, mode);
}
int evalMode() {
- return uidState.evalMode(op, mode);
+ return uidState.evalMode(op, getMode());
}
void removeAttributionsWithNoTime() {
@@ -1503,7 +1532,7 @@
mAttributions.valueAt(i).createAttributedOpEntryLocked());
}
- return new OpEntry(op, mode, attributionEntries);
+ return new OpEntry(op, getMode(), attributionEntries);
}
@NonNull OpEntry createSingleAttributionEntryLocked(@Nullable String attributionTag) {
@@ -1518,7 +1547,7 @@
}
}
- return new OpEntry(op, mode, attributionEntries);
+ return new OpEntry(op, getMode(), attributionEntries);
}
boolean isRunning() {
@@ -1775,6 +1804,7 @@
public AppOpsService(File storagePath, Handler handler, Context context) {
mContext = context;
+ mAppOpsServiceInterface = new LegacyAppOpsServiceInterfaceImpl(this, this);
LockGuard.installLock(this, LockGuard.INDEX_APP_OPS);
mFile = new AtomicFile(storagePath, "appops");
@@ -1815,7 +1845,7 @@
if (uidState == null || uidState.pkgOps == null) {
return;
}
-
+ mAppOpsServiceInterface.removePackage(pkgName);
Ops removedOps = uidState.pkgOps.remove(pkgName);
if (removedOps != null) {
scheduleFastWriteLocked();
@@ -2037,25 +2067,27 @@
return;
}
- Ops ops = null;
+ Ops removedOps = null;
// Remove any package state if such.
if (uidState.pkgOps != null) {
- ops = uidState.pkgOps.remove(packageName);
+ removedOps = uidState.pkgOps.remove(packageName);
+ mAppOpsServiceInterface.removePackage(packageName);
}
// If we just nuked the last package state check if the UID is valid.
- if (ops != null && uidState.pkgOps.isEmpty()
+ if (removedOps != null && uidState.pkgOps.isEmpty()
&& getPackagesForUid(uid).length <= 0) {
+ uidState.clear();
mUidStates.remove(uid);
}
- if (ops != null) {
+ if (removedOps != null) {
scheduleFastWriteLocked();
- final int numOps = ops.size();
+ final int numOps = removedOps.size();
for (int opNum = 0; opNum < numOps; opNum++) {
- final Op op = ops.valueAt(opNum);
+ final Op op = removedOps.valueAt(opNum);
final int numAttributions = op.mAttributions.size();
for (int attributionNum = 0; attributionNum < numAttributions;
@@ -2080,6 +2112,7 @@
public void uidRemoved(int uid) {
synchronized (this) {
if (mUidStates.indexOfKey(uid) >= 0) {
+ mUidStates.get(uid).clear();
mUidStates.remove(uid);
scheduleFastWriteLocked();
}
@@ -2185,12 +2218,11 @@
private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) {
ArrayList<AppOpsManager.OpEntry> resOps = null;
- final long elapsedNow = SystemClock.elapsedRealtime();
if (ops == null) {
resOps = new ArrayList<>();
for (int j=0; j<pkgOps.size(); j++) {
Op curOp = pkgOps.valueAt(j);
- resOps.add(getOpEntryForResult(curOp, elapsedNow));
+ resOps.add(getOpEntryForResult(curOp));
}
} else {
for (int j=0; j<ops.length; j++) {
@@ -2199,7 +2231,7 @@
if (resOps == null) {
resOps = new ArrayList<>();
}
- resOps.add(getOpEntryForResult(curOp, elapsedNow));
+ resOps.add(getOpEntryForResult(curOp));
}
}
}
@@ -2209,11 +2241,12 @@
@Nullable
private ArrayList<AppOpsManager.OpEntry> collectUidOps(@NonNull UidState uidState,
@Nullable int[] ops) {
- if (uidState.opModes == null) {
+ final SparseIntArray opModes = uidState.getNonDefaultUidModes();
+ if (opModes == null) {
return null;
}
- int opModeCount = uidState.opModes.size();
+ int opModeCount = opModes.size();
if (opModeCount == 0) {
return null;
}
@@ -2221,25 +2254,24 @@
if (ops == null) {
resOps = new ArrayList<>();
for (int i = 0; i < opModeCount; i++) {
- int code = uidState.opModes.keyAt(i);
- resOps.add(new OpEntry(code, uidState.opModes.get(code), Collections.emptyMap()));
+ int code = opModes.keyAt(i);
+ resOps.add(new OpEntry(code, opModes.get(code), Collections.emptyMap()));
}
} else {
for (int j=0; j<ops.length; j++) {
int code = ops[j];
- if (uidState.opModes.indexOfKey(code) >= 0) {
+ if (opModes.indexOfKey(code) >= 0) {
if (resOps == null) {
resOps = new ArrayList<>();
}
- resOps.add(new OpEntry(code, uidState.opModes.get(code),
- Collections.emptyMap()));
+ resOps.add(new OpEntry(code, opModes.get(code), Collections.emptyMap()));
}
}
}
return resOps;
}
- private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op, long elapsedNow) {
+ private static @NonNull OpEntry getOpEntryForResult(@NonNull Op op) {
return op.createEntryLocked();
}
@@ -2484,15 +2516,18 @@
Ops ops = getOpsLocked(uid, packageName, null, false, null, /* edit */ false);
if (ops != null) {
ops.remove(op.op);
+ op.setMode(AppOpsManager.opToDefaultMode(op.op));
if (ops.size() <= 0) {
UidState uidState = ops.uidState;
ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
if (pkgOps != null) {
pkgOps.remove(ops.packageName);
+ mAppOpsServiceInterface.removePackage(ops.packageName);
if (pkgOps.isEmpty()) {
uidState.pkgOps = null;
}
if (uidState.isDefault()) {
+ uidState.clear();
mUidStates.remove(uid);
}
}
@@ -2548,33 +2583,18 @@
if (mode == defaultMode) {
return;
}
- previousMode = MODE_DEFAULT;
uidState = new UidState(uid);
- uidState.opModes = new SparseIntArray();
- uidState.opModes.put(code, mode);
mUidStates.put(uid, uidState);
- scheduleWriteLocked();
- } else if (uidState.opModes == null) {
- previousMode = MODE_DEFAULT;
- if (mode != defaultMode) {
- uidState.opModes = new SparseIntArray();
- uidState.opModes.put(code, mode);
- scheduleWriteLocked();
- }
+ }
+ if (uidState.getUidMode(code) != AppOpsManager.opToDefaultMode(code)) {
+ previousMode = uidState.getUidMode(code);
} else {
- if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) {
- return;
- }
- previousMode = uidState.opModes.get(code);
- if (mode == defaultMode) {
- uidState.opModes.delete(code);
- if (uidState.opModes.size() <= 0) {
- uidState.opModes = null;
- }
- } else {
- uidState.opModes.put(code, mode);
- }
- scheduleWriteLocked();
+ // doesn't look right but is legacy behavior.
+ previousMode = MODE_DEFAULT;
+ }
+
+ if (!uidState.setUidMode(code, mode)) {
+ return;
}
uidState.evalForegroundOps(mOpModeWatchers);
if (mode != MODE_ERRORED && mode != previousMode) {
@@ -2806,9 +2826,10 @@
UidState uidState = getUidStateLocked(uid, false);
Op op = getOpLocked(code, uid, packageName, null, false, pvr.bypass, /* edit */ true);
if (op != null) {
- if (op.mode != mode) {
- previousMode = op.mode;
- op.mode = mode;
+ if (op.getMode() != mode) {
+ previousMode = op.getMode();
+ op.setMode(mode);
+
if (uidState != null) {
uidState.evalForegroundOps(mOpModeWatchers);
}
@@ -2976,17 +2997,14 @@
for (int i = mUidStates.size() - 1; i >= 0; i--) {
UidState uidState = mUidStates.valueAt(i);
- SparseIntArray opModes = uidState.opModes;
+ SparseIntArray opModes = uidState.getNonDefaultUidModes();
if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) {
final int uidOpCount = opModes.size();
for (int j = uidOpCount - 1; j >= 0; j--) {
final int code = opModes.keyAt(j);
if (AppOpsManager.opAllowsReset(code)) {
int previousMode = opModes.valueAt(j);
- opModes.removeAt(j);
- if (opModes.size() <= 0) {
- uidState.opModes = null;
- }
+ uidState.setUidMode(code, AppOpsManager.opToDefaultMode(code));
for (String packageName : getPackagesForUid(uidState.uid)) {
callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
previousMode, mOpModeWatchers.get(code));
@@ -3028,9 +3046,9 @@
continue;
}
if (AppOpsManager.opAllowsReset(curOp.op)
- && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
- int previousMode = curOp.mode;
- curOp.mode = AppOpsManager.opToDefaultMode(curOp.op);
+ && curOp.getMode() != AppOpsManager.opToDefaultMode(curOp.op)) {
+ int previousMode = curOp.getMode();
+ curOp.setMode(AppOpsManager.opToDefaultMode(curOp.op));
changed = true;
uidChanged = true;
final int uid = curOp.uidState.uid;
@@ -3049,9 +3067,11 @@
}
if (pkgOps.size() == 0) {
it.remove();
+ mAppOpsServiceInterface.removePackage(packageName);
}
}
if (uidState.isDefault()) {
+ uidState.clear();
mUidStates.remove(uidState.uid);
}
if (uidChanged) {
@@ -3267,16 +3287,16 @@
}
code = AppOpsManager.opToSwitch(code);
UidState uidState = getUidStateLocked(uid, false);
- if (uidState != null && uidState.opModes != null
- && uidState.opModes.indexOfKey(code) >= 0) {
- final int rawMode = uidState.opModes.get(code);
+ if (uidState != null
+ && uidState.getUidMode(code) != AppOpsManager.opToDefaultMode(code)) {
+ final int rawMode = uidState.getUidMode(code);
return raw ? rawMode : uidState.evalMode(code, rawMode);
}
Op op = getOpLocked(code, uid, packageName, null, false, pvr.bypass, /* edit */ false);
if (op == null) {
return AppOpsManager.opToDefaultMode(code);
}
- return raw ? op.mode : op.evalMode();
+ return raw ? op.getMode() : op.evalMode();
}
}
@@ -3502,8 +3522,8 @@
}
// If there is a non-default per UID policy (we set UID op mode only if
// non-default) it takes over, otherwise use the per package policy.
- if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
- final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
+ if (uidState.getUidMode(switchCode) != AppOpsManager.opToDefaultMode(switchCode)) {
+ final int uidMode = uidState.evalMode(code, uidState.getUidMode(switchCode));
if (uidMode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
@@ -4018,8 +4038,8 @@
final int switchCode = AppOpsManager.opToSwitch(code);
// If there is a non-default per UID policy (we set UID op mode only if
// non-default) it takes over, otherwise use the per package policy.
- if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
- final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
+ if (uidState.getUidMode(switchCode) != AppOpsManager.opToDefaultMode(switchCode)) {
+ final int uidMode = uidState.evalMode(code, uidState.getUidMode(switchCode));
if (!shouldStartForMode(uidMode, startIfModeDefault)) {
if (DEBUG) {
Slog.d(TAG, "startOperation: uid reject #" + uidMode + " for code "
@@ -4516,9 +4536,8 @@
continue;
}
- if (uidState.opModes != null
- && uidState.opModes.indexOfKey(code) >= 0
- && uidState.opModes.get(code) == AppOpsManager.MODE_FOREGROUND) {
+ if (uidState.getUidMode(code) != AppOpsManager.opToDefaultMode(code)
+ && uidState.getUidMode(code) == AppOpsManager.MODE_FOREGROUND) {
mHandler.sendMessage(PooledLambda.obtainMessage(
AppOpsService::notifyOpChangedForAllPkgsInUid,
this, code, uidState.uid, true, null));
@@ -4536,7 +4555,7 @@
if (op == null) {
continue;
}
- if (op.mode == AppOpsManager.MODE_FOREGROUND) {
+ if (op.getMode() == AppOpsManager.MODE_FOREGROUND) {
mHandler.sendMessage(PooledLambda.obtainMessage(
AppOpsService::notifyOpChanged,
this, callback, code, uidState.uid,
@@ -4811,14 +4830,16 @@
return ops;
}
- private void scheduleWriteLocked() {
+ @Override
+ public void scheduleWriteLocked() {
if (!mWriteScheduled) {
mWriteScheduled = true;
mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
}
}
- private void scheduleFastWriteLocked() {
+ @Override
+ public void scheduleFastWriteLocked() {
if (!mFastWriteScheduled) {
mWriteScheduled = true;
mFastWriteScheduled = true;
@@ -4929,6 +4950,7 @@
}
boolean success = false;
mUidStates.clear();
+ mAppOpsServiceInterface.clearAllModes();
try {
TypedXmlPullParser parser = Xml.resolvePullParser(stream);
int type;
@@ -4977,6 +4999,7 @@
} finally {
if (!success) {
mUidStates.clear();
+ mAppOpsServiceInterface.clearAllModes();
}
try {
stream.close();
@@ -4996,11 +5019,12 @@
if (uidState == null) {
continue;
}
- if (uidState.opModes != null) {
- final int idx = uidState.opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND);
+ SparseIntArray opModes = uidState.getNonDefaultUidModes();
+ if (opModes != null) {
+ final int idx = opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND);
if (idx >= 0) {
- uidState.opModes.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
- uidState.opModes.valueAt(idx));
+ uidState.setUidMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
+ opModes.valueAt(idx));
}
}
if (uidState.pkgOps == null) {
@@ -5011,10 +5035,10 @@
Ops ops = uidState.pkgOps.valueAt(j);
if (ops != null) {
final Op op = ops.get(AppOpsManager.OP_RUN_IN_BACKGROUND);
- if (op != null && op.mode != AppOpsManager.opToDefaultMode(op.op)) {
+ if (op != null && op.getMode() != AppOpsManager.opToDefaultMode(op.op)) {
final Op copy = new Op(op.uidState, op.packageName,
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uidState.uid);
- copy.mode = op.mode;
+ copy.setMode(op.getMode());
ops.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, copy);
changed = true;
}
@@ -5142,7 +5166,7 @@
Op op = new Op(uidState, pkgName, opCode, uidState.uid);
final int mode = parser.getAttributeInt(null, "m", AppOpsManager.opToDefaultMode(op.op));
- op.mode = mode;
+ op.setMode(mode);
int outerDepth = parser.getDepth();
int type;
@@ -5199,16 +5223,9 @@
UidState uidState = mUidStates.valueAt(uidStateNum);
int uid = mUidStates.keyAt(uidStateNum);
- SparseIntArray opModes = uidState.opModes;
+ SparseIntArray opModes = uidState.getNonDefaultUidModes();
if (opModes != null && opModes.size() > 0) {
- uidStatesClone.put(uid, new SparseIntArray(opModes.size()));
-
- final int opCount = opModes.size();
- for (int opCountNum = 0; opCountNum < opCount; opCountNum++) {
- uidStatesClone.get(uid).put(
- opModes.keyAt(opCountNum),
- opModes.valueAt(opCountNum));
- }
+ uidStatesClone.put(uid, opModes);
}
}
}
@@ -6314,15 +6331,15 @@
}
for (int i=0; i<mUidStates.size(); i++) {
UidState uidState = mUidStates.valueAt(i);
- final SparseIntArray opModes = uidState.opModes;
+ final SparseIntArray opModes = uidState.getNonDefaultUidModes();
final ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
if (dumpWatchers || dumpHistory) {
continue;
}
if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) {
- boolean hasOp = dumpOp < 0 || (uidState.opModes != null
- && uidState.opModes.indexOfKey(dumpOp) >= 0);
+ boolean hasOp = dumpOp < 0 || (opModes != null
+ && opModes.indexOfKey(dumpOp) >= 0);
boolean hasPackage = dumpPackage == null || dumpUid == mUidStates.keyAt(i);
boolean hasMode = dumpMode < 0;
if (!hasMode && opModes != null) {
@@ -6342,7 +6359,7 @@
}
if (!hasMode) {
for (int opi = 0; !hasMode && opi < ops.size(); opi++) {
- if (ops.valueAt(opi).mode == dumpMode) {
+ if (ops.valueAt(opi).getMode() == dumpMode) {
hasMode = true;
}
}
@@ -6437,7 +6454,7 @@
if (dumpOp >= 0 && dumpOp != opCode) {
continue;
}
- if (dumpMode >= 0 && dumpMode != op.mode) {
+ if (dumpMode >= 0 && dumpMode != op.getMode()) {
continue;
}
if (!printedPackage) {
@@ -6445,14 +6462,14 @@
printedPackage = true;
}
pw.print(" "); pw.print(AppOpsManager.opToName(opCode));
- pw.print(" ("); pw.print(AppOpsManager.modeToName(op.mode));
+ pw.print(" ("); pw.print(AppOpsManager.modeToName(op.getMode()));
final int switchOp = AppOpsManager.opToSwitch(opCode);
if (switchOp != opCode) {
pw.print(" / switch ");
pw.print(AppOpsManager.opToName(switchOp));
final Op switchObj = ops.get(switchOp);
- int mode = switchObj != null ? switchObj.mode
- : AppOpsManager.opToDefaultMode(switchOp);
+ int mode = switchObj == null
+ ? AppOpsManager.opToDefaultMode(switchOp) : switchObj.getMode();
pw.print("="); pw.print(AppOpsManager.modeToName(mode));
}
pw.println("): ");
@@ -6696,7 +6713,7 @@
for (int pkgNum = 0; pkgNum < numPkgOps; pkgNum++) {
Ops ops = uidState.pkgOps.valueAt(pkgNum);
Op op = ops != null ? ops.get(code) : null;
- if (op == null || (op.mode != MODE_ALLOWED && op.mode != MODE_FOREGROUND)) {
+ if (op == null || (op.getMode() != MODE_ALLOWED && op.getMode() != MODE_FOREGROUND)) {
continue;
}
int numAttrTags = op.mAttributions.size();
@@ -6817,6 +6834,7 @@
return;
}
Ops removedOps = uidState.pkgOps.remove(packageName);
+ mAppOpsServiceInterface.removePackage(packageName);
if (removedOps != null) {
scheduleFastWriteLocked();
}
@@ -7136,10 +7154,12 @@
return false;
}
+ @GuardedBy("this")
private void removeUidsForUserLocked(int userHandle) {
for (int i = mUidStates.size() - 1; i >= 0; --i) {
final int uid = mUidStates.keyAt(i);
if (UserHandle.getUserId(uid) == userHandle) {
+ mUidStates.valueAt(i).clear();
mUidStates.removeAt(i);
}
}
diff --git a/services/core/java/com/android/server/appop/AppOpsServiceInterface.java b/services/core/java/com/android/server/appop/AppOpsServiceInterface.java
new file mode 100644
index 0000000..cd5ea12
--- /dev/null
+++ b/services/core/java/com/android/server/appop/AppOpsServiceInterface.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.appop;
+import android.annotation.NonNull;
+import android.app.AppOpsManager.Mode;
+import android.util.SparseIntArray;
+/**
+ * Interface for accessing and modifying modes for app-ops i.e. package and uid modes.
+ * In the future this interface will also include mode callbacks and op restrictions.
+ */
+public interface AppOpsServiceInterface {
+ /**
+ * Returns a copy of non-default app-ops with op as keys and their modes as values for a uid.
+ * Returns an empty SparseIntArray if nothing is set.
+ * @param uid for which we need the app-ops and their modes.
+ */
+ SparseIntArray getNonDefaultUidModes(int uid);
+
+ /**
+ * Returns the app-op mode for a particular app-op of a uid.
+ * Returns default op mode if the op mode for particular uid and op is not set.
+ * @param uid user id for which we need the mode.
+ * @param op app-op for which we need the mode.
+ * @return mode of the app-op.
+ */
+ int getUidMode(int uid, int op);
+
+ /**
+ * Set the app-op mode for a particular uid and op.
+ * The mode is not set if the mode is the same as the default mode for the op.
+ * @param uid user id for which we want to set the mode.
+ * @param op app-op for which we want to set the mode.
+ * @param mode mode for the app-op.
+ * @return true if op mode is changed.
+ */
+ boolean setUidMode(int uid, int op, @Mode int mode);
+
+ /**
+ * Gets the app-op mode for a particular package.
+ * Returns default op mode if the op mode for the particular package is not set.
+ * @param packageName package name for which we need the op mode.
+ * @param op app-op for which we need the mode.
+ * @return the mode of the app-op.
+ */
+ int getPackageMode(@NonNull String packageName, int op);
+
+ /**
+ * Sets the app-op mode for a particular package.
+ * @param packageName package name for which we need to set the op mode.
+ * @param op app-op for which we need to set the mode.
+ * @param mode the mode of the app-op.
+ */
+ void setPackageMode(@NonNull String packageName, int op, @Mode int mode);
+
+ /**
+ * Stop tracking any app-op modes for a package.
+ * @param packageName Name of the package for which we want to remove all mode tracking.
+ */
+ boolean removePackage(@NonNull String packageName);
+
+ /**
+ * Stop tracking any app-op modes for this uid.
+ * @param uid user id for which we want to remove all tracking.
+ */
+ void removeUid(int uid);
+
+ /**
+ * Returns true if all uid modes for this uid are
+ * in default state.
+ * @param uid user id
+ */
+ boolean areUidModesDefault(int uid);
+
+ /**
+ * Returns true if all package modes for this package name are
+ * in default state.
+ * @param packageName package name.
+ */
+ boolean arePackageModesDefault(String packageName);
+
+ /**
+ * Stop tracking app-op modes for all uid and packages.
+ */
+ void clearAllModes();
+}
diff --git a/services/core/java/com/android/server/appop/LegacyAppOpsServiceInterfaceImpl.java b/services/core/java/com/android/server/appop/LegacyAppOpsServiceInterfaceImpl.java
new file mode 100644
index 0000000..c27c0d3
--- /dev/null
+++ b/services/core/java/com/android/server/appop/LegacyAppOpsServiceInterfaceImpl.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appop;
+
+import android.annotation.NonNull;
+import android.app.AppOpsManager;
+import android.app.AppOpsManager.Mode;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+
+/**
+ * Legacy implementation for App-ops service's app-op mode (uid and package) storage and access.
+ * In the future this class will also include mode callbacks and op restrictions.
+ */
+public class LegacyAppOpsServiceInterfaceImpl implements AppOpsServiceInterface {
+
+ // Should be the same object that the AppOpsService is using for locking.
+ final Object mLock;
+
+ @GuardedBy("mLock")
+ @VisibleForTesting
+ final SparseArray<SparseIntArray> mUidModes = new SparseArray<>();
+
+ @GuardedBy("mLock")
+ final ArrayMap<String, SparseIntArray> mPackageModes = new ArrayMap<>();
+
+ final PersistenceScheduler mPersistenceScheduler;
+
+
+ LegacyAppOpsServiceInterfaceImpl(PersistenceScheduler persistenceScheduler,
+ @NonNull Object lock) {
+ this.mPersistenceScheduler = persistenceScheduler;
+ this.mLock = lock;
+ }
+
+ @Override
+ public SparseIntArray getNonDefaultUidModes(int uid) {
+ synchronized (mLock) {
+ SparseIntArray opModes = mUidModes.get(uid, null);
+ if (opModes == null) {
+ return new SparseIntArray();
+ }
+ return opModes.clone();
+ }
+ }
+
+ @Override
+ public int getUidMode(int uid, int op) {
+ synchronized (mLock) {
+ SparseIntArray opModes = mUidModes.get(uid, null);
+ if (opModes == null) {
+ return AppOpsManager.opToDefaultMode(op);
+ }
+ return opModes.get(op, AppOpsManager.opToDefaultMode(op));
+ }
+ }
+
+ @Override
+ public boolean setUidMode(int uid, int op, int mode) {
+ final int defaultMode = AppOpsManager.opToDefaultMode(op);
+ synchronized (mLock) {
+ SparseIntArray opModes = mUidModes.get(uid, null);
+ if (opModes == null) {
+ if (mode != defaultMode) {
+ opModes = new SparseIntArray();
+ mUidModes.put(uid, opModes);
+ opModes.put(op, mode);
+ mPersistenceScheduler.scheduleWriteLocked();
+ }
+ } else {
+ if (opModes.indexOfKey(op) >= 0 && opModes.get(op) == mode) {
+ return false;
+ }
+ if (mode == defaultMode) {
+ opModes.delete(op);
+ if (opModes.size() <= 0) {
+ opModes = null;
+ mUidModes.delete(uid);
+ }
+ } else {
+ opModes.put(op, mode);
+ }
+ mPersistenceScheduler.scheduleWriteLocked();
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int getPackageMode(String packageName, int op) {
+ synchronized (mLock) {
+ SparseIntArray opModes = mPackageModes.getOrDefault(packageName, null);
+ if (opModes == null) {
+ return AppOpsManager.opToDefaultMode(op);
+ }
+ return opModes.get(op, AppOpsManager.opToDefaultMode(op));
+ }
+ }
+
+ @Override
+ public void setPackageMode(String packageName, int op, @Mode int mode) {
+ final int defaultMode = AppOpsManager.opToDefaultMode(op);
+ synchronized (mLock) {
+ SparseIntArray opModes = mPackageModes.get(packageName);
+ if (opModes == null) {
+ if (mode != defaultMode) {
+ opModes = new SparseIntArray();
+ mPackageModes.put(packageName, opModes);
+ opModes.put(op, mode);
+ mPersistenceScheduler.scheduleWriteLocked();
+ }
+ } else {
+ if (opModes.indexOfKey(op) >= 0 && opModes.get(op) == mode) {
+ return;
+ }
+ if (mode == defaultMode) {
+ opModes.delete(op);
+ if (opModes.size() <= 0) {
+ opModes = null;
+ mPackageModes.remove(packageName);
+ }
+ } else {
+ opModes.put(op, mode);
+ }
+ mPersistenceScheduler.scheduleWriteLocked();
+ }
+ }
+ }
+
+ @Override
+ public void removeUid(int uid) {
+ synchronized (mLock) {
+ SparseIntArray opModes = mUidModes.get(uid);
+ if (opModes == null) {
+ return;
+ }
+ mUidModes.remove(uid);
+ mPersistenceScheduler.scheduleFastWriteLocked();
+ }
+ }
+
+
+ @Override
+ public boolean areUidModesDefault(int uid) {
+ synchronized (mLock) {
+ SparseIntArray opModes = mUidModes.get(uid);
+ return (opModes == null || opModes.size() <= 0);
+ }
+ }
+
+ @Override
+ public boolean arePackageModesDefault(String packageMode) {
+ synchronized (mLock) {
+ SparseIntArray opModes = mPackageModes.get(packageMode);
+ return (opModes == null || opModes.size() <= 0);
+ }
+ }
+
+ @Override
+ public boolean removePackage(String packageName) {
+ synchronized (mLock) {
+ SparseIntArray ops = mPackageModes.remove(packageName);
+ if (ops != null) {
+ mPersistenceScheduler.scheduleFastWriteLocked();
+ return true;
+ }
+ return false;
+ }
+ }
+
+ @Override
+ public void clearAllModes() {
+ synchronized (mLock) {
+ mUidModes.clear();
+ mPackageModes.clear();
+ }
+ }
+
+}
diff --git a/services/core/java/com/android/server/appop/PersistenceScheduler.java b/services/core/java/com/android/server/appop/PersistenceScheduler.java
new file mode 100644
index 0000000..e50b658
--- /dev/null
+++ b/services/core/java/com/android/server/appop/PersistenceScheduler.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appop;
+
+/**
+ * Interface that allows callers to persist AppOpsService's internal state
+ * to disk.
+ */
+public interface PersistenceScheduler {
+
+ /**
+ * Schedules disk writes for appOpsService and it's internal states.
+ */
+ void scheduleWriteLocked();
+
+ /**
+ * Schedules fast disk writes for appOpsService and it's internal states.
+ */
+ void scheduleFastWriteLocked();
+
+}
diff --git a/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java
index 351a1e9..23183f9 100644
--- a/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java
+++ b/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java
@@ -26,11 +26,14 @@
import android.hardware.radio.ITunerCallback;
import android.hardware.radio.RadioManager;
import android.os.RemoteException;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import com.android.server.SystemService;
import com.android.server.broadcastradio.hal2.AnnouncementAggregator;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -46,7 +49,7 @@
private final com.android.server.broadcastradio.hal2.BroadcastRadioService mHal2;
private final Object mLock = new Object();
- private List<RadioManager.ModuleProperties> mV1Modules = null;
+ private final List<RadioManager.ModuleProperties> mV1Modules;
public BroadcastRadioService(Context context) {
super(context);
@@ -115,5 +118,21 @@
return mHal2.addAnnouncementListener(enabledTypes, listener);
}
}
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ IndentingPrintWriter radioPw = new IndentingPrintWriter(pw);
+ radioPw.printf("BroadcastRadioService\n");
+ radioPw.increaseIndent();
+ radioPw.printf("HAL1: %s\n", mHal1);
+ radioPw.increaseIndent();
+ radioPw.printf("Modules of HAL1: %s\n", mV1Modules);
+ radioPw.decreaseIndent();
+ radioPw.printf("HAL2:\n");
+ radioPw.increaseIndent();
+ mHal2.dumpInfo(radioPw);
+ radioPw.decreaseIndent();
+ radioPw.decreaseIndent();
+ }
}
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
index 534e828..5605737 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
@@ -29,6 +29,7 @@
import android.hidl.manager.V1_0.IServiceNotification;
import android.os.IHwBinder.DeathRecipient;
import android.os.RemoteException;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
@@ -195,4 +196,30 @@
}
return aggregator;
}
+
+ /**
+ * Dump state of broadcastradio service for HIDL HAL 2.0.
+ *
+ * @param pw The file to which BroadcastRadioService state is dumped.
+ */
+ public void dumpInfo(IndentingPrintWriter pw) {
+ synchronized (mLock) {
+ pw.printf("Next module id available: %d\n", mNextModuleId);
+ pw.printf("ServiceName to module id map:\n");
+ pw.increaseIndent();
+ for (Map.Entry<String, Integer> entry : mServiceNameToModuleIdMap.entrySet()) {
+ pw.printf("Service name: %s, module id: %d\n", entry.getKey(), entry.getValue());
+ }
+ pw.decreaseIndent();
+ pw.printf("Radio modules:\n");
+ pw.increaseIndent();
+ for (Map.Entry<Integer, RadioModule> moduleEntry : mModules.entrySet()) {
+ pw.printf("Module id=%d:\n", moduleEntry.getKey());
+ pw.increaseIndent();
+ moduleEntry.getValue().dumpInfo(pw);
+ pw.decreaseIndent();
+ }
+ pw.decreaseIndent();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
index aeaa678..852aa66 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
@@ -38,6 +38,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
+import android.util.IndentingPrintWriter;
import android.util.MutableInt;
import android.util.Slog;
@@ -424,4 +425,30 @@
return BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
}
+
+ void dumpInfo(IndentingPrintWriter pw) {
+ pw.printf("RadioModule\n");
+ pw.increaseIndent();
+ synchronized (mLock) {
+ pw.printf("BroadcastRadioService: %s\n", mService);
+ pw.printf("Properties: %s\n", mProperties);
+ pw.printf("HIDL2.0 HAL TunerSession: %s\n", mHalTunerSession);
+ pw.printf("Is antenna connected? ");
+ if (mAntennaConnected == null) {
+ pw.printf("null\n");
+ } else {
+ pw.printf("%s\n", mAntennaConnected ? "Yes" : "No");
+ }
+ pw.printf("current ProgramInfo: %s\n", mCurrentProgramInfo);
+ pw.printf("ProgramInfoCache: %s\n", mProgramInfoCache);
+ pw.printf("Union of AIDL ProgramFilters: %s\n", mUnionOfAidlProgramFilters);
+ pw.printf("AIDL TunerSessions:\n");
+ pw.increaseIndent();
+ for (TunerSession aidlTunerSession : mAidlTunerSessions) {
+ aidlTunerSession.dumpInfo(pw);
+ }
+ pw.decreaseIndent();
+ }
+ pw.decreaseIndent();
+ }
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index c13216b..41f753c 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -27,6 +27,7 @@
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
import android.os.RemoteException;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.MutableBoolean;
import android.util.MutableInt;
@@ -339,4 +340,17 @@
() -> mHwSession.getParameters(Convert.listToArrayList(keys))));
}
}
+
+ void dumpInfo(IndentingPrintWriter pw) {
+ pw.printf("TunerSession\n");
+ pw.increaseIndent();
+ synchronized (mLock) {
+ pw.printf("HIDL HAL Session: %s\n", mHwSession);
+ pw.printf("Is session closed? %s\n", mIsClosed ? "Yes" : "No");
+ pw.printf("Is muted? %s\n", mIsMuted ? "Yes" : "No");
+ pw.printf("ProgramInfoCache: %s\n", mProgramInfoCache);
+ pw.printf("Config: %s\n", mDummyConfig);
+ }
+ pw.decreaseIndent();
+ }
}
diff --git a/services/core/java/com/android/server/display/RampAnimator.java b/services/core/java/com/android/server/display/RampAnimator.java
index 690ec3f..52b92c4 100644
--- a/services/core/java/com/android/server/display/RampAnimator.java
+++ b/services/core/java/com/android/server/display/RampAnimator.java
@@ -29,7 +29,6 @@
class RampAnimator<T> {
private final T mObject;
private final FloatProperty<T> mProperty;
- private final Choreographer mChoreographer;
private float mCurrentValue;
private float mTargetValue;
@@ -43,18 +42,16 @@
private boolean mFirstTime = true;
- private Listener mListener;
RampAnimator(T object, FloatProperty<T> property) {
mObject = object;
mProperty = property;
- mChoreographer = Choreographer.getInstance();
}
/**
* Sets the maximum time that a brightness animation can take.
*/
- public void setAnimationTimeLimits(long animationRampIncreaseMaxTimeMillis,
+ void setAnimationTimeLimits(long animationRampIncreaseMaxTimeMillis,
long animationRampDecreaseMaxTimeMillis) {
mAnimationIncreaseMaxTimeSecs = (animationRampIncreaseMaxTimeMillis > 0)
? (animationRampIncreaseMaxTimeMillis / 1000.0f) : 0.0f;
@@ -63,7 +60,7 @@
}
/**
- * Starts animating towards the specified value.
+ * Sets the animation target and the rate of this ramp animator.
*
* If this is the first time the property is being set or if the rate is 0,
* the value jumps directly to the target.
@@ -72,7 +69,7 @@
* @param rate The convergence rate in units per second, or 0 to set the value immediately.
* @return True if the target differs from the previous target.
*/
- public boolean animateTo(float targetLinear, float rate) {
+ boolean setAnimationTarget(float targetLinear, float rate) {
// Convert the target from the linear into the HLG space.
final float target = BrightnessUtils.convertLinearToGamma(targetLinear);
@@ -84,13 +81,7 @@
mTargetValue = target;
mCurrentValue = target;
setPropertyValue(target);
- if (mAnimating) {
- mAnimating = false;
- cancelAnimationCallback();
- }
- if (mListener != null) {
- mListener.onAnimationEnd();
- }
+ mAnimating = false;
return true;
}
return false;
@@ -127,7 +118,6 @@
mAnimating = true;
mAnimatedValue = mCurrentValue;
mLastFrameTimeNanos = System.nanoTime();
- postAnimationCallback();
}
return changed;
@@ -136,18 +126,11 @@
/**
* Returns true if the animation is running.
*/
- public boolean isAnimating() {
+ boolean isAnimating() {
return mAnimating;
}
/**
- * Sets a listener to watch for animation events.
- */
- public void setListener(Listener listener) {
- mListener = listener;
- }
-
- /**
* Sets the brightness property by converting the given value from HLG space
* into linear space.
*/
@@ -156,78 +139,53 @@
mProperty.setValue(mObject, linearVal);
}
- private void postAnimationCallback() {
- mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
- }
+ void performNextAnimationStep(long frameTimeNanos) {
+ final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos) * 0.000000001f;
+ mLastFrameTimeNanos = frameTimeNanos;
- private void cancelAnimationCallback() {
- mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
- }
-
- private final Runnable mAnimationCallback = new Runnable() {
- @Override // Choreographer callback
- public void run() {
- final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
- final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos)
- * 0.000000001f;
- mLastFrameTimeNanos = frameTimeNanos;
-
- // Advance the animated value towards the target at the specified rate
- // and clamp to the target. This gives us the new current value but
- // we keep the animated value around to allow for fractional increments
- // towards the target.
- final float scale = ValueAnimator.getDurationScale();
- if (scale == 0) {
- // Animation off.
- mAnimatedValue = mTargetValue;
+ // Advance the animated value towards the target at the specified rate
+ // and clamp to the target. This gives us the new current value but
+ // we keep the animated value around to allow for fractional increments
+ // towards the target.
+ final float scale = ValueAnimator.getDurationScale();
+ if (scale == 0) {
+ // Animation off.
+ mAnimatedValue = mTargetValue;
+ } else {
+ final float amount = timeDelta * mRate / scale;
+ if (mTargetValue > mCurrentValue) {
+ mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);
} else {
- final float amount = timeDelta * mRate / scale;
- if (mTargetValue > mCurrentValue) {
- mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);
- } else {
- mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
- }
- }
- final float oldCurrentValue = mCurrentValue;
- mCurrentValue = mAnimatedValue;
- if (oldCurrentValue != mCurrentValue) {
- setPropertyValue(mCurrentValue);
- }
- if (mTargetValue != mCurrentValue) {
- postAnimationCallback();
- } else {
- mAnimating = false;
- if (mListener != null) {
- mListener.onAnimationEnd();
- }
+ mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
}
}
- };
+ final float oldCurrentValue = mCurrentValue;
+ mCurrentValue = mAnimatedValue;
+ if (oldCurrentValue != mCurrentValue) {
+ setPropertyValue(mCurrentValue);
+ }
+ if (mTargetValue == mCurrentValue) {
+ mAnimating = false;
+ }
+ }
public interface Listener {
void onAnimationEnd();
}
static class DualRampAnimator<T> {
+ private final Choreographer mChoreographer;
private final RampAnimator<T> mFirst;
private final RampAnimator<T> mSecond;
- private final Listener mInternalListener = new Listener() {
- @Override
- public void onAnimationEnd() {
- if (mListener != null && !isAnimating()) {
- mListener.onAnimationEnd();
- }
- }
- };
private Listener mListener;
+ private boolean mAwaitingCallback;
DualRampAnimator(T object, FloatProperty<T> firstProperty,
FloatProperty<T> secondProperty) {
- mFirst = new RampAnimator(object, firstProperty);
- mFirst.setListener(mInternalListener);
- mSecond = new RampAnimator(object, secondProperty);
- mSecond.setListener(mInternalListener);
+ mChoreographer = Choreographer.getInstance();
+ mFirst = new RampAnimator<>(object, firstProperty);
+ mSecond = new RampAnimator<>(object, secondProperty);
}
/**
@@ -253,17 +211,56 @@
* @return True if either target differs from the previous target.
*/
public boolean animateTo(float linearFirstTarget, float linearSecondTarget, float rate) {
- final boolean firstRetval = mFirst.animateTo(linearFirstTarget, rate);
- final boolean secondRetval = mSecond.animateTo(linearSecondTarget, rate);
- return firstRetval && secondRetval;
+ boolean animationTargetChanged = mFirst.setAnimationTarget(linearFirstTarget, rate);
+ animationTargetChanged |= mSecond.setAnimationTarget(linearSecondTarget, rate);
+ boolean shouldBeAnimating = isAnimating();
+
+ if (shouldBeAnimating != mAwaitingCallback) {
+ if (shouldBeAnimating) {
+ mAwaitingCallback = true;
+ postAnimationCallback();
+ } else if (mAwaitingCallback) {
+ mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
+ mAnimationCallback, null);
+ mAwaitingCallback = false;
+ }
+ }
+ return animationTargetChanged;
}
+ /**
+ * Sets a listener to watch for animation events.
+ */
public void setListener(Listener listener) {
mListener = listener;
}
+ /**
+ * Returns true if the animation is running.
+ */
public boolean isAnimating() {
- return mFirst.isAnimating() && mSecond.isAnimating();
+ return mFirst.isAnimating() || mSecond.isAnimating();
}
+
+ private void postAnimationCallback() {
+ mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
+ }
+
+ private final Runnable mAnimationCallback = new Runnable() {
+ @Override // Choreographer callback
+ public void run() {
+ long frameTimeNanos = mChoreographer.getFrameTimeNanos();
+ mFirst.performNextAnimationStep(frameTimeNanos);
+ mSecond.performNextAnimationStep(frameTimeNanos);
+ if (isAnimating()) {
+ postAnimationCallback();
+ } else {
+ if (mListener != null) {
+ mListener.onAnimationEnd();
+ }
+ mAwaitingCallback = false;
+ }
+ }
+ };
}
}
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 9f44765..479629e 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -35,6 +35,7 @@
import static com.android.server.display.DisplayDeviceInfo.FLAG_TOUCH_FEEDBACK_DISABLED;
import static com.android.server.display.DisplayDeviceInfo.FLAG_TRUSTED;
+import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Point;
import android.hardware.display.IVirtualDisplayCallback;
@@ -110,15 +111,20 @@
} else {
uniqueId = UNIQUE_ID_PREFIX + ownerPackageName + ":" + uniqueId;
}
+ MediaProjectionCallback mediaProjectionCallback = null;
+ if (projection != null) {
+ mediaProjectionCallback = new MediaProjectionCallback(appToken);
+ }
VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken,
- ownerUid, ownerPackageName, surface, flags, new Callback(callback, mHandler),
+ ownerUid, ownerPackageName, surface, flags,
+ new Callback(callback, mHandler), projection, mediaProjectionCallback,
uniqueId, uniqueIndex, virtualDisplayConfig);
mVirtualDisplayDevices.put(appToken, device);
try {
if (projection != null) {
- projection.registerCallback(new MediaProjectionCallback(appToken));
+ projection.registerCallback(mediaProjectionCallback);
}
appToken.linkToDeath(device, 0);
} catch (RemoteException ex) {
@@ -223,6 +229,8 @@
final String mName;
private final int mFlags;
private final Callback mCallback;
+ @Nullable private final IMediaProjection mProjection;
+ @Nullable private final IMediaProjectionCallback mMediaProjectionCallback;
private int mWidth;
private int mHeight;
@@ -240,7 +248,8 @@
public VirtualDisplayDevice(IBinder displayToken, IBinder appToken,
int ownerUid, String ownerPackageName, Surface surface, int flags,
- Callback callback, String uniqueId, int uniqueIndex,
+ Callback callback, IMediaProjection projection,
+ IMediaProjectionCallback mediaProjectionCallback, String uniqueId, int uniqueIndex,
VirtualDisplayConfig virtualDisplayConfig) {
super(VirtualDisplayAdapter.this, displayToken, uniqueId, getContext());
mAppToken = appToken;
@@ -254,6 +263,8 @@
mSurface = surface;
mFlags = flags;
mCallback = callback;
+ mProjection = projection;
+ mMediaProjectionCallback = mediaProjectionCallback;
mDisplayState = Display.STATE_UNKNOWN;
mPendingChanges |= PENDING_SURFACE_CHANGE;
mUniqueIndex = uniqueIndex;
@@ -269,6 +280,13 @@
Slog.i(TAG, "Virtual display device released because application token died: "
+ mOwnerPackageName);
destroyLocked(false);
+ if (mProjection != null && mMediaProjectionCallback != null) {
+ try {
+ mProjection.unregisterCallback(mMediaProjectionCallback);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to unregister callback in binderDied", e);
+ }
+ }
sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_REMOVED);
}
}
@@ -279,6 +297,13 @@
mSurface = null;
}
SurfaceControl.destroyDisplay(getDisplayTokenLocked());
+ if (mProjection != null && mMediaProjectionCallback != null) {
+ try {
+ mProjection.unregisterCallback(mMediaProjectionCallback);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to unregister callback in destroy", e);
+ }
+ }
if (binderAlive) {
mCallback.dispatchDisplayStopped();
}
diff --git a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java
index 8180e66..0c889c2 100644
--- a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java
+++ b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java
@@ -32,11 +32,10 @@
public static final String TAG = HandwritingEventReceiverSurface.class.getSimpleName();
static final boolean DEBUG = HandwritingModeController.DEBUG;
- // Place the layer below the highest layer to place it under gesture monitors. If the surface
- // is above gesture monitors, then edge-back and swipe-up gestures won't work when this surface
- // is intercepting.
+ // Place the layer at the highest layer so stylus cannot trigger gesture monitors
+ // (e.g. navigation bar, edge-back, etc) while handwriting is ongoing.
// TODO(b/217538817): Specify the ordering in WM by usage.
- private static final int HANDWRITING_SURFACE_LAYER = Integer.MAX_VALUE - 1;
+ private static final int HANDWRITING_SURFACE_LAYER = Integer.MAX_VALUE;
private final InputWindowHandle mWindowHandle;
private final InputChannel mClientChannel;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index b86fa7a..f4ad750 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1627,7 +1627,7 @@
}
onSyntheticPasswordKnown(userId, sp);
- setLockCredentialWithSpLocked(credential, sp, userId, isLockTiedToParent);
+ setLockCredentialWithSpLocked(credential, sp, userId);
sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
return true;
}
@@ -1641,15 +1641,18 @@
if (newCredential.isPattern()) {
setBoolean(LockPatternUtils.PATTERN_EVER_CHOSEN_KEY, true, userHandle);
}
+ updatePasswordHistory(newCredential, userHandle);
mContext.getSystemService(TrustManager.class).reportEnabledTrustAgentsChanged(userHandle);
}
/**
* Store the hash of the new password in the password history list, if device policy enforces
* a password history requirement.
+ *
+ * This must not be called while the mSpManager lock is held, as this calls into
+ * DevicePolicyManagerService to get the requested password history length.
*/
- private void updatePasswordHistory(SyntheticPassword sp, LockscreenCredential password,
- int userHandle, boolean isLockTiedToParent) {
+ private void updatePasswordHistory(LockscreenCredential password, int userHandle) {
if (password.isNone()) {
return;
}
@@ -1657,10 +1660,6 @@
// Do not keep track of historical patterns
return;
}
- if (isLockTiedToParent) {
- // Do not keep track of historical auto-generated profile passwords
- return;
- }
// Add the password to the password history.
String passwordHistory = getString(
LockPatternUtils.PASSWORD_HISTORY_KEY, /* defaultValue= */ null, userHandle);
@@ -1671,9 +1670,16 @@
if (passwordHistoryLength == 0) {
passwordHistory = "";
} else {
- final byte[] hashFactor = sp.derivePasswordHashFactor();
+ final byte[] hashFactor = getHashFactor(password, userHandle);
final byte[] salt = getSalt(userHandle).getBytes();
String hash = password.passwordToHistoryHash(salt, hashFactor);
+ if (hash == null) {
+ // This should never happen, as all information needed to compute the hash should be
+ // available. In particular, unwrapping the SP in getHashFactor() should always
+ // succeed, as we're using the LSKF that was just set.
+ Slog.e(TAG, "Failed to compute password hash; password history won't be updated");
+ return;
+ }
if (TextUtils.isEmpty(passwordHistory)) {
passwordHistory = hash;
} else {
@@ -2644,7 +2650,7 @@
*/
@GuardedBy("mSpManager")
private long setLockCredentialWithSpLocked(LockscreenCredential credential,
- SyntheticPassword sp, int userId, boolean isLockTiedToParent) {
+ SyntheticPassword sp, int userId) {
if (DEBUG) Slog.d(TAG, "setLockCredentialWithSpLocked: user=" + userId);
final int savedCredentialType = getCredentialTypeInternal(userId);
final long oldProtectorId = getCurrentLskfBasedProtectorId(userId);
@@ -2682,7 +2688,6 @@
LockPatternUtils.invalidateCredentialTypeCache();
synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
- updatePasswordHistory(sp, credential, userId, isLockTiedToParent);
setUserPasswordMetrics(credential, userId);
mManagedProfilePasswordCache.removePassword(userId);
if (savedCredentialType != CREDENTIAL_TYPE_NONE) {
@@ -2928,8 +2933,7 @@
return false;
}
onSyntheticPasswordKnown(userId, result.syntheticPassword);
- setLockCredentialWithSpLocked(credential, result.syntheticPassword, userId,
- /* isLockTiedToParent= */ false);
+ setLockCredentialWithSpLocked(credential, result.syntheticPassword, userId);
return true;
}
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 48ec436..bda7b82 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -816,9 +816,10 @@
}
// Allow package verifier to silently uninstall.
- if (mPm.mRequiredVerifierPackage != null && callingUid == snapshot
- .getPackageUid(mPm.mRequiredVerifierPackage, 0, callingUserId)) {
- return true;
+ for (String verifierPackageName : mPm.mRequiredVerifierPackages) {
+ if (callingUid == snapshot.getPackageUid(verifierPackageName, 0, callingUserId)) {
+ return true;
+ }
}
// Allow package uninstaller to silently uninstall.
diff --git a/services/core/java/com/android/server/pm/DumpHelper.java b/services/core/java/com/android/server/pm/DumpHelper.java
index 7352018..d2a5e32 100644
--- a/services/core/java/com/android/server/pm/DumpHelper.java
+++ b/services/core/java/com/android/server/pm/DumpHelper.java
@@ -54,7 +54,7 @@
private final StorageEventHelper mStorageEventHelper;
private final DomainVerificationManagerInternal mDomainVerificationManager;
private final PackageInstallerService mInstallerService;
- private final String mRequiredVerifierPackage;
+ private final String[] mRequiredVerifierPackages;
private final KnownPackages mKnownPackages;
private final ChangedPackagesTracker mChangedPackagesTracker;
private final ArrayMap<String, FeatureInfo> mAvailableFeatures;
@@ -65,7 +65,7 @@
PermissionManagerServiceInternal permissionManager,
StorageEventHelper storageEventHelper,
DomainVerificationManagerInternal domainVerificationManager,
- PackageInstallerService installerService, String requiredVerifierPackage,
+ PackageInstallerService installerService, String[] requiredVerifierPackages,
KnownPackages knownPackages,
ChangedPackagesTracker changedPackagesTracker,
ArrayMap<String, FeatureInfo> availableFeatures,
@@ -75,7 +75,7 @@
mStorageEventHelper = storageEventHelper;
mDomainVerificationManager = domainVerificationManager;
mInstallerService = installerService;
- mRequiredVerifierPackage = requiredVerifierPackage;
+ mRequiredVerifierPackages = requiredVerifierPackages;
mKnownPackages = knownPackages;
mChangedPackagesTracker = changedPackagesTracker;
mAvailableFeatures = availableFeatures;
@@ -313,26 +313,28 @@
ipw.decreaseIndent();
}
- if (dumpState.isDumping(DumpState.DUMP_VERIFIERS)
- && packageName == null) {
- final String requiredVerifierPackage = mRequiredVerifierPackage;
- if (!checkin) {
+ if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
+ if (!checkin && mRequiredVerifierPackages.length > 0) {
if (dumpState.onTitlePrinted()) {
pw.println();
}
pw.println("Verifiers:");
- pw.print(" Required: ");
- pw.print(requiredVerifierPackage);
- pw.print(" (uid=");
- pw.print(snapshot.getPackageUid(requiredVerifierPackage,
- MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
- pw.println(")");
- } else if (requiredVerifierPackage != null) {
- pw.print("vrfy,");
- pw.print(requiredVerifierPackage);
- pw.print(",");
- pw.println(snapshot.getPackageUid(requiredVerifierPackage,
- MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
+ }
+ for (String requiredVerifierPackage : mRequiredVerifierPackages) {
+ if (!checkin) {
+ pw.print(" Required: ");
+ pw.print(requiredVerifierPackage);
+ pw.print(" (uid=");
+ pw.print(snapshot.getPackageUid(requiredVerifierPackage,
+ MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
+ pw.println(")");
+ } else {
+ pw.print("vrfy,");
+ pw.print(requiredVerifierPackage);
+ pw.print(",");
+ pw.println(snapshot.getPackageUid(requiredVerifierPackage,
+ MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
+ }
}
}
@@ -642,17 +644,19 @@
private void dumpProto(Computer snapshot, FileDescriptor fd) {
final ProtoOutputStream proto = new ProtoOutputStream(fd);
- final long requiredVerifierPackageToken =
- proto.start(PackageServiceDumpProto.REQUIRED_VERIFIER_PACKAGE);
- proto.write(PackageServiceDumpProto.PackageShortProto.NAME,
- mRequiredVerifierPackage);
- proto.write(
- PackageServiceDumpProto.PackageShortProto.UID,
- snapshot.getPackageUid(
- mRequiredVerifierPackage,
- MATCH_DEBUG_TRIAGED_MISSING,
- UserHandle.USER_SYSTEM));
- proto.end(requiredVerifierPackageToken);
+ for (String requiredVerifierPackage : mRequiredVerifierPackages) {
+ final long requiredVerifierPackageToken =
+ proto.start(PackageServiceDumpProto.REQUIRED_VERIFIER_PACKAGE);
+ proto.write(PackageServiceDumpProto.PackageShortProto.NAME,
+ requiredVerifierPackage);
+ proto.write(
+ PackageServiceDumpProto.PackageShortProto.UID,
+ snapshot.getPackageUid(
+ requiredVerifierPackage,
+ MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.USER_SYSTEM));
+ proto.end(requiredVerifierPackageToken);
+ }
DomainVerificationProxy proxy = mDomainVerificationManager.getProxy();
ComponentName verifierComponent = proxy.getComponentName();
diff --git a/services/core/java/com/android/server/pm/InitAppsHelper.java b/services/core/java/com/android/server/pm/InitAppsHelper.java
index 122ab10..52e3fd9 100644
--- a/services/core/java/com/android/server/pm/InitAppsHelper.java
+++ b/services/core/java/com/android/server/pm/InitAppsHelper.java
@@ -46,6 +46,7 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.om.OverlayConfig;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.EventLogTags;
@@ -401,4 +402,9 @@
public List<ScanPartition> getDirsToScanAsSystem() {
return mDirsToScanAsSystem;
}
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public int getSystemScanFlags() {
+ return mSystemScanFlags;
+ }
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 8bb9b84..728d2d1 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -2719,15 +2719,16 @@
installerPackageName, null /*finishedReceiver*/,
updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
}
- // if the required verifier is defined, but, is not the installer of record
- // for the package, it gets notified
- final boolean notifyVerifier = mPm.mRequiredVerifierPackage != null
- && !mPm.mRequiredVerifierPackage.equals(installerPackageName);
- if (notifyVerifier) {
- mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
- extras, 0 /*flags*/,
- mPm.mRequiredVerifierPackage, null /*finishedReceiver*/,
- updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
+ // Notify required verifier(s) that are not the installer of record for the package.
+ for (String verifierPackageName : mPm.mRequiredVerifierPackages) {
+ if (verifierPackageName != null && !verifierPackageName.equals(
+ installerPackageName)) {
+ mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
+ extras, 0 /*flags*/,
+ verifierPackageName, null /*finishedReceiver*/,
+ updateUserIds, instantUserIds, null /* broadcastAllowList */,
+ null);
+ }
}
// If package installer is defined, notify package installer about new
// app installed
@@ -2752,12 +2753,14 @@
updateUserIds, instantUserIds, null /*broadcastAllowList*/,
null);
}
- if (notifyVerifier) {
- mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
- extras, 0 /*flags*/,
- mPm.mRequiredVerifierPackage, null /*finishedReceiver*/,
- updateUserIds, instantUserIds, null /*broadcastAllowList*/,
- null);
+ for (String verifierPackageName : mPm.mRequiredVerifierPackages) {
+ if (verifierPackageName != null && !verifierPackageName.equals(
+ installerPackageName)) {
+ mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
+ packageName, extras, 0 /*flags*/, verifierPackageName,
+ null /*finishedReceiver*/, updateUserIds, instantUserIds,
+ null /*broadcastAllowList*/, null);
+ }
}
mPm.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
null /*package*/, null /*extras*/, 0 /*flags*/,
diff --git a/services/core/java/com/android/server/pm/KnownPackages.java b/services/core/java/com/android/server/pm/KnownPackages.java
index 04376b4..dcf7152 100644
--- a/services/core/java/com/android/server/pm/KnownPackages.java
+++ b/services/core/java/com/android/server/pm/KnownPackages.java
@@ -79,7 +79,7 @@
private final String mRequiredInstallerPackage;
private final String mRequiredUninstallerPackage;
private final String mSetupWizardPackage;
- private final String mRequiredVerifierPackage;
+ private final String[] mRequiredVerifierPackages;
private final String mDefaultTextClassifierPackage;
private final String mSystemTextClassifierPackageName;
private final String mRequiredPermissionControllerPackage;
@@ -94,7 +94,7 @@
KnownPackages(DefaultAppProvider defaultAppProvider, String requiredInstallerPackage,
String requiredUninstallerPackage, String setupWizardPackage,
- String requiredVerifierPackage, String defaultTextClassifierPackage,
+ String[] requiredVerifierPackages, String defaultTextClassifierPackage,
String systemTextClassifierPackageName, String requiredPermissionControllerPackage,
String configuratorPackage, String incidentReportApproverPackage,
String ambientContextDetectionPackage, String appPredictionServicePackage,
@@ -104,7 +104,7 @@
mRequiredInstallerPackage = requiredInstallerPackage;
mRequiredUninstallerPackage = requiredUninstallerPackage;
mSetupWizardPackage = setupWizardPackage;
- mRequiredVerifierPackage = requiredVerifierPackage;
+ mRequiredVerifierPackages = requiredVerifierPackages;
mDefaultTextClassifierPackage = defaultTextClassifierPackage;
mSystemTextClassifierPackageName = systemTextClassifierPackageName;
mRequiredPermissionControllerPackage = requiredPermissionControllerPackage;
@@ -182,7 +182,7 @@
case PACKAGE_SYSTEM:
return new String[]{"android"};
case PACKAGE_VERIFIER:
- return snapshot.filterOnlySystemPackages(mRequiredVerifierPackage);
+ return snapshot.filterOnlySystemPackages(mRequiredVerifierPackages);
case PACKAGE_SYSTEM_TEXT_CLASSIFIER:
return snapshot.filterOnlySystemPackages(
mDefaultTextClassifierPackage, mSystemTextClassifierPackageName);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 32b3e6a..8b40f65 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -238,6 +238,7 @@
import dalvik.system.VMRuntime;
+import libcore.util.EmptyArray;
import libcore.util.HexEncoding;
import java.io.ByteArrayInputStream;
@@ -521,6 +522,9 @@
private static final String COMPANION_PACKAGE_NAME = "com.android.companiondevicemanager";
+ // How many required verifiers can be on the system.
+ private static final int REQUIRED_VERIFIERS_MAX_COUNT = 2;
+
// Compilation reasons.
public static final int REASON_FIRST_BOOT = 0;
public static final int REASON_BOOT_AFTER_OTA = 1;
@@ -906,7 +910,7 @@
final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<>();
int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows
- final @Nullable String mRequiredVerifierPackage;
+ final @NonNull String[] mRequiredVerifierPackages;
final @NonNull String mRequiredInstallerPackage;
final @NonNull String mRequiredUninstallerPackage;
final @NonNull String mRequiredPermissionControllerPackage;
@@ -1642,7 +1646,7 @@
mProtectedPackages = testParams.protectedPackages;
mSeparateProcesses = testParams.separateProcesses;
mViewCompiler = testParams.viewCompiler;
- mRequiredVerifierPackage = testParams.requiredVerifierPackage;
+ mRequiredVerifierPackages = testParams.requiredVerifierPackages;
mRequiredInstallerPackage = testParams.requiredInstallerPackage;
mRequiredUninstallerPackage = testParams.requiredUninstallerPackage;
mRequiredPermissionControllerPackage = testParams.requiredPermissionControllerPackage;
@@ -2126,7 +2130,7 @@
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
- mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr(computer);
+ mRequiredVerifierPackages = getRequiredButNotReallyRequiredVerifiersLPr(computer);
mRequiredInstallerPackage = getRequiredInstallerLPr(computer);
mRequiredUninstallerPackage = getRequiredUninstallerLPr(computer);
ComponentName intentFilterVerifierComponent =
@@ -2265,8 +2269,8 @@
"persist.pm.mock-upgrade", false /* default */);
}
- @Nullable
- private String getRequiredButNotReallyRequiredVerifierLPr(@NonNull Computer computer) {
+ @NonNull
+ private String[] getRequiredButNotReallyRequiredVerifiersLPr(@NonNull Computer computer) {
final Intent intent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
final List<ResolveInfo> matches =
@@ -2274,13 +2278,23 @@
PACKAGE_MIME_TYPE,
MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
UserHandle.USER_SYSTEM, Binder.getCallingUid());
- if (matches.size() == 1) {
- return matches.get(0).getComponentInfo().packageName;
- } else if (matches.size() == 0) {
+ final int size = matches.size();
+ if (size == 0) {
Log.w(TAG, "There should probably be a verifier, but, none were found");
- return null;
+ return EmptyArray.STRING;
+ } else if (size <= REQUIRED_VERIFIERS_MAX_COUNT) {
+ String[] verifiers = new String[size];
+ for (int i = 0; i < size; ++i) {
+ verifiers[i] = matches.get(i).getComponentInfo().packageName;
+ if (TextUtils.isEmpty(verifiers[i])) {
+ throw new RuntimeException("Invalid verifier: " + matches);
+ }
+ }
+ return verifiers;
}
- throw new RuntimeException("There must be exactly one verifier; found " + matches);
+ throw new RuntimeException(
+ "There must be no more than " + REQUIRED_VERIFIERS_MAX_COUNT + " verifiers; found "
+ + matches);
}
@NonNull
@@ -3153,8 +3167,12 @@
boolean isCallerVerifier(@NonNull Computer snapshot, int callingUid) {
final int callingUserId = UserHandle.getUserId(callingUid);
- return mRequiredVerifierPackage != null && callingUid == snapshot.getPackageUid(
- mRequiredVerifierPackage, 0, callingUserId);
+ for (String requiredVerifierPackage : mRequiredVerifierPackages) {
+ if (callingUid == snapshot.getPackageUid(requiredVerifierPackage, 0, callingUserId)) {
+ return true;
+ }
+ }
+ return false;
}
public boolean isPackageDeviceAdminOnAnyUser(@NonNull Computer snapshot, String packageName) {
@@ -4665,15 +4683,28 @@
}
@Override
- public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
+ public void extendVerificationTimeout(int verificationId, int verificationCodeAtTimeout,
long millisecondsToDelay) {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.PACKAGE_VERIFICATION_AGENT,
- "Only package verification agents can extend verification timeouts");
+ // Negative ids correspond to testing verifiers and will be silently enforced in
+ // the handler thread.
+ if (verificationId >= 0) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.PACKAGE_VERIFICATION_AGENT,
+ "Only package verification agents can extend verification timeouts");
+ }
final int callingUid = Binder.getCallingUid();
mHandler.post(() -> {
+ final int id = verificationId >= 0 ? verificationId : -verificationId;
final PackageVerificationState state = mPendingVerification.get(id);
+ if (state == null || state.timeoutExtended() || !state.checkRequiredVerifierUid(
+ callingUid)) {
+ // Only allow calls from required verifiers.
+ return;
+ }
+
+ state.extendTimeout();
+
final PackageVerificationResponse response = new PackageVerificationResponse(
verificationCodeAtTimeout, callingUid);
@@ -4685,14 +4716,10 @@
delay = 0;
}
- if ((state != null) && !state.timeoutExtended()) {
- state.extendTimeout();
-
- final Message msg = mHandler.obtainMessage(PackageManagerService.PACKAGE_VERIFIED);
- msg.arg1 = id;
- msg.obj = response;
- mHandler.sendMessageDelayed(msg, delay);
- }
+ final Message msg = mHandler.obtainMessage(PackageManagerService.PACKAGE_VERIFIED);
+ msg.arg1 = id;
+ msg.obj = response;
+ mHandler.sendMessageDelayed(msg, delay);
});
}
@@ -5434,13 +5461,19 @@
final long callingId = Binder.clearCallingIdentity();
try {
- final PackageStateInternal packageState =
- snapshot.getPackageStateForInstalledAndFiltered(
- packageName, callingUid, userId);
+ final PackageStateInternal packageState = snapshot.getPackageStateInternal(
+ packageName);
if (packageState == null) {
return false;
}
+ final PackageUserStateInternal userState = packageState.getUserStateOrDefault(
+ userId);
+ if (userState.isHidden() == hidden || !userState.isInstalled()
+ || snapshot.shouldFilterApplication(packageState, callingUid, userId)) {
+ return false;
+ }
+
// Cannot hide static shared libs as they are considered
// a part of the using app (emulating static linking). Also
// static libs are installed always on internal storage.
@@ -5470,10 +5503,6 @@
return false;
}
- if (packageState.getUserStateOrDefault(userId).isHidden() == hidden) {
- return false;
- }
-
commitPackageStateMutation(null, packageName, packageState1 ->
packageState1.userState(userId).setHidden(hidden));
@@ -5862,18 +5891,32 @@
}
@Override
- public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.PACKAGE_VERIFICATION_AGENT,
- "Only package verification agents can verify applications");
+ public void verifyPendingInstall(int verificationId, int verificationCode)
+ throws RemoteException {
+ // Negative ids correspond to testing verifiers and will be silently enforced in
+ // the handler thread.
+ if (verificationId >= 0) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.PACKAGE_VERIFICATION_AGENT,
+ "Only package verification agents can verify applications");
+ }
final int callingUid = Binder.getCallingUid();
- final Message msg = mHandler.obtainMessage(PackageManagerService.PACKAGE_VERIFIED);
- final PackageVerificationResponse response = new PackageVerificationResponse(
- verificationCode, callingUid);
- msg.arg1 = id;
- msg.obj = response;
- mHandler.sendMessage(msg);
+ mHandler.post(() -> {
+ final int id = verificationId >= 0 ? verificationId : -verificationId;
+ final PackageVerificationState state = mPendingVerification.get(id);
+ if (state == null || !state.checkRequiredVerifierUid(callingUid)) {
+ // Only allow calls from required verifiers.
+ return;
+ }
+
+ final Message msg = mHandler.obtainMessage(PackageManagerService.PACKAGE_VERIFIED);
+ final PackageVerificationResponse response = new PackageVerificationResponse(
+ verificationCode, callingUid);
+ msg.arg1 = id;
+ msg.obj = response;
+ mHandler.sendMessage(msg);
+ });
}
@Override
@@ -5928,7 +5971,7 @@
mRequiredInstallerPackage,
mRequiredUninstallerPackage,
mSetupWizardPackage,
- mRequiredVerifierPackage,
+ mRequiredVerifierPackages,
mDefaultTextClassifierPackage,
mSystemTextClassifierPackageName,
mRequiredPermissionControllerPackage,
@@ -5949,7 +5992,7 @@
protectedBroadcasts = new ArraySet<>(mProtectedBroadcasts);
}
new DumpHelper(mPermissionManager, mStorageEventHelper,
- mDomainVerificationManager, mInstallerService, mRequiredVerifierPackage,
+ mDomainVerificationManager, mInstallerService, mRequiredVerifierPackages,
knownPackages, mChangedPackagesTracker, availableFeatures, protectedBroadcasts,
getPerUidReadTimeouts(snapshot)
).doDump(snapshot, fd, pw, args);
@@ -6956,7 +6999,7 @@
mRequiredInstallerPackage,
mRequiredUninstallerPackage,
mSetupWizardPackage,
- mRequiredVerifierPackage,
+ mRequiredVerifierPackages,
mDefaultTextClassifierPackage,
mSystemTextClassifierPackageName,
mRequiredPermissionControllerPackage,
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
index f44d922..ec1b29e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
@@ -80,7 +80,7 @@
public @NonNull String requiredInstallerPackage;
public @NonNull String requiredPermissionControllerPackage;
public @NonNull String requiredUninstallerPackage;
- public @Nullable String requiredVerifierPackage;
+ public @NonNull String[] requiredVerifierPackages;
public String[] separateProcesses;
public @NonNull String servicesExtensionPackageName;
public @Nullable String setupWizardPackage;
diff --git a/services/core/java/com/android/server/pm/PackageVerificationState.java b/services/core/java/com/android/server/pm/PackageVerificationState.java
index d105fc4..a574fc9 100644
--- a/services/core/java/com/android/server/pm/PackageVerificationState.java
+++ b/services/core/java/com/android/server/pm/PackageVerificationState.java
@@ -30,7 +30,7 @@
private final SparseBooleanArray mSufficientVerifierUids;
- private int mRequiredVerifierUid;
+ private final SparseBooleanArray mRequiredVerifierUids;
private boolean mSufficientVerificationComplete;
@@ -51,6 +51,9 @@
PackageVerificationState(VerifyingSession verifyingSession) {
mVerifyingSession = verifyingSession;
mSufficientVerifierUids = new SparseBooleanArray();
+ mRequiredVerifierUids = new SparseBooleanArray();
+ mRequiredVerificationComplete = false;
+ mRequiredVerificationPassed = true;
mExtendedTimeout = false;
}
@@ -58,9 +61,14 @@
return mVerifyingSession;
}
- /** Sets the user ID of the required package verifier. */
- void setRequiredVerifierUid(int uid) {
- mRequiredVerifierUid = uid;
+ /** Add the user ID of the required package verifier. */
+ void addRequiredVerifierUid(int uid) {
+ mRequiredVerifierUids.put(uid, true);
+ }
+
+ /** Returns true if the uid a required verifier. */
+ boolean checkRequiredVerifierUid(int uid) {
+ return mRequiredVerifierUids.get(uid, false);
}
/**
@@ -80,39 +88,55 @@
* @return {@code true} if the verifying agent actually exists in our list
*/
boolean setVerifierResponse(int uid, int code) {
- if (uid == mRequiredVerifierUid) {
- mRequiredVerificationComplete = true;
+ if (mRequiredVerifierUids.get(uid)) {
switch (code) {
case PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT:
mSufficientVerifierUids.clear();
// fall through
case PackageManager.VERIFICATION_ALLOW:
- mRequiredVerificationPassed = true;
+ // Two possible options:
+ // - verification result is true,
+ // - another verifier set it to false.
+ // In both cases we don't need to assign anything, just exit.
break;
default:
mRequiredVerificationPassed = false;
}
- return true;
- } else {
- if (mSufficientVerifierUids.get(uid)) {
- if (code == PackageManager.VERIFICATION_ALLOW) {
- mSufficientVerificationComplete = true;
- mSufficientVerificationPassed = true;
- }
- mSufficientVerifierUids.delete(uid);
- if (mSufficientVerifierUids.size() == 0) {
- mSufficientVerificationComplete = true;
- }
-
- return true;
+ mRequiredVerifierUids.delete(uid);
+ if (mRequiredVerifierUids.size() == 0) {
+ mRequiredVerificationComplete = true;
}
+ return true;
+ } else if (mSufficientVerifierUids.get(uid)) {
+ if (code == PackageManager.VERIFICATION_ALLOW) {
+ mSufficientVerificationPassed = true;
+ mSufficientVerificationComplete = true;
+ }
+
+ mSufficientVerifierUids.delete(uid);
+ if (mSufficientVerifierUids.size() == 0) {
+ mSufficientVerificationComplete = true;
+ }
+
+ return true;
}
return false;
}
/**
+ * Mark the session as passed required verification.
+ */
+ void passRequiredVerification() {
+ if (mRequiredVerifierUids.size() > 0) {
+ throw new RuntimeException("Required verifiers still present.");
+ }
+ mRequiredVerificationPassed = true;
+ mRequiredVerificationComplete = true;
+ }
+
+ /**
* Returns whether verification is considered complete. This means that the required verifier
* and at least one of the sufficient verifiers has returned a positive verification.
*
@@ -137,15 +161,15 @@
* @return {@code true} if installation should be allowed
*/
boolean isInstallAllowed() {
- if (!mRequiredVerificationComplete) {
+ if (!mRequiredVerificationComplete || !mRequiredVerificationPassed) {
return false;
}
if (mSufficientVerificationComplete) {
- return mRequiredVerificationPassed && mSufficientVerificationPassed;
+ return mSufficientVerificationPassed;
}
- return mRequiredVerificationPassed;
+ return true;
}
/** Extend the timeout for this Package to be verified. */
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index f931ba8..01aecd9 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -126,10 +126,9 @@
unmodifiablePackages.add(packageName);
continue;
}
- final PackageStateInternal packageState =
- snapshot.getPackageStateForInstalledAndFiltered(
- packageName, callingUid, userId);
- if (packageState == null) {
+ final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName);
+ if (packageState == null || !packageState.getUserStateOrDefault(userId).isInstalled()
+ || snapshot.shouldFilterApplication(packageState, callingUid, userId)) {
Slog.w(TAG, "Could not find package setting for package: " + packageName
+ ". Skipping suspending/un-suspending.");
unmodifiablePackages.add(packageName);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index e022f15..0c1c265 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -6010,6 +6010,10 @@
} // synchronized (mPackagesLock)
+ // Multiple Users on Multiple Display info
+ pw.println(" Supports users on secondary displays: "
+ + UserManager.isUsersOnSecondaryDisplaysEnabled());
+
// Dump some capabilities
pw.println();
pw.print(" Max users: " + UserManager.getMaxSupportedUsers());
diff --git a/services/core/java/com/android/server/pm/VerifyingSession.java b/services/core/java/com/android/server/pm/VerifyingSession.java
index 9bad4a8..0a39e64 100644
--- a/services/core/java/com/android/server/pm/VerifyingSession.java
+++ b/services/core/java/com/android/server/pm/VerifyingSession.java
@@ -353,45 +353,54 @@
}
final int verifierUserId = verifierUser.getIdentifier();
- String requiredVerifierPackage = mPm.mRequiredVerifierPackage;
- boolean requiredVerifierPackageOverridden = false;
+ String[] requiredVerifierPackages = mPm.mRequiredVerifierPackages;
+ boolean requiredVerifierPackagesOverridden = false;
// Allow verifier override for ADB installations which could already be unverified using
// PackageManager.INSTALL_DISABLE_VERIFICATION flag.
if ((mInstallFlags & PackageManager.INSTALL_FROM_ADB) != 0
&& (mInstallFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) == 0) {
- final String adbVerifierOverridePackage = SystemProperties.get(
- "debug.pm.adb_verifier_override_package", "");
- // Check if the package installed.
- if (!TextUtils.isEmpty(adbVerifierOverridePackage)
- && packageExists(adbVerifierOverridePackage)) {
- // Pretend we requested to disable verification from command line.
- boolean requestedDisableVerification = true;
- // If this returns false then the caller can already skip verification, so we are
- // not adding a new way to disable verifications.
- if (!isAdbVerificationEnabled(pkgLite, verifierUserId,
- requestedDisableVerification)) {
- requiredVerifierPackage = adbVerifierOverridePackage;
- requiredVerifierPackageOverridden = true;
+ String property = SystemProperties.get("debug.pm.adb_verifier_override_packages", "");
+ if (!TextUtils.isEmpty(property)) {
+ String[] verifierPackages = property.split(";");
+ List<String> adbVerifierOverridePackages = new ArrayList<>();
+ for (String verifierPackage : verifierPackages) {
+ if (!TextUtils.isEmpty(verifierPackage) && packageExists(verifierPackage)) {
+ adbVerifierOverridePackages.add(verifierPackage);
+ }
+ }
+ // Check if the package installed.
+ if (adbVerifierOverridePackages.size() > 0) {
+ // Pretend we requested to disable verification from command line.
+ boolean requestedDisableVerification = true;
+ // If this returns false then the caller can already skip verification, so we
+ // are not adding a new way to disable verifications.
+ if (!isAdbVerificationEnabled(pkgLite, verifierUserId,
+ requestedDisableVerification)) {
+ requiredVerifierPackages = adbVerifierOverridePackages.toArray(
+ new String[adbVerifierOverridePackages.size()]);
+ requiredVerifierPackagesOverridden = true;
+ }
}
}
}
+ if (mOriginInfo.mExisting || !isVerificationEnabled(pkgLite, verifierUserId,
+ requiredVerifierPackages)) {
+ verificationState.passRequiredVerification();
+ return;
+ }
+
/*
* Determine if we have any installed package verifiers. If we
* do, then we'll defer to them to verify the packages.
*/
final Computer snapshot = mPm.snapshotComputer();
- final int requiredUid = requiredVerifierPackage == null ? -1
- : snapshot.getPackageUid(requiredVerifierPackage,
- MATCH_DEBUG_TRIAGED_MISSING, verifierUserId);
- verificationState.setRequiredVerifierUid(requiredUid);
- final boolean isVerificationEnabled = isVerificationEnabled(pkgLite,
- verifierUserId);
- if (mOriginInfo.mExisting || !isVerificationEnabled) {
- verificationState.setVerifierResponse(requiredUid, PackageManager.VERIFICATION_ALLOW);
- return;
+ for (String requiredVerifierPackage : requiredVerifierPackages) {
+ final int requiredUid = snapshot.getPackageUid(requiredVerifierPackage,
+ MATCH_DEBUG_TRIAGED_MISSING, verifierUserId);
+ verificationState.addRequiredVerifierUid(requiredUid);
}
final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
@@ -428,11 +437,13 @@
final String baseCodePath = mPackageLite.getBaseApkPath();
final String[] splitCodePaths = mPackageLite.getSplitApkPaths();
+ final String rootHashString;
if (IncrementalManager.isIncrementalPath(baseCodePath)) {
- final String rootHashString =
- PackageManagerServiceUtils.buildVerificationRootHashString(
- baseCodePath, splitCodePaths);
+ rootHashString = PackageManagerServiceUtils.buildVerificationRootHashString(
+ baseCodePath, splitCodePaths);
verification.putExtra(PackageManager.EXTRA_VERIFICATION_ROOT_HASH, rootHashString);
+ } else {
+ rootHashString = null;
}
verification.putExtra(PackageInstaller.EXTRA_DATA_LOADER_TYPE, mDataLoaderType);
@@ -503,8 +514,8 @@
}
}
- if (requiredVerifierPackage == null) {
- Slog.e(TAG, "Required verifier is null");
+ if (requiredVerifierPackages.length == 0) {
+ Slog.e(TAG, "No required verifiers");
return;
}
@@ -514,47 +525,75 @@
} else {
verificationCodeAtTimeout = PackageManager.VERIFICATION_REJECT;
}
- final PackageVerificationResponse response = new PackageVerificationResponse(
- verificationCodeAtTimeout, requiredUid);
- /*
- * Send the intent to the required verification agent,
- * but only start the verification timeout after the
- * target BroadcastReceivers have run.
- */
- if (!requiredVerifierPackageOverridden) {
- final ComponentName requiredVerifierComponent = matchComponentForVerifier(
- requiredVerifierPackage, receivers.getList());
- verification.setComponent(requiredVerifierComponent);
- } else {
- verification.setPackage(requiredVerifierPackage);
- }
- idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
- requiredVerifierPackage, verificationTimeout,
- verifierUserId, false,
- REASON_PACKAGE_VERIFIER, "package verifier");
+ for (String requiredVerifierPackage : requiredVerifierPackages) {
+ final int requiredUid = snapshot.getPackageUid(requiredVerifierPackage,
+ MATCH_DEBUG_TRIAGED_MISSING, verifierUserId);
- if (streaming) {
- // For streaming installations, count verification timeout from the broadcast.
- startVerificationTimeoutCountdown(verificationId, streaming, response,
- verificationTimeout);
- }
+ final Intent requiredIntent;
+ final String receiverPermission;
+ if (!requiredVerifierPackagesOverridden || requiredVerifierPackages.length == 1) {
+ // Prod code OR test code+single verifier.
+ requiredIntent = new Intent(verification);
+ if (!requiredVerifierPackagesOverridden) {
+ ComponentName requiredVerifierComponent = matchComponentForVerifier(
+ requiredVerifierPackage, receivers.getList());
+ requiredIntent.setComponent(requiredVerifierComponent);
+ } else {
+ requiredIntent.setPackage(requiredVerifierPackage);
+ }
+ receiverPermission = android.Manifest.permission.PACKAGE_VERIFICATION_AGENT;
+ } else {
+ // Test code+multiple verifiers.
+ // Recreate the intent to contain test-only information.
+ requiredIntent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+ requiredIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ requiredIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ requiredIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+ requiredIntent.setDataAndType(Uri.fromFile(new File(mOriginInfo.mResolvedPath)),
+ PACKAGE_MIME_TYPE);
+ requiredIntent.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
+ requiredIntent.putExtra(PackageInstaller.EXTRA_DATA_LOADER_TYPE, mDataLoaderType);
+ if (rootHashString != null) {
+ requiredIntent.putExtra(PackageManager.EXTRA_VERIFICATION_ROOT_HASH,
+ rootHashString);
+ }
+ requiredIntent.setPackage(requiredVerifierPackage);
+ // Negative verification id.
+ requiredIntent.putExtra(PackageManager.EXTRA_VERIFICATION_ID, -verificationId);
+ // OK not to have permission.
+ receiverPermission = null;
+ }
- mPm.mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
- android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
- /* appOp= */ AppOpsManager.OP_NONE,
- /* options= */ options.toBundle(),
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!streaming) {
- // For NON-streaming installations, count verification timeout from
- // the broadcast was processed by all receivers.
- startVerificationTimeoutCountdown(verificationId, streaming, response,
- verificationTimeout);
+ idleController.addPowerSaveTempWhitelistApp(Process.myUid(), requiredVerifierPackage,
+ verificationTimeout, verifierUserId, false, REASON_PACKAGE_VERIFIER,
+ "package verifier");
+
+ final PackageVerificationResponse response = new PackageVerificationResponse(
+ verificationCodeAtTimeout, requiredUid);
+
+ if (streaming) {
+ // For streaming installations, count verification timeout from the broadcast.
+ startVerificationTimeoutCountdown(verificationId, streaming, response,
+ verificationTimeout);
+ }
+
+ // Send the intent to the required verification agent, but only start the
+ // verification timeout after the target BroadcastReceivers have run.
+ mPm.mContext.sendOrderedBroadcastAsUser(requiredIntent, verifierUser,
+ receiverPermission, AppOpsManager.OP_NONE, options.toBundle(),
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!streaming) {
+ // For NON-streaming installations, count verification timeout from
+ // the broadcast was processed by all receivers.
+ startVerificationTimeoutCountdown(verificationId, streaming,
+ response, verificationTimeout);
+ }
}
- }
- }, null, 0, null, null);
+ }, null, 0, null, null);
+ }
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
@@ -617,7 +656,8 @@
*
* @return true if verification should be performed
*/
- private boolean isVerificationEnabled(PackageInfoLite pkgInfoLite, int userId) {
+ private boolean isVerificationEnabled(PackageInfoLite pkgInfoLite, int userId,
+ String[] requiredVerifierPackages) {
if (!DEFAULT_VERIFY_ENABLE) {
return false;
}
@@ -634,18 +674,21 @@
// only when not installed from ADB, skip verification for instant apps when
// the installer and verifier are the same.
- if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
- if (mPm.mInstantAppInstallerActivity != null
- && mPm.mInstantAppInstallerActivity.packageName.equals(
- mPm.mRequiredVerifierPackage)) {
- try {
- mPm.mInjector.getSystemService(AppOpsManager.class)
- .checkPackage(installerUid, mPm.mRequiredVerifierPackage);
- if (DEBUG_VERIFY) {
- Slog.i(TAG, "disable verification for instant app");
+ if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0
+ && mPm.mInstantAppInstallerActivity != null) {
+ String installerPackage = mPm.mInstantAppInstallerActivity.packageName;
+ for (String requiredVerifierPackage : requiredVerifierPackages) {
+ if (installerPackage.equals(requiredVerifierPackage)) {
+ try {
+ mPm.mInjector.getSystemService(AppOpsManager.class)
+ .checkPackage(installerUid, requiredVerifierPackage);
+ if (DEBUG_VERIFY) {
+ Slog.i(TAG, "disable verification for instant app");
+ }
+ return false;
+ } catch (SecurityException ignore) {
}
- return false;
- } catch (SecurityException ignore) { }
+ }
}
}
return true;
diff --git a/services/core/java/com/android/server/pm/pkg/component/InstallConstraintsTagParser.java b/services/core/java/com/android/server/pm/pkg/component/InstallConstraintsTagParser.java
new file mode 100644
index 0000000..1497684
--- /dev/null
+++ b/services/core/java/com/android/server/pm/pkg/component/InstallConstraintsTagParser.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.pkg.component;
+
+
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Build;
+import android.util.ArraySet;
+
+import com.android.internal.R;
+import com.android.server.SystemConfig;
+import com.android.server.pm.pkg.parsing.ParsingPackage;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * Utility methods for handling the tag {@code <install-constraints/>}
+ *
+ * @hide
+ */
+public class InstallConstraintsTagParser {
+
+ private static final String TAG_FINGERPRINT_PREFIX = "fingerprint-prefix";
+
+ /**
+ * @hide
+ */
+ public static ParseResult<ParsingPackage> parseInstallConstraints(
+ ParseInput input, ParsingPackage pkg, Resources res, XmlResourceParser parser)
+ throws XmlPullParserException, IOException {
+ Set<String> allowlist = SystemConfig.getInstance().getInstallConstraintsAllowlist();
+ if (!allowlist.contains(pkg.getPackageName())) {
+ return input.skip("install-constraints cannot be used by this package");
+ }
+
+ ParseResult<Set<String>> prefixes = parseFingerprintPrefixes(input, res, parser);
+ if (prefixes.isSuccess()) {
+ if (validateFingerprintPrefixes(prefixes.getResult())) {
+ return input.success(pkg);
+ } else {
+ return input.skip(
+ "Install of this package is restricted on this device; device fingerprint"
+ + " does not start with one of the allowed prefixes");
+ }
+ }
+ return input.skip(prefixes.getErrorMessage());
+ }
+
+ private static ParseResult<Set<String>> parseFingerprintPrefixes(
+ ParseInput input, Resources res, XmlResourceParser parser)
+ throws XmlPullParserException, IOException {
+ Set<String> prefixes = new ArraySet<>();
+ int type;
+ while (true) {
+ // move to the tag that contains the next prefix
+ type = parser.next();
+ if (type == XmlPullParser.END_TAG) {
+ if (prefixes.size() == 0) {
+ return input.error("install-constraints must contain at least one constraint");
+ }
+ return input.success(prefixes);
+ } else if (type == XmlPullParser.START_TAG) {
+ if (parser.getName().equals(TAG_FINGERPRINT_PREFIX)) {
+ ParseResult<String> parsedPrefix =
+ readFingerprintPrefixValue(input, res, parser);
+ if (parsedPrefix.isSuccess()) {
+ prefixes.add(parsedPrefix.getResult());
+ } else {
+ return input.error(parsedPrefix.getErrorMessage());
+ }
+ } else {
+ return input.error("Unexpected tag: " + parser.getName());
+ }
+
+ // consume the end tag of this attribute
+ type = parser.next();
+ if (type != XmlPullParser.END_TAG) {
+ return input.error("Expected end tag; instead got " + type);
+ }
+ }
+ }
+ }
+
+ private static ParseResult<String> readFingerprintPrefixValue(ParseInput input, Resources res,
+ XmlResourceParser parser) {
+ TypedArray sa = res.obtainAttributes(parser,
+ R.styleable.AndroidManifestInstallConstraintsFingerprintPrefix);
+ try {
+ String value = sa.getString(
+ R.styleable.AndroidManifestInstallConstraintsFingerprintPrefix_value);
+ if (value == null) {
+ return input.error("Failed to specify prefix value");
+ }
+ return input.success(value);
+ } finally {
+ sa.recycle();
+ }
+ }
+
+ private static boolean validateFingerprintPrefixes(Set<String> prefixes) {
+ String fingerprint = Build.FINGERPRINT;
+ for (String prefix : prefixes) {
+ if (fingerprint.startsWith(prefix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/PackageInfoWithoutStateUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/PackageInfoWithoutStateUtils.java
index ee59810..8f953e7 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/PackageInfoWithoutStateUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/PackageInfoWithoutStateUtils.java
@@ -293,6 +293,10 @@
pi.requestedPermissionsFlags[i] |=
PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION;
}
+ if (pkg.getImplicitPermissions().contains(pi.requestedPermissions[i])) {
+ pi.requestedPermissionsFlags[i] |=
+ PackageInfo.REQUESTED_PERMISSION_IMPLICIT;
+ }
}
}
}
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index b60b9a0..5b8f473 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -94,6 +94,7 @@
import com.android.server.pm.permission.CompatibilityPermissionInfo;
import com.android.server.pm.pkg.component.ComponentMutateUtils;
import com.android.server.pm.pkg.component.ComponentParseUtils;
+import com.android.server.pm.pkg.component.InstallConstraintsTagParser;
import com.android.server.pm.pkg.component.ParsedActivity;
import com.android.server.pm.pkg.component.ParsedActivityUtils;
import com.android.server.pm.pkg.component.ParsedApexSystemService;
@@ -168,9 +169,11 @@
public static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
public static final String TAG_APPLICATION = "application";
+ public static final String TAG_ATTRIBUTION = "attribution";
public static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
public static final String TAG_EAT_COMMENT = "eat-comment";
public static final String TAG_FEATURE_GROUP = "feature-group";
+ public static final String TAG_INSTALL_CONSTRAINTS = "install-constraints";
public static final String TAG_INSTRUMENTATION = "instrumentation";
public static final String TAG_KEY_SETS = "key-sets";
public static final String TAG_MANIFEST = "manifest";
@@ -178,15 +181,16 @@
public static final String TAG_OVERLAY = "overlay";
public static final String TAG_PACKAGE = "package";
public static final String TAG_PACKAGE_VERIFIER = "package-verifier";
- public static final String TAG_ATTRIBUTION = "attribution";
public static final String TAG_PERMISSION = "permission";
public static final String TAG_PERMISSION_GROUP = "permission-group";
public static final String TAG_PERMISSION_TREE = "permission-tree";
+ public static final String TAG_PROFILEABLE = "profileable";
public static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
public static final String TAG_QUERIES = "queries";
+ public static final String TAG_RECEIVER = "receiver";
public static final String TAG_RESTRICT_UPDATE = "restrict-update";
- public static final String TAG_SUPPORT_SCREENS = "supports-screens";
public static final String TAG_SUPPORTS_INPUT = "supports-input";
+ public static final String TAG_SUPPORT_SCREENS = "supports-screens";
public static final String TAG_USES_CONFIGURATION = "uses-configuration";
public static final String TAG_USES_FEATURE = "uses-feature";
public static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
@@ -195,8 +199,6 @@
public static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
public static final String TAG_USES_SDK = "uses-sdk";
public static final String TAG_USES_SPLIT = "uses-split";
- public static final String TAG_PROFILEABLE = "profileable";
- public static final String TAG_RECEIVER = "receiver";
public static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
public static final String METADATA_SUPPORTS_SIZE_CHANGES = "android.supports_size_changes";
@@ -1026,6 +1028,8 @@
return input.success(pkg);
case TAG_RESTRICT_UPDATE:
return parseRestrictUpdateHash(flags, input, pkg, res, parser);
+ case TAG_INSTALL_CONSTRAINTS:
+ return parseInstallConstraints(input, pkg, res, parser);
case TAG_QUERIES:
return parseQueries(input, pkg, res, parser);
default:
@@ -1719,6 +1723,12 @@
return input.success(pkg);
}
+ private static ParseResult<ParsingPackage> parseInstallConstraints(
+ ParseInput input, ParsingPackage pkg, Resources res, XmlResourceParser parser)
+ throws IOException, XmlPullParserException {
+ return InstallConstraintsTagParser.parseInstallConstraints(input, pkg, res, parser);
+ }
+
private static ParseResult<ParsingPackage> parseQueries(ParseInput input, ParsingPackage pkg,
Resources res, XmlResourceParser parser) throws IOException, XmlPullParserException {
final int depth = parser.getDepth();
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index e062c38..abedd96 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -131,6 +131,7 @@
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.server.am.PendingIntentRecord;
import com.android.server.pm.InstantAppResolver;
import com.android.server.power.ShutdownCheckPoints;
@@ -2095,6 +2096,49 @@
}
}
+ // Log activity starts which violate one of the following rules of the
+ // activity security model (ASM):
+ // 1. Only the top activity on a task can start activities on that task
+ // 2. Only the top activity on the top task can create new (top) tasks
+ // We don't currently block, but these checks may later become blocks
+ // TODO(b/236234252): Shift to BackgroundActivityStartController once
+ // class is ready
+ if (mSourceRecord != null) {
+ int callerUid = mSourceRecord.getUid();
+ ActivityRecord targetTopActivity =
+ targetTask != null ? targetTask.getTopNonFinishingActivity() : null;
+ boolean passesAsmChecks = newTask
+ ? mRootWindowContainer.hasResumedActivity(callerUid)
+ : targetTopActivity != null && targetTopActivity.getUid() == callerUid;
+
+ if (!passesAsmChecks) {
+ Slog.i(TAG, "Launching r: " + r
+ + " from background: " + mSourceRecord
+ + ". New task: " + newTask);
+ boolean newOrEmptyTask = newTask || (targetTopActivity == null);
+ FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
+ /* caller_uid */
+ callerUid,
+ /* caller_activity_class_name */
+ mSourceRecord.info.name,
+ /* target_task_top_activity_uid */
+ newOrEmptyTask ? -1 : targetTopActivity.getUid(),
+ /* target_task_top_activity_class_name */
+ newOrEmptyTask ? null : targetTopActivity.info.name,
+ /* target_task_is_different */
+ newTask || !mSourceRecord.getTask().equals(targetTask),
+ /* target_activity_uid */
+ r.getUid(),
+ /* target_activity_class_name */
+ r.info.name,
+ /* target_intent_action */
+ r.intent.getAction(),
+ /* target_intent_flags */
+ r.intent.getFlags()
+ );
+ }
+ }
+
return START_SUCCESS;
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 345ec11..be995a8 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -886,11 +886,12 @@
logIfTransactionTooLarge(r.intent, r.getSavedState());
- if (r.isEmbedded()) {
+ final TaskFragment organizedTaskFragment = r.getOrganizedTaskFragment();
+ if (organizedTaskFragment != null) {
// Sending TaskFragmentInfo to client to ensure the info is updated before
// the activity creation.
mService.mTaskFragmentOrganizerController.dispatchPendingInfoChangedEvent(
- r.getOrganizedTaskFragment());
+ organizedTaskFragment);
}
// Create activity launch transaction.
@@ -1874,6 +1875,9 @@
// End power mode launch before going sleep
mService.endLaunchPowerMode(ActivityTaskManagerService.POWER_MODE_REASON_ALL);
+ // Rank task layers to make sure the {@link Task#mLayerRank} is updated.
+ mRootWindowContainer.rankTaskLayers();
+
removeSleepTimeouts();
if (mGoingToSleepWakeLock.isHeld()) {
diff --git a/services/core/java/com/android/server/wm/CompatModePackages.java b/services/core/java/com/android/server/wm/CompatModePackages.java
index 2ea043a..6f19450 100644
--- a/services/core/java/com/android/server/wm/CompatModePackages.java
+++ b/services/core/java/com/android/server/wm/CompatModePackages.java
@@ -24,6 +24,7 @@
import android.app.ActivityManager;
import android.app.AppGlobals;
+import android.app.GameManagerInternal;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
@@ -48,6 +49,7 @@
import android.util.Xml;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.server.LocalServices;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -64,6 +66,7 @@
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
private final ActivityTaskManagerService mService;
+ private GameManagerInternal mGameManager;
private final AtomicFile mFile;
// Compatibility state: no longer ask user to select the mode.
@@ -375,6 +378,18 @@
float getCompatScale(String packageName, int uid) {
final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+ if (mGameManager == null) {
+ mGameManager = LocalServices.getService(GameManagerInternal.class);
+ }
+ if (mGameManager != null) {
+ final int userId = userHandle.getIdentifier();
+ final float scalingFactor = mGameManager.getResolutionScalingFactor(packageName,
+ userId);
+ if (scalingFactor > 0) {
+ return 1f / scalingFactor;
+ }
+ }
+
if (CompatChanges.isChangeEnabled(DOWNSCALED, packageName, userHandle)) {
if (CompatChanges.isChangeEnabled(DOWNSCALE_90, packageName, userHandle)) {
return 1f / 0.9f;
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 3e2d7c9..7a9e6a9 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -398,16 +398,18 @@
if (WindowConfiguration.isFloating(windowingMode)
|| (windowingMode == WINDOWING_MODE_MULTI_WINDOW && isAlwaysOnTop)) {
- if (!stateCopied) {
- state = new InsetsState(state);
- stateCopied = true;
+ InsetsState newState = new InsetsState();
+
+ // Only caption and IME are needed.
+ if (state.peekSource(ITYPE_CAPTION_BAR) != null) {
+ newState.addSource(state.peekSource(ITYPE_CAPTION_BAR));
}
- state.removeSource(ITYPE_STATUS_BAR);
- state.removeSource(ITYPE_NAVIGATION_BAR);
- state.removeSource(ITYPE_EXTRA_NAVIGATION_BAR);
- if (windowingMode == WINDOWING_MODE_PINNED) {
- state.removeSource(ITYPE_IME);
+ if (windowingMode != WINDOWING_MODE_PINNED && state.peekSource(ITYPE_IME) != null) {
+ newState.addSource(state.peekSource(ITYPE_IME));
}
+
+ state = newState;
+ stateCopied = true;
}
return state;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 7d9dc21..552c6a5 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1820,6 +1820,10 @@
return getItemFromTaskDisplayAreas(TaskDisplayArea::getFocusedActivity);
}
+ boolean hasResumedActivity(int uid) {
+ return forAllActivities(ar -> ar.isState(RESUMED) && ar.getUid() == uid);
+ }
+
boolean isTopDisplayFocusedRootTask(Task task) {
return task != null && task == getTopDisplayFocusedRootTask();
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 74e1fe4..8de556a 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1109,6 +1109,9 @@
// as the one in the task because either one of them could be the alias activity.
if (Objects.equals(realActivity, r.mActivityComponent) && this.intent != null) {
intent.setComponent(this.intent.getComponent());
+ // Make sure the package name the same to prevent one of the intent is set while the
+ // other one is not.
+ intent.setPackage(this.intent.getPackage());
}
return intent.filterEquals(this.intent);
}
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 589618e..e6afdd6 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -586,7 +586,10 @@
}
// Cannot embed activity across TaskFragments for activity result.
- if (a.resultTo != null && a.resultTo.getTaskFragment() != this) {
+ // If the activity that started for result is finishing, it's likely that this start mode
+ // is used to place an activity in the same task. Since the finishing activity won't be
+ // able to get the results, so it's OK to embed in a different TaskFragment.
+ if (a.resultTo != null && !a.resultTo.finishing && a.resultTo.getTaskFragment() != this) {
return EMBEDDING_DISALLOWED_NEW_TASK_FRAGMENT;
}
diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
index a4d6f70..6ca5648 100644
--- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.window.TaskFragmentOrganizer.putErrorInfoInBundle;
import static android.window.TaskFragmentTransaction.TYPE_ACTIVITY_REPARENT_TO_TASK;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED;
@@ -28,6 +29,8 @@
import static com.android.server.wm.TaskFragment.EMBEDDING_ALLOWED;
import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -38,6 +41,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.view.RemoteAnimationDefinition;
@@ -51,6 +55,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
@@ -70,15 +75,12 @@
private final ArrayMap<IBinder, TaskFragmentOrganizerState> mTaskFragmentOrganizerState =
new ArrayMap<>();
/**
- * A List which manages the TaskFragment pending event {@link PendingTaskFragmentEvent}
+ * Map from {@link ITaskFragmentOrganizer} to a list of related {@link PendingTaskFragmentEvent}
*/
- private final ArrayList<PendingTaskFragmentEvent> mPendingTaskFragmentEvents =
- new ArrayList<>();
-
- /** Map from {@link ITaskFragmentOrganizer} to {@link TaskFragmentTransaction}. */
- private final ArrayMap<IBinder, TaskFragmentTransaction> mTmpOrganizerToTransactionMap =
+ private final ArrayMap<IBinder, List<PendingTaskFragmentEvent>> mPendingTaskFragmentEvents =
new ArrayMap<>();
- private final ArrayList<ITaskFragmentOrganizer> mTmpOrganizerList = new ArrayList<>();
+
+ private final ArraySet<Task> mTmpTaskSet = new ArraySet<>();
TaskFragmentOrganizerController(ActivityTaskManagerService atm) {
mAtmService = atm;
@@ -94,10 +96,30 @@
private final ITaskFragmentOrganizer mOrganizer;
private final int mOrganizerPid;
private final int mOrganizerUid;
+
+ /**
+ * Map from {@link TaskFragment} to the last {@link TaskFragmentInfo} sent to the
+ * organizer.
+ */
private final Map<TaskFragment, TaskFragmentInfo> mLastSentTaskFragmentInfos =
new WeakHashMap<>();
- private final Map<TaskFragment, Configuration> mLastSentTaskFragmentParentConfigs =
- new WeakHashMap<>();
+
+ /**
+ * Map from {@link TaskFragment} to its leaf {@link Task#mTaskId}. Embedded
+ * {@link TaskFragment} will not be reparented until it is removed.
+ */
+ private final Map<TaskFragment, Integer> mTaskFragmentTaskIds = new WeakHashMap<>();
+
+ /**
+ * Map from {@link Task#mTaskId} to the last Task {@link Configuration} sent to the
+ * organizer.
+ */
+ private final SparseArray<Configuration> mLastSentTaskFragmentParentConfigs =
+ new SparseArray<>();
+
+ /**
+ * Map from temporary activity token to the corresponding {@link ActivityRecord}.
+ */
private final Map<IBinder, ActivityRecord> mTemporaryActivityTokens =
new WeakHashMap<>();
@@ -161,21 +183,15 @@
TaskFragmentTransaction.Change prepareTaskFragmentAppeared(@NonNull TaskFragment tf) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment appeared name=%s", tf.getName());
final TaskFragmentInfo info = tf.getTaskFragmentInfo();
+ final int taskId = tf.getTask().mTaskId;
tf.mTaskFragmentAppearedSent = true;
mLastSentTaskFragmentInfos.put(tf, info);
- final TaskFragmentTransaction.Change change =
- new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_APPEARED)
- .setTaskFragmentToken(tf.getFragmentToken())
- .setTaskFragmentInfo(info);
- if (shouldSendTaskFragmentParentInfoChanged(tf)) {
- // TODO(b/240519866): convert to pass TaskConfiguration for all TFs in the same Task
- final Task task = tf.getTask();
- mLastSentTaskFragmentParentConfigs
- .put(tf, new Configuration(task.getConfiguration()));
- change.setTaskId(task.mTaskId)
- .setTaskConfiguration(task.getConfiguration());
- }
- return change;
+ mTaskFragmentTaskIds.put(tf, taskId);
+ return new TaskFragmentTransaction.Change(
+ TYPE_TASK_FRAGMENT_APPEARED)
+ .setTaskFragmentToken(tf.getFragmentToken())
+ .setTaskFragmentInfo(info)
+ .setTaskId(taskId);
}
@NonNull
@@ -183,10 +199,24 @@
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment vanished name=%s", tf.getName());
tf.mTaskFragmentAppearedSent = false;
mLastSentTaskFragmentInfos.remove(tf);
- mLastSentTaskFragmentParentConfigs.remove(tf);
+
+ // Cleanup TaskFragmentParentConfig if this is the last TaskFragment in the Task.
+ final int taskId;
+ if (mTaskFragmentTaskIds.containsKey(tf)) {
+ taskId = mTaskFragmentTaskIds.remove(tf);
+ if (!mTaskFragmentTaskIds.containsValue(taskId)) {
+ // No more TaskFragment in the Task.
+ mLastSentTaskFragmentParentConfigs.remove(taskId);
+ }
+ } else {
+ // This can happen if the appeared wasn't sent before remove.
+ taskId = INVALID_TASK_ID;
+ }
+
return new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_VANISHED)
.setTaskFragmentToken(tf.getFragmentToken())
- .setTaskFragmentInfo(tf.getTaskFragmentInfo());
+ .setTaskFragmentInfo(tf.getTaskFragmentInfo())
+ .setTaskId(taskId);
}
@Nullable
@@ -197,65 +227,39 @@
final TaskFragmentInfo lastInfo = mLastSentTaskFragmentInfos.get(tf);
if (info.equalsForTaskFragmentOrganizer(lastInfo) && configurationsAreEqualForOrganizer(
info.getConfiguration(), lastInfo.getConfiguration())) {
- // Parent config may have changed. The controller will check if there is any
- // important config change for the organizer.
- return prepareTaskFragmentParentInfoChanged(tf);
+ return null;
}
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment info changed name=%s",
tf.getName());
mLastSentTaskFragmentInfos.put(tf, info);
- final TaskFragmentTransaction.Change change =
- new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_INFO_CHANGED)
- .setTaskFragmentToken(tf.getFragmentToken())
- .setTaskFragmentInfo(info);
- if (shouldSendTaskFragmentParentInfoChanged(tf)) {
- // TODO(b/240519866): convert to pass TaskConfiguration for all TFs in the same Task
- // at once.
- // Parent config may have changed. The controller will check if there is any
- // important config change for the organizer.
- final Task task = tf.getTask();
- mLastSentTaskFragmentParentConfigs
- .put(tf, new Configuration(task.getConfiguration()));
- change.setTaskId(task.mTaskId)
- .setTaskConfiguration(task.getConfiguration());
- }
- return change;
+ return new TaskFragmentTransaction.Change(
+ TYPE_TASK_FRAGMENT_INFO_CHANGED)
+ .setTaskFragmentToken(tf.getFragmentToken())
+ .setTaskFragmentInfo(info)
+ .setTaskId(tf.getTask().mTaskId);
}
@Nullable
TaskFragmentTransaction.Change prepareTaskFragmentParentInfoChanged(
- @NonNull TaskFragment tf) {
- if (!shouldSendTaskFragmentParentInfoChanged(tf)) {
+ @NonNull Task task) {
+ final int taskId = task.mTaskId;
+ // Check if the parent info is different from the last reported parent info.
+ final Configuration taskConfig = task.getConfiguration();
+ final Configuration lastParentConfig = mLastSentTaskFragmentParentConfigs.get(taskId);
+ if (configurationsAreEqualForOrganizer(taskConfig, lastParentConfig)
+ && taskConfig.windowConfiguration.getWindowingMode()
+ == lastParentConfig.windowConfiguration.getWindowingMode()) {
return null;
}
- final Task parent = tf.getTask();
- final Configuration parentConfig = parent.getConfiguration();
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
"TaskFragment parent info changed name=%s parentTaskId=%d",
- tf.getName(), parent.mTaskId);
- mLastSentTaskFragmentParentConfigs.put(tf, new Configuration(parentConfig));
+ task.getName(), taskId);
+ mLastSentTaskFragmentParentConfigs.put(taskId, new Configuration(taskConfig));
return new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED)
- .setTaskFragmentToken(tf.getFragmentToken())
- .setTaskId(parent.mTaskId)
- .setTaskConfiguration(parent.getConfiguration());
- }
-
- /** Whether the system should report TaskFragment parent info changed to the organizer. */
- private boolean shouldSendTaskFragmentParentInfoChanged(@NonNull TaskFragment tf) {
- final Task parent = tf.getTask();
- if (parent == null) {
- // The TaskFragment is not attached.
- mLastSentTaskFragmentParentConfigs.remove(tf);
- return false;
- }
- // Check if the parent info is different from the last reported parent info.
- final Configuration parentConfig = parent.getConfiguration();
- final Configuration lastParentConfig = mLastSentTaskFragmentParentConfigs.get(tf);
- return !configurationsAreEqualForOrganizer(parentConfig, lastParentConfig)
- || parentConfig.windowConfiguration.getWindowingMode()
- != lastParentConfig.windowConfiguration.getWindowingMode();
+ .setTaskId(taskId)
+ .setTaskConfiguration(taskConfig);
}
@NonNull
@@ -345,6 +349,7 @@
}
mTaskFragmentOrganizerState.put(organizer.asBinder(),
new TaskFragmentOrganizerState(organizer, pid, uid));
+ mPendingTaskFragmentEvents.put(organizer.asBinder(), new ArrayList<>());
}
}
@@ -434,6 +439,11 @@
void onTaskFragmentAppeared(@NonNull ITaskFragmentOrganizer organizer,
@NonNull TaskFragment taskFragment) {
+ if (taskFragment.getTask() == null) {
+ Slog.w(TAG, "onTaskFragmentAppeared failed because it is not attached tf="
+ + taskFragment);
+ return;
+ }
final TaskFragmentOrganizerState state = validateAndGetState(organizer);
if (!state.addTaskFragment(taskFragment)) {
return;
@@ -441,28 +451,15 @@
PendingTaskFragmentEvent pendingEvent = getPendingTaskFragmentEvent(taskFragment,
PendingTaskFragmentEvent.EVENT_APPEARED);
if (pendingEvent == null) {
- pendingEvent = new PendingTaskFragmentEvent.Builder(
+ addPendingEvent(new PendingTaskFragmentEvent.Builder(
PendingTaskFragmentEvent.EVENT_APPEARED, organizer)
.setTaskFragment(taskFragment)
- .build();
- mPendingTaskFragmentEvents.add(pendingEvent);
+ .build());
}
}
void onTaskFragmentInfoChanged(@NonNull ITaskFragmentOrganizer organizer,
@NonNull TaskFragment taskFragment) {
- handleTaskFragmentInfoChanged(organizer, taskFragment,
- PendingTaskFragmentEvent.EVENT_INFO_CHANGED);
- }
-
- void onTaskFragmentParentInfoChanged(@NonNull ITaskFragmentOrganizer organizer,
- @NonNull TaskFragment taskFragment) {
- handleTaskFragmentInfoChanged(organizer, taskFragment,
- PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED);
- }
-
- private void handleTaskFragmentInfoChanged(@NonNull ITaskFragmentOrganizer organizer,
- @NonNull TaskFragment taskFragment, int eventType) {
validateAndGetState(organizer);
if (!taskFragment.mTaskFragmentAppearedSent) {
// Skip if TaskFragment still not appeared.
@@ -470,45 +467,41 @@
}
PendingTaskFragmentEvent pendingEvent = getLastPendingLifecycleEvent(taskFragment);
if (pendingEvent == null) {
- pendingEvent = new PendingTaskFragmentEvent.Builder(eventType, organizer)
- .setTaskFragment(taskFragment)
- .build();
+ pendingEvent = new PendingTaskFragmentEvent.Builder(
+ PendingTaskFragmentEvent.EVENT_INFO_CHANGED, organizer)
+ .setTaskFragment(taskFragment)
+ .build();
} else {
if (pendingEvent.mEventType == PendingTaskFragmentEvent.EVENT_VANISHED) {
// Skipped the info changed event if vanished event is pending.
return;
}
// Remove and add for re-ordering.
- mPendingTaskFragmentEvents.remove(pendingEvent);
+ removePendingEvent(pendingEvent);
// Reset the defer time when TaskFragment is changed, so that it can check again if
// the event should be sent to the organizer, for example the TaskFragment may become
// empty.
pendingEvent.mDeferTime = 0;
}
- mPendingTaskFragmentEvents.add(pendingEvent);
+ addPendingEvent(pendingEvent);
}
void onTaskFragmentVanished(@NonNull ITaskFragmentOrganizer organizer,
@NonNull TaskFragment taskFragment) {
final TaskFragmentOrganizerState state = validateAndGetState(organizer);
- for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
- PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i);
- if (taskFragment == entry.mTaskFragment) {
- mPendingTaskFragmentEvents.remove(i);
- if (entry.mEventType == PendingTaskFragmentEvent.EVENT_APPEARED) {
- // If taskFragment appeared callback is pending, ignore the vanished request.
- return;
- }
+ final List<PendingTaskFragmentEvent> pendingEvents = mPendingTaskFragmentEvents
+ .get(organizer.asBinder());
+ // Remove any pending events since this TaskFragment is being removed.
+ for (int i = pendingEvents.size() - 1; i >= 0; i--) {
+ final PendingTaskFragmentEvent event = pendingEvents.get(i);
+ if (taskFragment == event.mTaskFragment) {
+ pendingEvents.remove(i);
}
}
- if (!taskFragment.mTaskFragmentAppearedSent) {
- return;
- }
- final PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent.Builder(
+ addPendingEvent(new PendingTaskFragmentEvent.Builder(
PendingTaskFragmentEvent.EVENT_VANISHED, organizer)
.setTaskFragment(taskFragment)
- .build();
- mPendingTaskFragmentEvents.add(pendingEvent);
+ .build());
state.removeTaskFragment(taskFragment);
}
@@ -517,14 +510,13 @@
int opType, @NonNull Throwable exception) {
validateAndGetState(organizer);
Slog.w(TAG, "onTaskFragmentError ", exception);
- final PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent.Builder(
+ addPendingEvent(new PendingTaskFragmentEvent.Builder(
PendingTaskFragmentEvent.EVENT_ERROR, organizer)
.setErrorCallbackToken(errorCallbackToken)
.setTaskFragment(taskFragment)
.setException(exception)
.setOpType(opType)
- .build();
- mPendingTaskFragmentEvents.add(pendingEvent);
+ .build());
// Make sure the error event will be dispatched if there are no other changes.
mAtmService.mWindowManager.mWindowPlacerLocked.requestTraversal();
}
@@ -554,11 +546,18 @@
Slog.w(TAG, "The last TaskFragmentOrganizer no longer exists");
return;
}
- final PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent.Builder(
+ addPendingEvent(new PendingTaskFragmentEvent.Builder(
PendingTaskFragmentEvent.EVENT_ACTIVITY_REPARENT_TO_TASK, organizer)
.setActivity(activity)
- .build();
- mPendingTaskFragmentEvents.add(pendingEvent);
+ .build());
+ }
+
+ private void addPendingEvent(@NonNull PendingTaskFragmentEvent event) {
+ mPendingTaskFragmentEvents.get(event.mTaskFragmentOrg.asBinder()).add(event);
+ }
+
+ private void removePendingEvent(@NonNull PendingTaskFragmentEvent event) {
+ mPendingTaskFragmentEvents.get(event.mTaskFragmentOrg.asBinder()).remove(event);
}
boolean isOrganizerRegistered(@NonNull ITaskFragmentOrganizer organizer) {
@@ -570,12 +569,7 @@
// remove all of the children of the organized TaskFragment
state.dispose();
// Remove any pending event of this organizer.
- for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
- final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
- if (event.mTaskFragmentOrg.asBinder().equals(organizer.asBinder())) {
- mPendingTaskFragmentEvents.remove(i);
- }
- }
+ mPendingTaskFragmentEvents.remove(organizer.asBinder());
mTaskFragmentOrganizerState.remove(organizer.asBinder());
}
@@ -631,6 +625,8 @@
private final Throwable mException;
@Nullable
private final ActivityRecord mActivity;
+ @Nullable
+ private final Task mTask;
// Set when the event is deferred due to the host task is invisible. The defer time will
// be the last active time of the host task.
private long mDeferTime;
@@ -642,6 +638,7 @@
@Nullable IBinder errorCallbackToken,
@Nullable Throwable exception,
@Nullable ActivityRecord activity,
+ @Nullable Task task,
int opType) {
mEventType = eventType;
mTaskFragmentOrg = taskFragmentOrg;
@@ -649,6 +646,7 @@
mErrorCallbackToken = errorCallbackToken;
mException = exception;
mActivity = activity;
+ mTask = task;
mOpType = opType;
}
@@ -680,11 +678,13 @@
private Throwable mException;
@Nullable
private ActivityRecord mActivity;
+ @Nullable
+ private Task mTask;
private int mOpType;
- Builder(@EventType int eventType, ITaskFragmentOrganizer taskFragmentOrg) {
+ Builder(@EventType int eventType, @NonNull ITaskFragmentOrganizer taskFragmentOrg) {
mEventType = eventType;
- mTaskFragmentOrg = taskFragmentOrg;
+ mTaskFragmentOrg = requireNonNull(taskFragmentOrg);
}
Builder setTaskFragment(@Nullable TaskFragment taskFragment) {
@@ -697,13 +697,18 @@
return this;
}
- Builder setException(@Nullable Throwable exception) {
- mException = exception;
+ Builder setException(@NonNull Throwable exception) {
+ mException = requireNonNull(exception);
return this;
}
- Builder setActivity(@Nullable ActivityRecord activity) {
- mActivity = activity;
+ Builder setActivity(@NonNull ActivityRecord activity) {
+ mActivity = requireNonNull(activity);
+ return this;
+ }
+
+ Builder setTask(@NonNull Task task) {
+ mTask = requireNonNull(task);
return this;
}
@@ -714,17 +719,20 @@
PendingTaskFragmentEvent build() {
return new PendingTaskFragmentEvent(mEventType, mTaskFragmentOrg, mTaskFragment,
- mErrorCallbackToken, mException, mActivity, mOpType);
+ mErrorCallbackToken, mException, mActivity, mTask, mOpType);
}
}
}
@Nullable
private PendingTaskFragmentEvent getLastPendingLifecycleEvent(@NonNull TaskFragment tf) {
- for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
- PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i);
- if (tf == entry.mTaskFragment && entry.isLifecycleEvent()) {
- return entry;
+ final ITaskFragmentOrganizer organizer = tf.getTaskFragmentOrganizer();
+ final List<PendingTaskFragmentEvent> events = mPendingTaskFragmentEvents
+ .get(organizer.asBinder());
+ for (int i = events.size() - 1; i >= 0; i--) {
+ final PendingTaskFragmentEvent event = events.get(i);
+ if (tf == event.mTaskFragment && event.isLifecycleEvent()) {
+ return event;
}
}
return null;
@@ -733,10 +741,13 @@
@Nullable
private PendingTaskFragmentEvent getPendingTaskFragmentEvent(@NonNull TaskFragment taskFragment,
int type) {
- for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
- PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i);
- if (taskFragment == entry.mTaskFragment && type == entry.mEventType) {
- return entry;
+ final ITaskFragmentOrganizer organizer = taskFragment.getTaskFragmentOrganizer();
+ final List<PendingTaskFragmentEvent> events = mPendingTaskFragmentEvents
+ .get(organizer.asBinder());
+ for (int i = events.size() - 1; i >= 0; i--) {
+ final PendingTaskFragmentEvent event = events.get(i);
+ if (taskFragment == event.mTaskFragment && type == event.mEventType) {
+ return event;
}
}
return null;
@@ -762,12 +773,25 @@
|| mPendingTaskFragmentEvents.isEmpty()) {
return;
}
+ final int organizerNum = mPendingTaskFragmentEvents.size();
+ for (int i = 0; i < organizerNum; i++) {
+ final ITaskFragmentOrganizer organizer = mTaskFragmentOrganizerState.get(
+ mPendingTaskFragmentEvents.keyAt(i)).mOrganizer;
+ dispatchPendingEvents(organizer, mPendingTaskFragmentEvents.valueAt(i));
+ }
+ }
+
+ void dispatchPendingEvents(@NonNull ITaskFragmentOrganizer organizer,
+ @NonNull List<PendingTaskFragmentEvent> pendingEvents) {
+ if (pendingEvents.isEmpty()) {
+ return;
+ }
final ArrayList<Task> visibleTasks = new ArrayList<>();
final ArrayList<Task> invisibleTasks = new ArrayList<>();
final ArrayList<PendingTaskFragmentEvent> candidateEvents = new ArrayList<>();
- for (int i = 0, n = mPendingTaskFragmentEvents.size(); i < n; i++) {
- final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
+ for (int i = 0, n = pendingEvents.size(); i < n; i++) {
+ final PendingTaskFragmentEvent event = pendingEvents.get(i);
final Task task = event.mTaskFragment != null ? event.mTaskFragment.getTask() : null;
if (task != null && (task.lastActiveTime <= event.mDeferTime
|| !(isTaskVisible(task, visibleTasks, invisibleTasks)
@@ -783,27 +807,26 @@
return;
}
- mTmpOrganizerToTransactionMap.clear();
- mTmpOrganizerList.clear();
+ mTmpTaskSet.clear();
+ final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
for (int i = 0; i < numEvents; i++) {
final PendingTaskFragmentEvent event = candidateEvents.get(i);
- if (!mTmpOrganizerToTransactionMap.containsKey(event.mTaskFragmentOrg.asBinder())) {
- mTmpOrganizerToTransactionMap.put(event.mTaskFragmentOrg.asBinder(),
- new TaskFragmentTransaction());
- mTmpOrganizerList.add(event.mTaskFragmentOrg);
+ if (event.mEventType == PendingTaskFragmentEvent.EVENT_APPEARED
+ || event.mEventType == PendingTaskFragmentEvent.EVENT_INFO_CHANGED) {
+ final Task task = event.mTaskFragment.getTask();
+ if (mTmpTaskSet.add(task)) {
+ // Make sure the organizer know about the Task config.
+ transaction.addChange(prepareChange(new PendingTaskFragmentEvent.Builder(
+ PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED, organizer)
+ .setTask(task)
+ .build()));
+ }
}
- mTmpOrganizerToTransactionMap.get(event.mTaskFragmentOrg.asBinder())
- .addChange(prepareChange(event));
+ transaction.addChange(prepareChange(event));
}
- final int numOrganizers = mTmpOrganizerList.size();
- for (int i = 0; i < numOrganizers; i++) {
- final ITaskFragmentOrganizer organizer = mTmpOrganizerList.get(i);
- dispatchTransactionInfo(organizer,
- mTmpOrganizerToTransactionMap.get(organizer.asBinder()));
- }
- mPendingTaskFragmentEvents.removeAll(candidateEvents);
- mTmpOrganizerToTransactionMap.clear();
- mTmpOrganizerList.clear();
+ mTmpTaskSet.clear();
+ dispatchTransactionInfo(organizer, transaction);
+ pendingEvents.removeAll(candidateEvents);
}
private static boolean isTaskVisible(@NonNull Task task,
@@ -831,10 +854,16 @@
return;
}
+ final ITaskFragmentOrganizer organizer = taskFragment.getTaskFragmentOrganizer();
final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
+ // Make sure the organizer know about the Task config.
+ transaction.addChange(prepareChange(new PendingTaskFragmentEvent.Builder(
+ PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED, organizer)
+ .setTask(taskFragment.getTask())
+ .build()));
transaction.addChange(prepareChange(event));
dispatchTransactionInfo(event.mTaskFragmentOrg, transaction);
- mPendingTaskFragmentEvents.remove(event);
+ mPendingTaskFragmentEvents.get(organizer.asBinder()).remove(event);
}
private void dispatchTransactionInfo(@NonNull ITaskFragmentOrganizer organizer,
@@ -867,7 +896,7 @@
case PendingTaskFragmentEvent.EVENT_INFO_CHANGED:
return state.prepareTaskFragmentInfoChanged(taskFragment);
case PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED:
- return state.prepareTaskFragmentParentInfoChanged(taskFragment);
+ return state.prepareTaskFragmentParentInfoChanged(event.mTask);
case PendingTaskFragmentEvent.EVENT_ERROR:
return state.prepareTaskFragmentError(event.mErrorCallbackToken, taskFragment,
event.mOpType, event.mException);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index adb8bf6..70dd9f3 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -3389,6 +3389,13 @@
pw.println(prefix + "mLastOrientationSource=" + mLastOrientationSource);
pw.println(prefix + "deepestLastOrientationSource=" + getLastOrientationSource());
}
+ if (mLocalInsetsSourceProviders != null && mLocalInsetsSourceProviders.size() != 0) {
+ pw.println(prefix + mLocalInsetsSourceProviders.size() + " LocalInsetsSourceProviders");
+ final String childPrefix = prefix + " ";
+ for (int i = 0; i < mLocalInsetsSourceProviders.size(); ++i) {
+ mLocalInsetsSourceProviders.valueAt(i).dump(pw, childPrefix);
+ }
+ }
}
final void updateSurfacePositionNonOrganized() {
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index af5718f..1d56078 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -29,8 +29,10 @@
#include <dirent.h>
#include <jni.h>
#include <linux/errno.h>
+#include <linux/time.h>
#include <log/log.h>
#include <meminfo/procmeminfo.h>
+#include <meminfo/sysmeminfo.h>
#include <nativehelper/JNIHelp.h>
#include <processgroup/processgroup.h>
#include <stddef.h>
@@ -42,6 +44,7 @@
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>
+#include <utils/Timers.h>
#include <utils/Trace.h>
#include <algorithm>
@@ -457,6 +460,12 @@
ATRACE_INSTANT_FOR_TRACK(ATRACE_COMPACTION_TRACK, "Cancel compaction");
}
+static jlong com_android_server_am_CachedAppOptimizer_threadCpuTimeNs(JNIEnv*, jobject) {
+ int64_t currentCpuTime = systemTime(CLOCK_THREAD_CPUTIME_ID);
+
+ return currentCpuTime;
+}
+
static jdouble com_android_server_am_CachedAppOptimizer_getFreeSwapPercent(JNIEnv*, jobject) {
struct sysinfo memoryInfo;
int error = sysinfo(&memoryInfo);
@@ -467,6 +476,16 @@
return (double)memoryInfo.freeswap / (double)memoryInfo.totalswap;
}
+static jlong com_android_server_am_CachedAppOptimizer_getUsedZramMemory() {
+ android::meminfo::SysMemInfo sysmeminfo;
+ return sysmeminfo.mem_zram_kb();
+}
+
+static jlong com_android_server_am_CachedAppOptimizer_getMemoryFreedCompaction() {
+ android::meminfo::SysMemInfo sysmeminfo;
+ return sysmeminfo.mem_compacted_kb("/sys/block/zram0/");
+}
+
static void com_android_server_am_CachedAppOptimizer_compactProcess(JNIEnv*, jobject, jint pid,
jint compactionFlags) {
compactProcessOrFallback(pid, compactionFlags);
@@ -520,8 +539,13 @@
/* name, signature, funcPtr */
{"cancelCompaction", "()V",
(void*)com_android_server_am_CachedAppOptimizer_cancelCompaction},
+ {"threadCpuTimeNs", "()J", (void*)com_android_server_am_CachedAppOptimizer_threadCpuTimeNs},
{"getFreeSwapPercent", "()D",
(void*)com_android_server_am_CachedAppOptimizer_getFreeSwapPercent},
+ {"getUsedZramMemory", "()J",
+ (void*)com_android_server_am_CachedAppOptimizer_getUsedZramMemory},
+ {"getMemoryFreedCompaction", "()J",
+ (void*)com_android_server_am_CachedAppOptimizer_getMemoryFreedCompaction},
{"compactSystem", "()V", (void*)com_android_server_am_CachedAppOptimizer_compactSystem},
{"compactProcess", "(II)V", (void*)com_android_server_am_CachedAppOptimizer_compactProcess},
{"freezeBinder", "(IZ)I", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder},
diff --git a/services/proguard.flags b/services/proguard.flags
index c648f7d..c930346 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -64,6 +64,12 @@
# Referenced via CarServiceHelperService in car-frameworks-service (avoid removing)
-keep public class com.android.server.utils.Slogf { *; }
+# Referenced in wear-service
+# HIDL interfaces
+-keep public class android.hidl.base.** { *; }
+-keep public class android.hidl.manager.** { *; }
+-keep public class com.android.server.wm.WindowManagerInternal { *; }
+
# Notification extractors
# TODO(b/210510433): Revisit and consider generating from frameworks/base/core/res/res/values/config.xml.
-keep,allowoptimization,allowaccessmodification public class com.android.server.notification.** implements com.android.server.notification.NotificationSignalExtractor
diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt
index 45e0d09..4ef6875 100644
--- a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt
+++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SystemStubMultiUserDisableUninstallTest.kt
@@ -628,6 +628,7 @@
CodePath.SAME, CodePath.DIFFERENT ->
throw AssertionError("secondDataPath cannot be a data path")
CodePath.SYSTEM -> assertThat(codePaths[1]).isEqualTo(stubFile.parent.toString())
+ else -> {}
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index 2baa1ec..05cad16 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -17,12 +17,9 @@
package com.android.server.am;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
-
import static com.android.server.am.ActivityManagerService.Injector;
-import static com.android.server.am.CachedAppOptimizer.compactActionIntToString;
-
+import static com.android.server.am.CachedAppOptimizer.compactActionIntToAction;
import static com.google.common.truth.Truth.assertThat;
-
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -37,15 +34,18 @@
import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig;
import android.text.TextUtils;
-
import androidx.test.platform.app.InstrumentationRegistry;
-
import com.android.modules.utils.testing.TestableDeviceConfig;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.appop.AppOpsService;
import com.android.server.wm.ActivityTaskManagerService;
-
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
@@ -55,13 +55,6 @@
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
/**
* Tests for {@link CachedAppOptimizer}.
*
@@ -147,36 +140,40 @@
@Test
public void init_setsDefaults() {
mCachedAppOptimizerUnderTest.init();
- assertThat(mCachedAppOptimizerUnderTest.useCompaction()).isEqualTo(
- CachedAppOptimizer.DEFAULT_USE_COMPACTION);
- assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome).isEqualTo(
- compactActionIntToString(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1));
- assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull).isEqualTo(
- compactActionIntToString(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2));
- assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeSome).isEqualTo(
- CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_1);
- assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeFull).isEqualTo(
- CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_2);
- assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleFullSome).isEqualTo(
- CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_3);
- assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleFullFull).isEqualTo(
- CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_4);
- assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
- CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
- assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo(
- CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
- assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleBFGS).isEqualTo(
- CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5);
- assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo(
- CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6);
- assertThat(mCachedAppOptimizerUnderTest.mFullAnonRssThrottleKb).isEqualTo(
- CachedAppOptimizer.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
- assertThat(mCachedAppOptimizerUnderTest.mFullDeltaRssThrottleKb).isEqualTo(
- CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB);
- assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMinOomAdj).isEqualTo(
- CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ);
- assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMaxOomAdj).isEqualTo(
- CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ);
+ synchronized (mCachedAppOptimizerUnderTest.mPhenotypeFlagLock) {
+ assertThat(mCachedAppOptimizerUnderTest.useCompaction()).isEqualTo(
+ CachedAppOptimizer.DEFAULT_USE_COMPACTION);
+ assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome)
+ .isEqualTo(
+ compactActionIntToAction(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1));
+ assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull)
+ .isEqualTo(
+ compactActionIntToAction(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2));
+ assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeSome).isEqualTo(
+ CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_1);
+ assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeFull).isEqualTo(
+ CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_2);
+ assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleFullSome).isEqualTo(
+ CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_3);
+ assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleFullFull).isEqualTo(
+ CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_4);
+ assertThat(mCachedAppOptimizerUnderTest.mCompactStatsdSampleRate).isEqualTo(
+ CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
+ assertThat(mCachedAppOptimizerUnderTest.mFreezerStatsdSampleRate).isEqualTo(
+ CachedAppOptimizer.DEFAULT_STATSD_SAMPLE_RATE);
+ assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleBFGS).isEqualTo(
+ CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_5);
+ assertThat(mCachedAppOptimizerUnderTest.mCompactThrottlePersistent).isEqualTo(
+ CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_6);
+ assertThat(mCachedAppOptimizerUnderTest.mFullAnonRssThrottleKb).isEqualTo(
+ CachedAppOptimizer.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
+ assertThat(mCachedAppOptimizerUnderTest.mFullDeltaRssThrottleKb).isEqualTo(
+ CachedAppOptimizer.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB);
+ assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMinOomAdj).isEqualTo(
+ CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MIN_OOM_ADJ);
+ assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleMaxOomAdj).isEqualTo(
+ CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_MAX_OOM_ADJ);
+ }
Set<Integer> expected = new HashSet<>();
@@ -192,6 +189,7 @@
CachedAppOptimizer.DEFAULT_USE_FREEZER);
}
+ @SuppressWarnings("GuardedBy")
@Test
public void init_withDeviceConfigSetsParameters() {
// When the DeviceConfig already has a flag value stored (note this test will need to
@@ -256,11 +254,11 @@
assertThat(mCachedAppOptimizerUnderTest.useCompaction()).isTrue();
assertThat(mCachedAppOptimizerUnderTest.mCachedAppOptimizerThread.isAlive()).isTrue();
- assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome).isEqualTo(
- compactActionIntToString(
+ assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome)
+ .isEqualTo(compactActionIntToAction(
(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1 + 1 % 4) + 1));
- assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull).isEqualTo(
- compactActionIntToString(
+ assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull)
+ .isEqualTo(compactActionIntToAction(
(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2 + 1 % 4) + 1));
assertThat(mCachedAppOptimizerUnderTest.mCompactThrottleSomeSome).isEqualTo(
CachedAppOptimizer.DEFAULT_COMPACT_THROTTLE_1 + 1);
@@ -412,10 +410,12 @@
assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
// Then the updates are reflected in the flags.
- assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome).isEqualTo(
- compactActionIntToString(expectedSome));
- assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull).isEqualTo(
- compactActionIntToString(expectedFull));
+ synchronized (mCachedAppOptimizerUnderTest.mPhenotypeFlagLock) {
+ assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome)
+ .isEqualTo(compactActionIntToAction(expectedSome));
+ assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull)
+ .isEqualTo(compactActionIntToAction(expectedFull));
+ }
}
}
@@ -431,11 +431,15 @@
CachedAppOptimizer.KEY_COMPACT_ACTION_2, "foo", false);
assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
- // Then the default values are reflected in the flag
- assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome).isEqualTo(
- compactActionIntToString(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1));
- assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull).isEqualTo(
- compactActionIntToString(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2));
+ synchronized (mCachedAppOptimizerUnderTest.mPhenotypeFlagLock) {
+ // Then the default values are reflected in the flag
+ assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome)
+ .isEqualTo(
+ compactActionIntToAction(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1));
+ assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull)
+ .isEqualTo(
+ compactActionIntToAction(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2));
+ }
mCountDown = new CountDownLatch(2);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -444,10 +448,14 @@
CachedAppOptimizer.KEY_COMPACT_ACTION_2, "", false);
assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
- assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome).isEqualTo(
- compactActionIntToString(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1));
- assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull).isEqualTo(
- compactActionIntToString(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2));
+ synchronized (mCachedAppOptimizerUnderTest.mPhenotypeFlagLock) {
+ assertThat(mCachedAppOptimizerUnderTest.mCompactActionSome)
+ .isEqualTo(
+ compactActionIntToAction(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_1));
+ assertThat(mCachedAppOptimizerUnderTest.mCompactActionFull)
+ .isEqualTo(
+ compactActionIntToAction(CachedAppOptimizer.DEFAULT_COMPACT_ACTION_2));
+ }
}
@Test
@@ -893,7 +901,9 @@
mProcessDependencies.setRss(rssBefore1);
mProcessDependencies.setRssAfterCompaction(rssAfter1); //
// WHEN we try to run compaction
- mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+ mCachedAppOptimizerUnderTest.compactApp(processRecord,
+ CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+ false);
waitForHandler();
// THEN process IS compacted.
assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
@@ -908,7 +918,9 @@
processRecord.mOptRecord.setLastCompactTime(
processRecord.mOptRecord.getLastCompactTime() - 10_000);
// WHEN we try to run compaction.
- mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+ mCachedAppOptimizerUnderTest.compactApp(processRecord,
+ CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+ false);
waitForHandler();
// THEN process IS NOT compacted - values after compaction for process 1 should remain the
// same as from the last compaction.
@@ -924,7 +936,9 @@
processRecord.mOptRecord.setLastCompactTime(
processRecord.mOptRecord.getLastCompactTime() - 10_000);
// WHEN we try to run compaction
- mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+ mCachedAppOptimizerUnderTest.compactApp(processRecord,
+ CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+ false);
waitForHandler();
// THEN process IS compacted - values after compaction for process 1 should be updated.
assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
@@ -965,7 +979,9 @@
mProcessDependencies.setRss(rssBelowThreshold);
mProcessDependencies.setRssAfterCompaction(rssBelowThresholdAfter);
// WHEN we try to run compaction
- mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+ mCachedAppOptimizerUnderTest.compactApp(processRecord,
+ CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+ false);
waitForHandler();
// THEN process IS NOT compacted.
assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNull();
@@ -974,7 +990,9 @@
mProcessDependencies.setRss(rssAboveThreshold);
mProcessDependencies.setRssAfterCompaction(rssAboveThresholdAfter);
// WHEN we try to run compaction
- mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+ mCachedAppOptimizerUnderTest.compactApp(processRecord,
+ CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+ false);
waitForHandler();
// THEN process IS compacted.
assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
@@ -1008,22 +1026,16 @@
mProcessDependencies.setRss(rssBefore);
mProcessDependencies.setRssAfterCompaction(rssAfter);
- // Compaction should occur if (setAdj < min for process || setAdj > max for process) &&
- // (MIN < curAdj < MAX)
- // GIVEN OomAdj score below threshold.
- processRecord.mState.setSetAdj(899);
- processRecord.mState.setCurAdj(970);
- // WHEN we try to run compaction
- mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+ // When moving within cached state
+ mCachedAppOptimizerUnderTest.onOomAdjustChanged(
+ ProcessList.CACHED_APP_MIN_ADJ, ProcessList.CACHED_APP_MIN_ADJ + 1, processRecord);
waitForHandler();
// THEN process IS NOT compacted.
assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNull();
- // GIVEN (setAdj < MIN || setAdj > MAX) && (MIN < curAdj < MAX)
- processRecord.mState.setSetAdj(910);
- processRecord.mState.setCurAdj(930);
- // WHEN we try to run compaction
- mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+ // When moving into cached state
+ mCachedAppOptimizerUnderTest.onOomAdjustChanged(ProcessList.CACHED_APP_MIN_ADJ - 1,
+ ProcessList.CACHED_APP_MIN_ADJ + 1, processRecord);
waitForHandler();
// THEN process IS compacted.
assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
@@ -1057,13 +1069,17 @@
processRecord.mState.setCurAdj(100);
// Compact process full
- mCachedAppOptimizerUnderTest.compactAppFull(processRecord, false);
+ mCachedAppOptimizerUnderTest.compactApp(processRecord,
+ CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+ false);
waitForHandler();
// the process is not compacted
assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNull();
// Compact process some
- mCachedAppOptimizerUnderTest.compactAppSome(processRecord, false);
+ mCachedAppOptimizerUnderTest.compactApp(processRecord,
+ CachedAppOptimizer.CompactProfile.SOME, CachedAppOptimizer.CompactSource.APP,
+ false);
waitForHandler();
// the process is not compacted
assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNull();
@@ -1072,7 +1088,9 @@
processRecord.mState.setCurAdj(100);
// We force a full compaction
- mCachedAppOptimizerUnderTest.compactAppFull(processRecord, true);
+ mCachedAppOptimizerUnderTest.compactApp(processRecord,
+ CachedAppOptimizer.CompactProfile.FULL, CachedAppOptimizer.CompactSource.APP,
+ true);
waitForHandler();
// then process is compacted.
assertThat(mCachedAppOptimizerUnderTest.mLastCompactionStats.get(pid)).isNotNull();
@@ -1080,13 +1098,13 @@
mCachedAppOptimizerUnderTest.mLastCompactionStats.clear();
// We force a some compaction
- mCachedAppOptimizerUnderTest.compactAppSome(processRecord, true);
+ mCachedAppOptimizerUnderTest.compactApp(processRecord,
+ CachedAppOptimizer.CompactProfile.SOME, CachedAppOptimizer.CompactSource.APP, true);
waitForHandler();
// then process is compacted.
- String executedCompactAction =
- compactActionIntToString(processRecord.mOptRecord.getLastCompactAction());
- assertThat(executedCompactAction)
- .isEqualTo(mCachedAppOptimizerUnderTest.mCompactActionSome);
+ CachedAppOptimizer.CompactProfile executedCompactProfile =
+ processRecord.mOptRecord.getLastCompactProfile();
+ assertThat(executedCompactProfile).isEqualTo(CachedAppOptimizer.CompactProfile.SOME);
}
private void setFlag(String key, String value, boolean defaultValue) throws Exception {
@@ -1162,7 +1180,8 @@
}
@Override
- public void performCompaction(String action, int pid) throws IOException {
+ public void performCompaction(CachedAppOptimizer.CompactAction action, int pid)
+ throws IOException {
mRss = mRssAfterCompaction;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 8d59dce..598c6b0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -40,6 +40,7 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static com.android.server.am.OomAdjuster.OOM_ADJ_REASON_ACTIVITY;
import static com.android.server.am.ProcessList.BACKUP_APP_ADJ;
import static com.android.server.am.ProcessList.CACHED_APP_MAX_ADJ;
import static com.android.server.am.ProcessList.CACHED_APP_MIN_ADJ;
@@ -146,6 +147,7 @@
private static PackageManagerInternal sPackageManagerInternal;
private static ActivityManagerService sService;
+ @SuppressWarnings("GuardedBy")
@BeforeClass
public static void setUpOnce() {
sContext = getInstrumentation().getTargetContext();
@@ -196,7 +198,7 @@
new ActivityManagerService.Injector(sContext));
doReturn(mock(AppOpsManager.class)).when(sService).getAppOpsManager();
doCallRealMethod().when(sService).enqueueOomAdjTargetLocked(any(ProcessRecord.class));
- doCallRealMethod().when(sService).updateOomAdjPendingTargetsLocked(any(String.class));
+ doCallRealMethod().when(sService).updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_ACTIVITY);
setFieldValue(AppProfiler.class, profiler, "mProfilerLock", new Object());
doReturn(new ActivityManagerService.ProcessChangeItem()).when(pr)
.enqueueProcessChangeItemLocked(anyInt(), anyInt());
diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
index d675b0a..b53a2c6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
@@ -201,7 +201,6 @@
public void tearDown() throws Exception {
LocalServices.removeServiceForTest(PowerManagerInternal.class);
GameManagerService gameManagerService = new GameManagerService(mMockContext);
- gameManagerService.disableCompatScale(mPackageName);
if (mMockingSession != null) {
mMockingSession.finishMocking();
}
@@ -450,13 +449,13 @@
startUser(gameManagerService, USER_ID_1);
- gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
mockModifyGameModeGranted();
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
gameManagerService.getGameMode(mPackageName, USER_ID_1));
// We need to make sure the mode is supported before setting it.
mockDeviceConfigAll();
- gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_STANDARD, USER_ID_1);
assertEquals(GameManager.GAME_MODE_STANDARD,
gameManagerService.getGameMode(mPackageName, USER_ID_1));
@@ -534,8 +533,8 @@
startUser(gameManagerService, USER_ID_1);
startUser(gameManagerService, USER_ID_2);
- gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
- gameManagerService.updateConfigsForUser(USER_ID_2, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_2, true, mPackageName);
// Set User 1 to Standard
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_STANDARD, USER_ID_1);
@@ -563,7 +562,7 @@
if (gameManagerService == null) {
gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper());
startUser(gameManagerService, USER_ID_1);
- gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
}
ArraySet<Integer> reportedModes = new ArraySet<>();
int[] modes = gameManagerService.getAvailableGameModes(mPackageName);
@@ -578,20 +577,20 @@
}
private void checkDownscaling(GameManagerService gameManagerService,
- int gameMode, String scaling) {
+ int gameMode, float scaling) {
if (gameManagerService == null) {
gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper());
startUser(gameManagerService, USER_ID_1);
- gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
}
GameManagerService.GamePackageConfiguration config =
gameManagerService.getConfig(mPackageName);
- assertEquals(config.getGameModeConfiguration(gameMode).getScaling(), scaling);
+ assertEquals(scaling, config.getGameModeConfiguration(gameMode).getScaling(), 0.01f);
}
private void checkAngleEnabled(GameManagerService gameManagerService, int gameMode,
boolean angleEnabled) {
- gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
// Validate GamePackageConfiguration returns the correct value.
GameManagerService.GamePackageConfiguration config =
@@ -604,7 +603,7 @@
private void checkLoadingBoost(GameManagerService gameManagerService, int gameMode,
int loadingBoost) {
- gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
// Validate GamePackageConfiguration returns the correct value.
GameManagerService.GamePackageConfiguration config =
@@ -621,7 +620,7 @@
if (gameManagerService == null) {
gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper());
startUser(gameManagerService, USER_ID_1);
- gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
}
GameManagerService.GamePackageConfiguration config =
gameManagerService.getConfig(mPackageName);
@@ -715,7 +714,7 @@
checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.3");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.3f);
checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 120);
}
@@ -735,7 +734,7 @@
checkReportedModes(gameManagerService, GameManager.GAME_MODE_BATTERY,
GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.5");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.5f);
checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 60);
}
@@ -757,9 +756,9 @@
checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.3");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.3f);
checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 120);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.5");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.5f);
checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 60);
}
@@ -782,7 +781,7 @@
checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.5");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
}
@@ -805,7 +804,7 @@
checkReportedModes(gameManagerService, GameManager.GAME_MODE_BATTERY,
GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.7");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.7f);
checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 30);
}
@@ -829,9 +828,9 @@
checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.5");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.7");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.7f);
checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 30);
}
@@ -858,9 +857,9 @@
checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.3");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.3f);
checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 120);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.7");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.7f);
checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 30);
}
@@ -933,7 +932,7 @@
public void testInterventionAllowScalingDefault() throws Exception {
mockDeviceConfigPerformance();
mockModifyGameModeGranted();
- checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, "0.5");
+ checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
}
/**
@@ -944,7 +943,7 @@
mockDeviceConfigPerformance();
mockInterventionAllowDownscaleFalse();
mockModifyGameModeGranted();
- checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, "1.0");
+ checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, -1.0f);
}
/**
@@ -956,7 +955,7 @@
mockDeviceConfigPerformance();
mockInterventionAllowDownscaleTrue();
mockModifyGameModeGranted();
- checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, "0.5");
+ checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
}
/**
@@ -1091,7 +1090,7 @@
GameManagerService gameManagerService =
new GameManagerService(mMockContext, mTestLooper.getLooper());
startUser(gameManagerService, USER_ID_1);
- gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
GameManagerService.GamePackageConfiguration config =
gameManagerService.getConfig(mPackageName);
assertNull(config.getGameModeConfiguration(GameManager.GAME_MODE_PERFORMANCE));
@@ -1109,7 +1108,7 @@
new GameManagerService(mMockContext, mTestLooper.getLooper());
startUser(gameManagerService, USER_ID_1);
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1);
- gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
gameManagerService.getGameMode(mPackageName, USER_ID_1));
}
@@ -1126,7 +1125,7 @@
new GameManagerService(mMockContext, mTestLooper.getLooper());
startUser(gameManagerService, USER_ID_1);
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_BATTERY, USER_ID_1);
- gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
assertEquals(GameManager.GAME_MODE_STANDARD,
gameManagerService.getGameMode(mPackageName, USER_ID_1));
}
@@ -1143,7 +1142,7 @@
new GameManagerService(mMockContext, mTestLooper.getLooper());
startUser(gameManagerService, USER_ID_1);
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_UNSUPPORTED, USER_ID_1);
- gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
+ gameManagerService.updateConfigsForUser(USER_ID_1, true, mPackageName);
assertEquals(GameManager.GAME_MODE_STANDARD,
gameManagerService.getGameMode(mPackageName, USER_ID_1));
}
@@ -1404,4 +1403,102 @@
assertEquals(splitLine[6], "angle=0,scaling=0.7,fps=30");
}
+
+ @Test
+ public void testUpdateResolutionScalingFactor() {
+ mockModifyGameModeGranted();
+ mockDeviceConfigBattery();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ startUser(gameManagerService, USER_ID_1);
+ float scalingFactor = 0.123f;
+ gameManagerService.updateResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, scalingFactor,
+ USER_ID_1);
+ assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+ scalingFactor = 0.321f;
+ gameManagerService.updateResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, scalingFactor,
+ USER_ID_1);
+ assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+ }
+
+ @Test
+ public void testUpdateResolutionScalingFactor_noDeviceConfig() {
+ mockModifyGameModeGranted();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ startUser(gameManagerService, USER_ID_1);
+ float scalingFactor = 0.123f;
+ gameManagerService.updateResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, scalingFactor,
+ USER_ID_1);
+ assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+ scalingFactor = 0.321f;
+ gameManagerService.updateResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, scalingFactor,
+ USER_ID_1);
+ assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY,
+ USER_ID_1), 0.001f);
+ }
+
+ @Test
+ public void testUpdateResolutionScalingFactor_permissionDenied() {
+ mockModifyGameModeDenied();
+ mockDeviceConfigAll();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ startUser(gameManagerService, USER_ID_1);
+ float scalingFactor = 0.123f;
+ assertThrows(SecurityException.class, () -> {
+ gameManagerService.updateResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, scalingFactor,
+ USER_ID_1);
+ });
+ mockModifyGameModeGranted();
+ assertEquals(0.7f, gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+ }
+
+ @Test
+ public void testUpdateResolutionScalingFactor_noUserId() {
+ mockModifyGameModeGranted();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ startUser(gameManagerService, USER_ID_2);
+ final float scalingFactor = 0.123f;
+ assertThrows(IllegalArgumentException.class, () -> {
+ gameManagerService.updateResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, scalingFactor,
+ USER_ID_1);
+ });
+ }
+
+ @Test
+ public void testGetResolutionScalingFactor_permissionDenied() {
+ mockModifyGameModeDenied();
+ mockDeviceConfigAll();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ startUser(gameManagerService, USER_ID_1);
+ assertThrows(SecurityException.class, () -> {
+ gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, USER_ID_1);
+ });
+ }
+
+ @Test
+ public void testGetResolutionScalingFactor_noUserId() {
+ mockModifyGameModeDenied();
+ mockDeviceConfigAll();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ startUser(gameManagerService, USER_ID_2);
+ assertEquals(-1f, gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
index 99693d2..7111047 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
@@ -35,6 +35,7 @@
import android.os.HandlerThread;
import android.util.Log;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.util.TypedXmlPullParser;
import android.util.Xml;
@@ -97,9 +98,10 @@
final int defaultModeOp2 = AppOpsManager.opToDefaultMode(op2);
for(int i = 0; i < uidStates.size(); i++) {
final AppOpsService.UidState uidState = uidStates.valueAt(i);
- if (uidState.opModes != null) {
- final int uidMode1 = uidState.opModes.get(op1, defaultModeOp1);
- final int uidMode2 = uidState.opModes.get(op2, defaultModeOp2);
+ SparseIntArray opModes = uidState.getNonDefaultUidModes();
+ if (opModes != null) {
+ final int uidMode1 = opModes.get(op1, defaultModeOp1);
+ final int uidMode2 = opModes.get(op2, defaultModeOp2);
assertEquals(uidMode1, uidMode2);
if (uidMode1 != defaultModeOp1) {
numberOfNonDefaultOps++;
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/InitAppsHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/InitAppsHelperTest.kt
new file mode 100644
index 0000000..2165301
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/InitAppsHelperTest.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm
+
+import android.os.Build
+import android.os.SystemProperties
+import com.android.server.extendedtestutils.wheneverStatic
+import com.android.server.testutils.spy
+import com.android.server.testutils.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class InitAppsHelperTest {
+ @Rule
+ @JvmField
+ val rule = MockSystemRule()
+
+ @Before
+ fun setUp() {
+ rule.system().stageNominalSystemState()
+ }
+
+ private fun mockNoFirstBoot() {
+ // To mock that this is not the first boot
+ rule.system().stageScanExistingPackage("a.data.package", 1L,
+ rule.system().dataAppDirectory)
+ }
+
+ private fun mockFingerprintChanged() {
+ val versionInfo = Settings.VersionInfo()
+ versionInfo.fingerprint = "mockFingerprintForTesting"
+ whenever(rule.mocks().settings.internalVersion) {
+ versionInfo
+ }
+ }
+
+ private fun mockFingerprintUnchanged() {
+ // To mock that this is not the first boot
+ val versionInfo = Settings.VersionInfo()
+ versionInfo.fingerprint = MockSystem.DEFAULT_VERSION_INFO.fingerprint
+ whenever(rule.mocks().settings.internalVersion) {
+ versionInfo
+ }
+ }
+
+ private fun mockOta() {
+ wheneverStatic {
+ SystemProperties.getBoolean("persist.pm.mock-upgrade", false)
+ }.thenReturn(true)
+ }
+
+ private fun createPackageManagerService(): PackageManagerService {
+ return spy(PackageManagerService(rule.mocks().injector,
+ false /*factoryTest*/,
+ MockSystem.DEFAULT_VERSION_INFO.fingerprint,
+ false /*isEngBuild*/,
+ false /*isUserDebugBuild*/,
+ Build.VERSION_CODES.CUR_DEVELOPMENT,
+ Build.VERSION.INCREMENTAL))
+ }
+
+ @Test
+ fun testSystemScanFlagOnFirstBoot() {
+ val pms = createPackageManagerService()
+ assertThat(pms.isFirstBoot).isEqualTo(true)
+ assertThat(pms.isDeviceUpgrading).isEqualTo(false)
+ val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null, null,
+ listOf<ScanPartition>())
+ assertThat(
+ initAppsHelper.systemScanFlags and PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+ .isEqualTo(PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+ }
+
+ @Test
+ fun testSystemScanFlagWithMockOTA() {
+ mockNoFirstBoot()
+ mockFingerprintUnchanged()
+ mockOta()
+ val pms = createPackageManagerService()
+ assertThat(pms.isFirstBoot).isEqualTo(false)
+ assertThat(pms.isDeviceUpgrading).isEqualTo(true)
+ val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null, null,
+ listOf<ScanPartition>())
+ assertThat(
+ initAppsHelper.systemScanFlags and PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+ .isEqualTo(PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+ }
+
+ @Test
+ fun testSystemScanFlagNoOTA() {
+ mockNoFirstBoot()
+ mockFingerprintUnchanged()
+ val pms = createPackageManagerService()
+ assertThat(pms.isFirstBoot).isEqualTo(false)
+ assertThat(pms.isDeviceUpgrading).isEqualTo(false)
+ val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null, null,
+ listOf<ScanPartition>())
+ assertThat(
+ initAppsHelper.systemScanFlags and PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+ .isEqualTo(0)
+ }
+
+ @Test
+ fun testSystemScanFlagWithFingerprintChanged() {
+ mockNoFirstBoot()
+ mockFingerprintChanged()
+ val pms = createPackageManagerService()
+ assertThat(pms.isFirstBoot).isEqualTo(false)
+ assertThat(pms.isDeviceUpgrading).isEqualTo(true)
+ val initAppsHelper = InitAppsHelper(pms, rule.mocks().apexManager, null, null,
+ listOf<ScanPartition>())
+ assertThat(
+ initAppsHelper.systemScanFlags and PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+ .isEqualTo(PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE)
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
index 51498a6..a62569f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
@@ -23,7 +23,9 @@
@Presubmit
public class PackageVerificationStateTest extends AndroidTestCase {
- private static final int REQUIRED_UID = 1948;
+ private static final int REQUIRED_UID_1 = 1948;
+
+ private static final int REQUIRED_UID_2 = 1949;
private static final int SUFFICIENT_UID_1 = 1005;
@@ -31,12 +33,12 @@
public void testPackageVerificationState_OnlyRequiredVerifier_AllowedInstall() {
PackageVerificationState state = new PackageVerificationState(null);
- state.setRequiredVerifierUid(REQUIRED_UID);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
- state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
assertTrue("Verification should be considered complete now",
state.isVerificationComplete());
@@ -47,23 +49,111 @@
public void testPackageVerificationState_OnlyRequiredVerifier_DeniedInstall() {
PackageVerificationState state = new PackageVerificationState(null);
- state.setRequiredVerifierUid(REQUIRED_UID);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
- state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_REJECT);
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_REJECT);
assertTrue("Verification should be considered complete now",
state.isVerificationComplete());
- assertFalse("Installation should be marked as allowed",
+ assertFalse("Installation should be marked as denied",
+ state.isInstallAllowed());
+ }
+
+ public void testPackageVerificationState_TwoRequiredVerifiers_AllowedInstall() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
+ state.addRequiredVerifierUid(REQUIRED_UID_2);
+
+ assertFalse("Verification should not be marked as complete yet",
+ state.isVerificationComplete());
+
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
+
+ assertFalse("Verification should not be marked as complete yet",
+ state.isVerificationComplete());
+
+ state.setVerifierResponse(REQUIRED_UID_2, PackageManager.VERIFICATION_ALLOW);
+
+ assertTrue("Verification should be considered complete now",
+ state.isVerificationComplete());
+
+ assertTrue("Installation should be marked as allowed",
+ state.isInstallAllowed());
+ }
+
+ public void testPackageVerificationState_TwoRequiredVerifiers_DeniedInstall() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
+ state.addRequiredVerifierUid(REQUIRED_UID_2);
+
+ assertFalse("Verification should not be marked as complete yet",
+ state.isVerificationComplete());
+
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_REJECT);
+
+ assertFalse("Verification should not be marked as complete yet",
+ state.isVerificationComplete());
+
+ state.setVerifierResponse(REQUIRED_UID_2, PackageManager.VERIFICATION_REJECT);
+
+ assertTrue("Verification should be considered complete now",
+ state.isVerificationComplete());
+
+ assertFalse("Installation should be marked as denied",
+ state.isInstallAllowed());
+ }
+
+ public void testPackageVerificationState_TwoRequiredVerifiers_FirstDeniedInstall() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
+ state.addRequiredVerifierUid(REQUIRED_UID_2);
+
+ assertFalse("Verification should not be marked as complete yet",
+ state.isVerificationComplete());
+
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_REJECT);
+
+ assertFalse("Verification should not be marked as complete yet",
+ state.isVerificationComplete());
+
+ state.setVerifierResponse(REQUIRED_UID_2, PackageManager.VERIFICATION_ALLOW);
+
+ assertTrue("Verification should be considered complete now",
+ state.isVerificationComplete());
+
+ assertFalse("Installation should be marked as denied",
+ state.isInstallAllowed());
+ }
+
+ public void testPackageVerificationState_TwoRequiredVerifiers_SecondDeniedInstall() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
+ state.addRequiredVerifierUid(REQUIRED_UID_2);
+
+ assertFalse("Verification should not be marked as complete yet",
+ state.isVerificationComplete());
+
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
+
+ assertFalse("Verification should not be marked as complete yet",
+ state.isVerificationComplete());
+
+ state.setVerifierResponse(REQUIRED_UID_2, PackageManager.VERIFICATION_REJECT);
+
+ assertTrue("Verification should be considered complete now",
+ state.isVerificationComplete());
+
+ assertFalse("Installation should be marked as denied",
state.isInstallAllowed());
}
public void testPackageVerificationState_RequiredAndOneSufficient_RequiredDeniedInstall() {
PackageVerificationState state = new PackageVerificationState(null);
- state.setRequiredVerifierUid(REQUIRED_UID);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -78,18 +168,46 @@
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
- state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_REJECT);
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_REJECT);
assertTrue("Verification should be considered complete now",
state.isVerificationComplete());
- assertFalse("Installation should be marked as allowed",
+ assertFalse("Installation should be marked as denied",
+ state.isInstallAllowed());
+ }
+
+ public void testPackageVerificationState_RequiredAndOneSufficient_OneRequiredDeniedInstall() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
+ state.addRequiredVerifierUid(REQUIRED_UID_2);
+
+ assertFalse("Verification should not be marked as complete yet",
+ state.isVerificationComplete());
+
+ state.addSufficientVerifier(SUFFICIENT_UID_1);
+
+ assertFalse("Verification should not be marked as complete yet",
+ state.isVerificationComplete());
+
+ state.setVerifierResponse(SUFFICIENT_UID_1, PackageManager.VERIFICATION_ALLOW);
+
+ assertFalse("Verification should not be marked as complete yet",
+ state.isVerificationComplete());
+
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
+ state.setVerifierResponse(REQUIRED_UID_2, PackageManager.VERIFICATION_REJECT);
+
+ assertTrue("Verification should be considered complete now",
+ state.isVerificationComplete());
+
+ assertFalse("Installation should be marked as denied",
state.isInstallAllowed());
}
public void testPackageVerificationState_RequiredAndOneSufficient_SufficientDeniedInstall() {
PackageVerificationState state = new PackageVerificationState(null);
- state.setRequiredVerifierUid(REQUIRED_UID);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -104,7 +222,7 @@
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
- state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
assertTrue("Verification should be considered complete now",
state.isVerificationComplete());
@@ -115,7 +233,7 @@
public void testPackageVerificationState_RequiredAndTwoSufficient_OneSufficientIsEnough() {
PackageVerificationState state = new PackageVerificationState(null);
- state.setRequiredVerifierUid(REQUIRED_UID);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -131,7 +249,7 @@
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
- state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
assertTrue("Verification should be considered complete now",
state.isVerificationComplete());
@@ -142,7 +260,7 @@
public void testPackageVerificationState_RequiredAndTwoSufficient_SecondSufficientIsEnough() {
PackageVerificationState state = new PackageVerificationState(null);
- state.setRequiredVerifierUid(REQUIRED_UID);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -153,7 +271,7 @@
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
- state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -174,7 +292,7 @@
public void testPackageVerificationState_RequiredAndTwoSufficient_RequiredOverrides() {
PackageVerificationState state = new PackageVerificationState(null);
- state.setRequiredVerifierUid(REQUIRED_UID);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -185,7 +303,7 @@
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
- state.setVerifierResponse(REQUIRED_UID,
+ state.setVerifierResponse(REQUIRED_UID_1,
PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
assertTrue("Verification should be marked as complete immediately",
@@ -213,17 +331,17 @@
public void testAreAllVerificationsComplete_onlyVerificationPasses() {
PackageVerificationState state = new PackageVerificationState(null);
- state.setRequiredVerifierUid(REQUIRED_UID);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
assertFalse(state.areAllVerificationsComplete());
- state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
assertFalse(state.areAllVerificationsComplete());
}
public void testAreAllVerificationsComplete_onlyIntegrityCheckPasses() {
PackageVerificationState state = new PackageVerificationState(null);
- state.setRequiredVerifierUid(REQUIRED_UID);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
assertFalse(state.areAllVerificationsComplete());
state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
@@ -233,28 +351,28 @@
public void testAreAllVerificationsComplete_bothPasses() {
PackageVerificationState state = new PackageVerificationState(null);
- state.setRequiredVerifierUid(REQUIRED_UID);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
assertFalse(state.areAllVerificationsComplete());
state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
- state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_ALLOW);
assertTrue(state.areAllVerificationsComplete());
}
public void testAreAllVerificationsComplete_onlyVerificationFails() {
PackageVerificationState state = new PackageVerificationState(null);
- state.setRequiredVerifierUid(REQUIRED_UID);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
assertFalse(state.areAllVerificationsComplete());
- state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_REJECT);
+ state.setVerifierResponse(REQUIRED_UID_1, PackageManager.VERIFICATION_REJECT);
assertFalse(state.areAllVerificationsComplete());
}
public void testAreAllVerificationsComplete_onlyIntegrityCheckFails() {
PackageVerificationState state = new PackageVerificationState(null);
- state.setRequiredVerifierUid(REQUIRED_UID);
+ state.addRequiredVerifierUid(REQUIRED_UID_1);
assertFalse(state.areAllVerificationsComplete());
state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index e9171c0c..92c7871 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -336,6 +336,59 @@
assertThat(mSysConfig.getAllowedVendorApexes()).isEmpty();
}
+ /**
+ * Tests that readPermissions works correctly for the tag: {@code install-constraints-allowed}.
+ */
+ @Test
+ public void readPermissions_installConstraints_successful() throws IOException {
+ final String contents =
+ "<config>\n"
+ + " <install-constraints-allowed package=\"com.android.apex1\" />\n"
+ + "</config>";
+ final File folder = createTempSubfolder("folder");
+ createTempFile(folder, "install-constraints-allowlist.xml", contents);
+
+ readPermissions(folder, /* Grant all permission flags */ ~0);
+
+ assertThat(mSysConfig.getInstallConstraintsAllowlist())
+ .containsExactly("com.android.apex1");
+ }
+
+ /**
+ * Tests that readPermissions works correctly for the tag: {@code install-constraints-allowed}.
+ */
+ @Test
+ public void readPermissions_installConstraints_noPackage() throws IOException {
+ final String contents =
+ "<config>\n"
+ + " <install-constraints-allowed/>\n"
+ + "</config>";
+ final File folder = createTempSubfolder("folder");
+ createTempFile(folder, "install-constraints-allowlist.xml", contents);
+
+ readPermissions(folder, /* Grant all permission flags */ ~0);
+
+ assertThat(mSysConfig.getInstallConstraintsAllowlist()).isEmpty();
+ }
+
+ /**
+ * Tests that readPermissions works correctly for the tag {@code install-constraints-allowed}
+ * without {@link SystemConfig#ALLOW_VENDOR_APEX}.
+ */
+ @Test
+ public void readPermissions_installConstraints_noAppConfigs() throws IOException {
+ final String contents =
+ "<config>\n"
+ + " <install-constraints-allowed package=\"com.android.apex1\" />\n"
+ + "</config>";
+ final File folder = createTempSubfolder("folder");
+ createTempFile(folder, "install-constraints-allowlist.xml", contents);
+
+ readPermissions(folder, /* Grant all but ALLOW_APP_CONFIGS flag */ ~0x08);
+
+ assertThat(mSysConfig.getInstallConstraintsAllowlist()).isEmpty();
+ }
+
@Test
public void readApexPrivAppPermissions_addAllPermissions()
throws Exception {
diff --git a/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java b/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java
new file mode 100644
index 0000000..1f7b65e
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+
+import android.app.GameManagerInternal;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.LocalServices;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link CompatModePackages} class.
+ *
+ * Build/Install/Run:
+ * atest WmTests:CompatModePackagesTests
+ */
+@SmallTest
+@Presubmit
+public class CompatModePackagesTests extends SystemServiceTestsBase {
+ ActivityTaskManagerService mAtm;
+ GameManagerInternal mGm;
+ static final String TEST_PACKAGE = "compat.mode.packages";
+ static final int TEST_USER_ID = 1;
+
+ @Before
+ public void setUp() {
+ mAtm = mSystemServicesTestRule.getActivityTaskManagerService();
+ mGm = mock(GameManagerInternal.class);
+ }
+
+ @After
+ public void tearDown() {
+ LocalServices.removeServiceForTest(GameManagerInternal.class);
+ }
+
+ @Test
+ public void testGetCompatScale_gameManagerReturnsPositive() {
+ LocalServices.addService(GameManagerInternal.class, mGm);
+ float scale = 0.25f;
+ doReturn(scale).when(mGm).getResolutionScalingFactor(anyString(), anyInt());
+ assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1 / scale,
+ 0.01f);
+ }
+
+ @Test
+ public void testGetCompatScale_gameManagerReturnsZero() {
+ LocalServices.addService(GameManagerInternal.class, mGm);
+ float scale = 0f;
+ doReturn(scale).when(mGm).getResolutionScalingFactor(anyString(), anyInt());
+ assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1f,
+ 0.01f);
+ }
+
+ @Test
+ public void testGetCompatScale_gameManagerReturnsNegative() {
+ LocalServices.addService(GameManagerInternal.class, mGm);
+ float scale = -1f;
+ doReturn(scale).when(mGm).getResolutionScalingFactor(anyString(), anyInt());
+ assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1f,
+ 0.01f);
+ }
+
+ @Test
+ public void testGetCompatScale_noGameManager() {
+ assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1f,
+ 0.01f);
+ }
+
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 68079f4..9e658e0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -72,6 +72,7 @@
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.os.PowerManager;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.util.MergedConfiguration;
@@ -169,7 +170,8 @@
public void testTaskLayerRank() {
final Task rootTask = new TaskBuilder(mSupervisor).build();
final Task task1 = new TaskBuilder(mSupervisor).setParentTaskFragment(rootTask).build();
- new ActivityBuilder(mAtm).setTask(task1).build().mVisibleRequested = true;
+ final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task1).build();
+ activity1.mVisibleRequested = true;
mWm.mRoot.rankTaskLayers();
assertEquals(1, task1.mLayerRank);
@@ -177,7 +179,8 @@
assertEquals(Task.LAYER_RANK_INVISIBLE, rootTask.mLayerRank);
final Task task2 = new TaskBuilder(mSupervisor).build();
- new ActivityBuilder(mAtm).setTask(task2).build().mVisibleRequested = true;
+ final ActivityRecord activity2 = new ActivityBuilder(mAtm).setTask(task2).build();
+ activity2.mVisibleRequested = true;
mWm.mRoot.rankTaskLayers();
// Note that ensureActivitiesVisible is disabled in SystemServicesTestRule, so both the
@@ -192,6 +195,17 @@
assertEquals(1, task1.mLayerRank);
assertEquals(2, task2.mLayerRank);
+
+ // The rank should be updated to invisible when device went to sleep.
+ activity1.mVisibleRequested = false;
+ activity2.mVisibleRequested = false;
+ doReturn(true).when(mAtm).isSleepingOrShuttingDownLocked();
+ doReturn(true).when(mRootWindowContainer).putTasksToSleep(anyBoolean(), anyBoolean());
+ mSupervisor.mGoingToSleepWakeLock = mock(PowerManager.WakeLock.class);
+ doReturn(false).when(mSupervisor.mGoingToSleepWakeLock).isHeld();
+ mAtm.mTaskSupervisor.checkReadyForSleepLocked(false /* allowDelay */);
+ assertEquals(Task.LAYER_RANK_INVISIBLE, task1.mLayerRank);
+ assertEquals(Task.LAYER_RANK_INVISIBLE, task2.mLayerRank);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index f38731b..8b3cff8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -75,6 +75,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
/**
* Build/Install/Run:
@@ -92,7 +94,6 @@
private TaskFragmentOrganizerToken mOrganizerToken;
private ITaskFragmentOrganizer mIOrganizer;
private TaskFragment mTaskFragment;
- private TaskFragmentInfo mTaskFragmentInfo;
private IBinder mFragmentToken;
private WindowContainerTransaction mTransaction;
private WindowContainerToken mFragmentWindowToken;
@@ -100,14 +101,19 @@
private IBinder mErrorToken;
private Rect mTaskFragBounds;
+ @Mock
+ private TaskFragmentInfo mTaskFragmentInfo;
+ @Mock
+ private Task mTask;
+
@Before
public void setup() {
+ MockitoAnnotations.initMocks(this);
mWindowOrganizerController = mAtm.mWindowOrganizerController;
mController = mWindowOrganizerController.mTaskFragmentOrganizerController;
mOrganizer = new TaskFragmentOrganizer(Runnable::run);
mOrganizerToken = mOrganizer.getOrganizerToken();
mIOrganizer = ITaskFragmentOrganizer.Stub.asInterface(mOrganizerToken.asBinder());
- mTaskFragmentInfo = mock(TaskFragmentInfo.class);
mFragmentToken = new Binder();
mTaskFragment =
new TaskFragment(mAtm, mFragmentToken, true /* createdByOrganizer */);
@@ -131,6 +137,8 @@
@Test
public void testCallTaskFragmentCallbackWithoutRegister_throwsException() {
+ doReturn(mTask).when(mTaskFragment).getTask();
+
assertThrows(IllegalArgumentException.class, () -> mController
.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment));
@@ -140,16 +148,21 @@
assertThrows(IllegalArgumentException.class, () -> mController
.onTaskFragmentVanished(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment));
-
- assertThrows(IllegalArgumentException.class, () -> mController
- .onTaskFragmentParentInfoChanged(mTaskFragment.getTaskFragmentOrganizer(),
- mTaskFragment));
}
@Test
public void testOnTaskFragmentAppeared() {
mController.registerOrganizer(mIOrganizer);
+ // No-op when the TaskFragment is not attached.
+ mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
+ mController.dispatchPendingEvents();
+
+ verify(mOrganizer, never()).onTaskFragmentAppeared(any());
+
+ // Send callback when the TaskFragment is attached.
+ setupMockParent(mTaskFragment, mTask);
+
mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
@@ -159,9 +172,21 @@
@Test
public void testOnTaskFragmentInfoChanged() {
mController.registerOrganizer(mIOrganizer);
+ setupMockParent(mTaskFragment, mTask);
+
+ // No-op if onTaskFragmentAppeared is not called yet.
+ mController.onTaskFragmentInfoChanged(mTaskFragment.getTaskFragmentOrganizer(),
+ mTaskFragment);
+ mController.dispatchPendingEvents();
+
+ verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
+
+ // Call onTaskFragmentAppeared first.
mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
+ verify(mOrganizer).onTaskFragmentAppeared(any());
+
// No callback if the info is not changed.
doReturn(true).when(mTaskFragmentInfo).equalsForTaskFragmentOrganizer(any());
doReturn(new Configuration()).when(mTaskFragmentInfo).getConfiguration();
@@ -194,49 +219,74 @@
}
@Test
+ public void testOnTaskFragmentVanished_clearUpRemaining() {
+ mController.registerOrganizer(mIOrganizer);
+ setupMockParent(mTaskFragment, mTask);
+
+ // Not trigger onTaskFragmentAppeared.
+ mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
+ mController.onTaskFragmentVanished(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
+ mController.dispatchPendingEvents();
+
+ verify(mOrganizer, never()).onTaskFragmentAppeared(any());
+ verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
+ verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(anyInt(), any());
+ verify(mOrganizer).onTaskFragmentVanished(mTaskFragmentInfo);
+
+ // Not trigger onTaskFragmentInfoChanged.
+ // Call onTaskFragmentAppeared before calling onTaskFragmentInfoChanged.
+ mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
+ mController.dispatchPendingEvents();
+ clearInvocations(mOrganizer);
+ doReturn(true).when(mTaskFragmentInfo).equalsForTaskFragmentOrganizer(any());
+ mController.onTaskFragmentInfoChanged(mTaskFragment.getTaskFragmentOrganizer(),
+ mTaskFragment);
+ mController.onTaskFragmentVanished(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
+ mController.dispatchPendingEvents();
+
+ verify(mOrganizer, never()).onTaskFragmentAppeared(any());
+ verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
+ verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(anyInt(), any());
+ verify(mOrganizer).onTaskFragmentVanished(mTaskFragmentInfo);
+ }
+
+ @Test
public void testOnTaskFragmentParentInfoChanged() {
mController.registerOrganizer(mIOrganizer);
- final Task parent = mock(Task.class);
- final Configuration parentConfig = new Configuration();
- parentConfig.smallestScreenWidthDp = 10;
- doReturn(parent).when(mTaskFragment).getTask();
- doReturn(parentConfig).when(parent).getConfiguration();
- // Task needs to be visible
- parent.lastActiveTime = 100;
- doReturn(true).when(parent).shouldBeVisible(any());
+ setupMockParent(mTaskFragment, mTask);
+ mTask.getConfiguration().smallestScreenWidthDp = 10;
- mTaskFragment.mTaskFragmentAppearedSent = true;
- mController.onTaskFragmentParentInfoChanged(
+ mController.onTaskFragmentAppeared(
mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mFragmentToken), any());
+ verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mTask.mTaskId), any());
// No extra callback if the info is not changed.
clearInvocations(mOrganizer);
- mController.onTaskFragmentParentInfoChanged(
+ mController.onTaskFragmentInfoChanged(
mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(any(), any());
+ verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(anyInt(), any());
// Trigger callback if the size is changed.
- parentConfig.smallestScreenWidthDp = 100;
- mController.onTaskFragmentParentInfoChanged(
+ mTask.getConfiguration().smallestScreenWidthDp = 100;
+ mController.onTaskFragmentInfoChanged(
mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mFragmentToken), any());
+ verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mTask.mTaskId), any());
// Trigger callback if the windowing mode is changed.
clearInvocations(mOrganizer);
- parentConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_PINNED);
- mController.onTaskFragmentParentInfoChanged(
+ mTask.getConfiguration().windowConfiguration.setWindowingMode(WINDOWING_MODE_PINNED);
+ mController.onTaskFragmentInfoChanged(
mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();
- verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mFragmentToken), any());
+ verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mTask.mTaskId), any());
}
@Test
@@ -1091,4 +1141,15 @@
.put(mFragmentToken, mTaskFragment);
mTaskFragment.getTask().setWindowingMode(WINDOWING_MODE_PINNED);
}
+
+ /** Setups the mock Task as the parent of the given TaskFragment. */
+ private static void setupMockParent(TaskFragment taskFragment, Task mockParent) {
+ doReturn(mockParent).when(taskFragment).getTask();
+ final Configuration taskConfig = new Configuration();
+ doReturn(taskConfig).when(mockParent).getConfiguration();
+
+ // Task needs to be visible
+ mockParent.lastActiveTime = 100;
+ doReturn(true).when(mockParent).shouldBeVisible(any());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index 1096351..88eadfc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -32,6 +32,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
+import static com.android.server.wm.TaskFragment.EMBEDDING_ALLOWED;
import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_MIN_DIMENSION_VIOLATION;
import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_NEW_TASK_FRAGMENT;
import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_UNTRUSTED_HOST;
@@ -468,6 +469,10 @@
newActivity.resultTo = activity;
assertEquals(EMBEDDING_DISALLOWED_NEW_TASK_FRAGMENT,
newTaskFragment.isAllowedToEmbedActivity(newActivity));
+
+ // Allow embedding if the resultTo activity is finishing.
+ activity.finishing = true;
+ assertEquals(EMBEDDING_ALLOWED, newTaskFragment.isAllowedToEmbedActivity(newActivity));
}
@Test
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 f4323db..6a7e388 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -846,6 +846,7 @@
new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME, targetClassName);
final Intent intent = new Intent();
+ intent.setPackage(DEFAULT_COMPONENT_PACKAGE_NAME);
intent.setComponent(aliasComponent);
final ActivityInfo info = new ActivityInfo();
info.applicationInfo = new ApplicationInfo();
diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortHalInstance.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortHalInstance.java
index 41f9fae..6fc4b67 100644
--- a/services/usb/java/com/android/server/usb/hal/port/UsbPortHalInstance.java
+++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortHalInstance.java
@@ -31,15 +31,14 @@
public static UsbPortHal getInstance(UsbPortManager portManager, IndentingPrintWriter pw) {
logAndPrint(Log.DEBUG, null, "Querying USB HAL version");
- if (UsbPortHidl.isServicePresent(null)) {
- logAndPrint(Log.INFO, null, "USB HAL HIDL present");
- return new UsbPortHidl(portManager, pw);
- }
if (UsbPortAidl.isServicePresent(null)) {
logAndPrint(Log.INFO, null, "USB HAL AIDL present");
return new UsbPortAidl(portManager, pw);
}
-
+ if (UsbPortHidl.isServicePresent(null)) {
+ logAndPrint(Log.INFO, null, "USB HAL HIDL present");
+ return new UsbPortHidl(portManager, pw);
+ }
return null;
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
index e0ae193..e138d33 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
@@ -108,7 +108,8 @@
}
/**
- * Checks that the [ComponentMatcher.TASK_BAR] layer is visible during the whole transition
+ * Checks that the [ComponentMatcher.TASK_BAR] window is visible at the start and end of the
+ * transition
*
* Note: Large screen only
*/
@@ -132,7 +133,8 @@
}
/**
- * Checks that the [ComponentMatcher.STATUS_BAR] layer is visible during the whole transition
+ * Checks that the [ComponentMatcher.STATUS_BAR] layer is visible at the start and end
+ * of the transition
*/
@Presubmit
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index d173b72..5e21252 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -53,6 +53,16 @@
}
/**
+ * Checks that [ComponentMatcher.TASK_BAR] window is visible and above the app windows in
+ * all WM trace entries
+ */
+fun FlickerTestParameter.taskBarWindowIsVisibleAtEnd() {
+ assertWmEnd {
+ this.isAboveAppWindowVisible(ComponentMatcher.TASK_BAR)
+ }
+}
+
+/**
* If [allStates] is true, checks if the stack space of all displays is fully covered
* by any visible layer, during the whole transitions
*
@@ -103,9 +113,25 @@
* trace
*/
fun FlickerTestParameter.taskBarLayerIsVisibleAtStartAndEnd() {
+ this.taskBarLayerIsVisibleAtStart()
+ this.taskBarLayerIsVisibleAtEnd()
+}
+
+/**
+ * Checks that [ComponentMatcher.TASK_BAR] layer is visible at the start of the SF
+ * trace
+ */
+fun FlickerTestParameter.taskBarLayerIsVisibleAtStart() {
assertLayersStart {
this.isVisible(ComponentMatcher.TASK_BAR)
}
+}
+
+/**
+ * Checks that [ComponentMatcher.TASK_BAR] layer is visible at the end of the SF
+ * trace
+ */
+fun FlickerTestParameter.taskBarLayerIsVisibleAtEnd() {
assertLayersEnd {
this.isVisible(ComponentMatcher.TASK_BAR)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
index 6e3e74d..866e819 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
@@ -32,8 +32,12 @@
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.taskBarLayerIsVisibleAtEnd
+import com.android.server.wm.flicker.taskBarWindowIsVisibleAtEnd
+import com.android.server.wm.traces.common.ComponentMatcher
import org.junit.Assume
import org.junit.FixMethodOrder
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -231,6 +235,42 @@
super.appWindowBecomesTopWindow()
}
+ /**
+ * Checks that the [ComponentMatcher.TASK_BAR] window is visible at the end of the transition
+ *
+ * Note: Large screen only
+ */
+ @Postsubmit
+ @Test
+ open fun taskBarWindowIsVisibleAtEnd() {
+ Assume.assumeFalse(testSpec.isTablet)
+ testSpec.taskBarWindowIsVisibleAtEnd()
+ }
+
+ /**
+ * Checks that the [ComponentMatcher.TASK_BAR] layer is visible at the end of the transition
+ *
+ * Note: Large screen only
+ */
+ @Postsubmit
+ @Test
+ open fun taskBarLayerIsVisibleAtEnd() {
+ Assume.assumeFalse(testSpec.isTablet)
+ testSpec.taskBarLayerIsVisibleAtEnd()
+ }
+
+ /** {@inheritDoc} */
+ @Test
+ @Ignore("Display is locked at the start")
+ override fun taskBarWindowIsAlwaysVisible() =
+ super.taskBarWindowIsAlwaysVisible()
+
+ /** {@inheritDoc} */
+ @Test
+ @Ignore("Display is locked at the start")
+ override fun taskBarLayerIsVisibleAtStartAndEnd() =
+ super.taskBarLayerIsVisibleAtStartAndEnd()
+
companion object {
/**
* Creates the test configurations.
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index cbf920ac..035f911 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -472,6 +472,7 @@
manifest_action["compatible-screens"]["screen"];
manifest_action["supports-gl-texture"];
manifest_action["restrict-update"];
+ manifest_action["install-constraints"]["fingerprint-prefix"];
manifest_action["package-verifier"];
manifest_action["meta-data"] = meta_data_action;
manifest_action["uses-split"].Action(RequiredNameIsJavaPackage);
diff --git a/tools/xmlpersistence/src/main/kotlin/Generator.kt b/tools/xmlpersistence/src/main/kotlin/Generator.kt
index b2c5f4a..8e62388 100644
--- a/tools/xmlpersistence/src/main/kotlin/Generator.kt
+++ b/tools/xmlpersistence/src/main/kotlin/Generator.kt
@@ -149,6 +149,7 @@
when (field) {
is ClassFieldInfo -> this += field.allClassFields
is ListFieldInfo -> this += field.element.allClassFields
+ else -> {}
}
}
}