Merge "Align the Talkback slider percentage announcement with the UI." into main
diff --git a/core/api/current.txt b/core/api/current.txt
index e9a63f7..17e7d7a 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -19346,7 +19346,7 @@
public class BiometricManager {
method @Deprecated @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public int canAuthenticate();
method @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public int canAuthenticate(int);
- method @FlaggedApi("android.hardware.biometrics.last_authentication_time") @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public long getLastAuthenticationTime(int);
+ method @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public long getLastAuthenticationTime(int);
method @NonNull @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public android.hardware.biometrics.BiometricManager.Strings getStrings(int);
field public static final int BIOMETRIC_ERROR_HW_UNAVAILABLE = 1; // 0x1
field @FlaggedApi("android.hardware.biometrics.identity_check_api") public static final int BIOMETRIC_ERROR_IDENTITY_CHECK_NOT_ACTIVE = 20; // 0x14
@@ -19354,7 +19354,7 @@
field @FlaggedApi("android.hardware.biometrics.identity_check_api") public static final int BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS = 21; // 0x15
field public static final int BIOMETRIC_ERROR_NO_HARDWARE = 12; // 0xc
field public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15; // 0xf
- field @FlaggedApi("android.hardware.biometrics.last_authentication_time") public static final long BIOMETRIC_NO_AUTHENTICATION = -1L; // 0xffffffffffffffffL
+ field public static final long BIOMETRIC_NO_AUTHENTICATION = -1L; // 0xffffffffffffffffL
field public static final int BIOMETRIC_SUCCESS = 0; // 0x0
}
@@ -19407,7 +19407,7 @@
field public static final int BIOMETRIC_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
field public static final int BIOMETRIC_ERROR_USER_CANCELED = 10; // 0xa
field public static final int BIOMETRIC_ERROR_VENDOR = 8; // 0x8
- field @FlaggedApi("android.hardware.biometrics.last_authentication_time") public static final long BIOMETRIC_NO_AUTHENTICATION = -1L; // 0xffffffffffffffffL
+ field public static final long BIOMETRIC_NO_AUTHENTICATION = -1L; // 0xffffffffffffffffL
}
public abstract static class BiometricPrompt.AuthenticationCallback {
@@ -21750,6 +21750,7 @@
field public static final int CHANNEL_IN_X_AXIS = 2048; // 0x800
field public static final int CHANNEL_IN_Y_AXIS = 4096; // 0x1000
field public static final int CHANNEL_IN_Z_AXIS = 8192; // 0x2000
+ field @FlaggedApi("android.media.audio.sony_360ra_mpegh_3d_format") public static final int CHANNEL_OUT_13POINT0 = 30136348; // 0x1cbd81c
field public static final int CHANNEL_OUT_5POINT1 = 252; // 0xfc
field public static final int CHANNEL_OUT_5POINT1POINT2 = 3145980; // 0x3000fc
field public static final int CHANNEL_OUT_5POINT1POINT4 = 737532; // 0xb40fc
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index 875adbd..7dc6afb 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -334,6 +334,5 @@
* Returned from {@link BiometricManager#getLastAuthenticationTime(int)} when there has
* been no successful authentication for the given authenticator since boot.
*/
- @FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME)
long BIOMETRIC_NO_AUTHENTICATION = -1;
}
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index c690c67..cefe20c 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -116,7 +116,6 @@
* Returned from {@link BiometricManager#getLastAuthenticationTime(int)} when no matching
* successful authentication has been performed since boot.
*/
- @FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME)
public static final long BIOMETRIC_NO_AUTHENTICATION =
BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
@@ -777,7 +776,6 @@
*/
@RequiresPermission(USE_BIOMETRIC)
@ElapsedRealtimeLong
- @FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME)
public long getLastAuthenticationTime(
@BiometricManager.Authenticators.Types int authenticators) {
if (authenticators == 0
diff --git a/core/java/android/hardware/biometrics/flags.aconfig b/core/java/android/hardware/biometrics/flags.aconfig
index 73b6417..4815f3e 100644
--- a/core/java/android/hardware/biometrics/flags.aconfig
+++ b/core/java/android/hardware/biometrics/flags.aconfig
@@ -2,14 +2,6 @@
container: "system"
flag {
- name: "last_authentication_time"
- is_exported: true
- namespace: "wallet_integration"
- description: "Feature flag for adding getLastAuthenticationTime API to BiometricManager"
- bug: "301979982"
-}
-
-flag {
name: "add_key_agreement_crypto_object"
is_exported: true
namespace: "biometrics"
diff --git a/core/java/android/os/TestLooperManager.java b/core/java/android/os/TestLooperManager.java
index d451109..ddfa379 100644
--- a/core/java/android/os/TestLooperManager.java
+++ b/core/java/android/os/TestLooperManager.java
@@ -84,17 +84,8 @@
* interactions with it have completed.
*/
public Message next() {
- // Wait for the looper block to come up, to make sure we don't accidentally get
- // the message for the block.
- while (!mLooperIsMyLooper && !mLooperBlocked) {
- synchronized (this) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
- }
checkReleased();
+ waitForLooperHolder();
return mQueue.next();
}
@@ -110,6 +101,7 @@
@Nullable
public Message poll() {
checkReleased();
+ waitForLooperHolder();
return mQueue.pollForTest();
}
@@ -124,6 +116,7 @@
@Nullable
public Long peekWhen() {
checkReleased();
+ waitForLooperHolder();
return mQueue.peekWhenForTest();
}
@@ -133,6 +126,7 @@
@FlaggedApi(Flags.FLAG_MESSAGE_QUEUE_TESTABILITY)
public boolean isBlockedOnSyncBarrier() {
checkReleased();
+ waitForLooperHolder();
return mQueue.isBlockedOnSyncBarrier();
}
@@ -221,6 +215,23 @@
}
}
+ /**
+ * Waits until the Looper is blocked by the LooperHolder, if one was posted.
+ *
+ * After this method returns, it's guaranteed that the LooperHolder Message
+ * is not in the underlying queue.
+ */
+ private void waitForLooperHolder() {
+ while (!mLooperIsMyLooper && !mLooperBlocked) {
+ synchronized (this) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+
private class LooperHolder implements Runnable {
@Override
public void run() {
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
index 1771642..6ed8c6d 100644
--- a/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
@@ -76,22 +76,30 @@
private IQuickAccessWalletService mService;
@Nullable
- private final QuickAccessWalletServiceInfo mServiceInfo;
+ private QuickAccessWalletServiceInfo mServiceInfo;
private static final int MSG_TIMEOUT_SERVICE = 5;
QuickAccessWalletClientImpl(@NonNull Context context, @Nullable Executor bgExecutor) {
mContext = context.getApplicationContext();
- mServiceInfo = QuickAccessWalletServiceInfo.tryCreate(context);
+ mServiceInfo = null;
mHandler = new Handler(Looper.getMainLooper());
mLifecycleExecutor = (bgExecutor == null) ? Runnable::run : bgExecutor;
mRequestQueue = new ArrayDeque<>();
mEventListeners = new HashMap<>(1);
}
+ private QuickAccessWalletServiceInfo ensureServiceInfo() {
+ if (mServiceInfo == null) {
+ mServiceInfo = QuickAccessWalletServiceInfo.tryCreate(mContext);
+ }
+
+ return mServiceInfo;
+ }
+
@Override
public boolean isWalletServiceAvailable() {
- return mServiceInfo != null;
+ return ensureServiceInfo() != null;
}
@Override
@@ -239,12 +247,13 @@
@Override
@Nullable
public Intent createWalletIntent() {
- if (mServiceInfo == null) {
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ if (serviceInfo == null) {
return null;
}
- String packageName = mServiceInfo.getComponentName().getPackageName();
- int userId = mServiceInfo.getUserId();
- String walletActivity = mServiceInfo.getWalletActivity();
+ String packageName = serviceInfo.getComponentName().getPackageName();
+ int userId = serviceInfo.getUserId();
+ String walletActivity = serviceInfo.getWalletActivity();
return createIntent(walletActivity, packageName, userId, ACTION_VIEW_WALLET);
}
@@ -298,11 +307,12 @@
@Override
@Nullable
public Intent createWalletSettingsIntent() {
- if (mServiceInfo == null) {
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ if (serviceInfo == null) {
return null;
}
- String packageName = mServiceInfo.getComponentName().getPackageName();
- String settingsActivity = mServiceInfo.getSettingsActivity();
+ String packageName = serviceInfo.getComponentName().getPackageName();
+ String settingsActivity = serviceInfo.getSettingsActivity();
return createIntent(settingsActivity, packageName, UserHandle.myUserId(),
ACTION_VIEW_WALLET_SETTINGS);
}
@@ -356,36 +366,42 @@
@Override
@Nullable
public Drawable getLogo() {
- return mServiceInfo == null ? null : mServiceInfo.getWalletLogo(mContext);
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ return serviceInfo == null ? null : serviceInfo.getWalletLogo(mContext);
}
@Nullable
@Override
public Drawable getTileIcon() {
- return mServiceInfo == null ? null : mServiceInfo.getTileIcon();
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ return serviceInfo == null ? null : serviceInfo.getTileIcon();
}
@Nullable
@Override
public UserHandle getUser() {
- return mServiceInfo == null ? null : UserHandle.of(mServiceInfo.getUserId());
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ return serviceInfo == null ? null : UserHandle.of(serviceInfo.getUserId());
}
@Override
@Nullable
public CharSequence getServiceLabel() {
- return mServiceInfo == null ? null : mServiceInfo.getServiceLabel(mContext);
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ return serviceInfo == null ? null : serviceInfo.getServiceLabel(mContext);
}
@Override
@Nullable
public CharSequence getShortcutShortLabel() {
- return mServiceInfo == null ? null : mServiceInfo.getShortcutShortLabel(mContext);
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ return serviceInfo == null ? null : serviceInfo.getShortcutShortLabel(mContext);
}
@Override
public CharSequence getShortcutLongLabel() {
- return mServiceInfo == null ? null : mServiceInfo.getShortcutLongLabel(mContext);
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ return serviceInfo == null ? null : serviceInfo.getShortcutLongLabel(mContext);
}
private void connect() {
@@ -393,7 +409,8 @@
}
private void connectInternal() {
- if (mServiceInfo == null) {
+ QuickAccessWalletServiceInfo serviceInfo = ensureServiceInfo();
+ if (serviceInfo == null) {
Log.w(TAG, "Wallet service unavailable");
return;
}
@@ -402,7 +419,7 @@
}
mIsConnected = true;
Intent intent = new Intent(SERVICE_INTERFACE);
- intent.setComponent(mServiceInfo.getComponentName());
+ intent.setComponent(serviceInfo.getComponentName());
int flags = Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY;
mLifecycleExecutor.execute(() -> mContext.bindService(intent, this, flags));
resetServiceConnectionTimeout();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index cd8a85a..bf34069 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5566,9 +5566,6 @@
if (mAttachInfo.mContentCaptureManager != null) {
ContentCaptureSession session =
mAttachInfo.mContentCaptureManager.getMainContentCaptureSession();
- if (android.view.contentcapture.flags.Flags.postCreateAndroidBgThread()) {
- session.performStart();
- }
session.notifyWindowBoundsChanged(session.getId(),
getConfiguration().windowConfiguration.getBounds());
}
diff --git a/core/java/android/view/contentcapture/ChildContentCaptureSession.java b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
index 6e2e100..8baa55f 100644
--- a/core/java/android/view/contentcapture/ChildContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
@@ -74,8 +74,8 @@
}
@Override
- void internalFlush(@FlushReason int reason) {
- mParent.internalFlush(reason);
+ void flush(@FlushReason int reason) {
+ mParent.flush(reason);
}
@Override
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index b7a77d7..724e8fa 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -52,6 +52,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.util.RingBuffer;
import com.android.internal.util.SyncResultReceiver;
@@ -604,6 +605,7 @@
mContext,
this,
prepareUiHandler(),
+ prepareContentCaptureHandler(),
mService
);
if (sVerbose) Log.v(TAG, "getMainContentCaptureSession(): created " + mMainSession);
@@ -614,6 +616,15 @@
@NonNull
@GuardedBy("mLock")
+ private Handler prepareContentCaptureHandler() {
+ if (mContentCaptureHandler == null) {
+ mContentCaptureHandler = BackgroundThread.getHandler();
+ }
+ return mContentCaptureHandler;
+ }
+
+ @NonNull
+ @GuardedBy("mLock")
private Handler prepareUiHandler() {
if (mUiHandler == null) {
mUiHandler = Handler.createAsync(Looper.getMainLooper());
@@ -663,7 +674,7 @@
@UiThread
public void flush(@FlushReason int reason) {
if (mOptions.lite) return;
- getMainContentCaptureSession().internalFlush(reason);
+ getMainContentCaptureSession().flush(reason);
}
/**
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 791a6f4..9aeec20 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -286,9 +286,6 @@
abstract void start(@NonNull IBinder token, @NonNull IBinder shareableActivityToken,
@NonNull ComponentName component, int flags);
- /** @hide */
- public void performStart() {}
-
abstract boolean isDisabled();
/**
@@ -342,7 +339,7 @@
/**
* Flushes the buffered events to the service.
*/
- abstract void internalFlush(@FlushReason int reason);
+ abstract void flush(@FlushReason int reason);
/**
* Sets the {@link ContentCaptureContext} associated with the session.
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 29cae85..2fb78c0 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -57,12 +57,10 @@
import android.view.ViewStructure;
import android.view.autofill.AutofillId;
import android.view.contentcapture.ViewNode.ViewStructureImpl;
-import android.view.contentcapture.flags.Flags;
import android.view.contentprotection.ContentProtectionEventProcessor;
import android.view.inputmethod.BaseInputConnection;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.os.BackgroundThread;
import com.android.internal.os.IResultReceiver;
import com.android.modules.expresslog.Counter;
@@ -109,10 +107,8 @@
@NonNull
private final Handler mUiHandler;
- /** @hide */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- @Nullable
- public Handler mContentCaptureHandler;
+ @NonNull
+ private final Handler mContentCaptureHandler;
/**
* Interface to the system_server binder object - it's only used to start the session (and
@@ -191,12 +187,6 @@
@Nullable
public ContentProtectionEventProcessor mContentProtectionEventProcessor;
- /**
- * A runnable object to perform the start of this session.
- */
- @Nullable
- private Runnable mStartRunnable = null;
-
private static class SessionStateReceiver extends IResultReceiver.Stub {
private final WeakReference<MainContentCaptureSession> mMainSession;
@@ -208,7 +198,7 @@
public void send(int resultCode, Bundle resultData) {
final MainContentCaptureSession mainSession = mMainSession.get();
if (mainSession == null) {
- Log.w(TAG, "received result after main session released");
+ Log.w(TAG, "received result after mina session released");
return;
}
final IBinder binder;
@@ -223,8 +213,6 @@
binder = resultData.getBinder(EXTRA_BINDER);
if (binder == null) {
Log.wtf(TAG, "No " + EXTRA_BINDER + " extra result");
- // explicitly init the bg thread
- mainSession.mContentCaptureHandler = mainSession.prepareContentCaptureHandler();
mainSession.runOnContentCaptureThread(() -> mainSession.resetSession(
STATE_DISABLED | STATE_INTERNAL_ERROR));
return;
@@ -232,45 +220,23 @@
} else {
binder = null;
}
- // explicitly init the bg thread
- mainSession.mContentCaptureHandler = mainSession.prepareContentCaptureHandler();
mainSession.runOnContentCaptureThread(() ->
mainSession.onSessionStarted(resultCode, binder));
}
}
- /**
- * Prepares the content capture handler(i.e. the background thread).
- *
- * This is expected to be called from the {@link SessionStateReceiver#send} callback, after the
- * session {@link performStart}. This is expected to be executed in a binder thread, instead
- * of the UI thread.
- */
- @NonNull
- private Handler prepareContentCaptureHandler() {
- if (mContentCaptureHandler == null) {
- try {
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "prepareContentCaptureHandler");
- }
- mContentCaptureHandler = BackgroundThread.getHandler();
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- }
- return mContentCaptureHandler;
- }
-
/** @hide */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
public MainContentCaptureSession(
@NonNull ContentCaptureManager.StrippedContext context,
@NonNull ContentCaptureManager manager,
@NonNull Handler uiHandler,
+ @NonNull Handler contentCaptureHandler,
@NonNull IContentCaptureManager systemServerInterface) {
mContext = context;
mManager = manager;
mUiHandler = uiHandler;
+ mContentCaptureHandler = contentCaptureHandler;
mSystemServerInterface = systemServerInterface;
final int logHistorySize = mManager.mOptions.logHistorySize;
@@ -294,49 +260,18 @@
}
/**
- * Performs the start of the session.
- *
- * This is expected to be called from the UI thread, when the activity finishes its first frame.
- * This is a no-op if the session has already been started.
- *
- * See {@link #start(IBinder, IBinder, ComponentName, int)} for more details.
- *
- * @hide */
- @Override
- public void performStart() {
- if (!hasStarted() && mStartRunnable != null) {
- mStartRunnable.run();
- }
- }
-
- /**
- * Creates a runnable to start this session.
- *
- * For performance reasons, it is better to only create a task to start the session
- * during the creation of the activity and perform the actual start when the activity
- * finishes it's first frame.
+ * Starts this session.
*/
@Override
void start(@NonNull IBinder token, @NonNull IBinder shareableActivityToken,
@NonNull ComponentName component, int flags) {
- if (Flags.postCreateAndroidBgThread()) {
- mStartRunnable = () -> {
- try {
- if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "cc session startImpl");
- }
- startImpl(token, shareableActivityToken, component, flags);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- };
- } else {
- startImpl(token, shareableActivityToken, component, flags);
- }
+ runOnContentCaptureThread(
+ () -> startImpl(token, shareableActivityToken, component, flags));
}
private void startImpl(@NonNull IBinder token, @NonNull IBinder shareableActivityToken,
@NonNull ComponentName component, int flags) {
+ checkOnContentCaptureThread();
if (!isContentCaptureEnabled()) return;
if (sVerbose) {
@@ -370,12 +305,11 @@
Log.w(TAG, "Error starting session for " + component.flattenToShortString() + ": " + e);
}
}
-
@Override
void onDestroy() {
clearAndRunOnContentCaptureThread(() -> {
try {
- internalFlush(FLUSH_REASON_SESSION_FINISHED);
+ flush(FLUSH_REASON_SESSION_FINISHED);
} finally {
destroySession();
}
@@ -623,10 +557,11 @@
flushReason = forceFlush ? FLUSH_REASON_FORCE_FLUSH : FLUSH_REASON_FULL;
}
- internalFlush(flushReason);
+ flush(flushReason);
}
private boolean hasStarted() {
+ checkOnContentCaptureThread();
return mState != UNKNOWN_STATE;
}
@@ -640,11 +575,6 @@
if (sVerbose) Log.v(TAG, "handleScheduleFlush(): session not started yet");
return;
}
- if (mContentCaptureHandler == null) {
- Log.w(TAG, "handleScheduleFlush(" + getDebugState(reason) + "): content capture "
- + "thread not ready");
- return;
- }
if (mDisabled.get()) {
// Should not be called on this state, as handleSendEvent checks.
@@ -687,18 +617,15 @@
if (sVerbose) Log.v(TAG, "Nothing to flush");
return;
}
- internalFlush(reason);
+ flush(reason);
}
- /**
- * Internal API to flush the buffered events to the service.
- *
- * Do not confuse this with the public API {@link #flush()}.
- *
- * @hide */
+ /** @hide */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@Override
- public void internalFlush(@FlushReason int reason) {
+ public void flush(@FlushReason int reason) {
+ // TODO: b/380381249 renaming the internal APIs to prevent confusions between this and the
+ // public API.
runOnContentCaptureThread(() -> flushImpl(reason));
}
@@ -720,11 +647,6 @@
if (!isContentCaptureReceiverEnabled()) {
return;
}
- if (mContentCaptureHandler == null) {
- Log.w(TAG, "handleForceFlush(" + getDebugState(reason) + "): content capture thread"
- + "not ready");
- return;
- }
if (mDirectServiceInterface == null) {
if (sVerbose) {
@@ -841,9 +763,7 @@
}
mDirectServiceInterface = null;
mContentProtectionEventProcessor = null;
- if (mContentCaptureHandler != null) {
- mContentCaptureHandler.removeMessages(MSG_FLUSH);
- }
+ mContentCaptureHandler.removeMessages(MSG_FLUSH);
}
@Override
@@ -997,10 +917,6 @@
* clear the buffer events then starting sending out current event.
*/
private void enqueueEvent(@NonNull final ContentCaptureEvent event, boolean forceFlush) {
- if (mContentCaptureHandler == null) {
- mEventProcessQueue.offer(event);
- return;
- }
if (forceFlush || mEventProcessQueue.size() >= mManager.mOptions.maxBufferSize - 1) {
// The buffer events are cleared in the same thread first to prevent new events
// being added during the time of context switch. This would disrupt the sequence
@@ -1203,10 +1119,6 @@
* always delegate to the assigned thread from {@code mHandler} for synchronization.</p>
*/
private void checkOnContentCaptureThread() {
- if (mContentCaptureHandler == null) {
- Log.e(TAG, "content capture thread is not initiallized!");
- return;
- }
final boolean onContentCaptureThread = mContentCaptureHandler.getLooper().isCurrentThread();
if (!onContentCaptureThread) {
mWrongThreadCount.incrementAndGet();
@@ -1227,12 +1139,6 @@
* </p>
*/
private void runOnContentCaptureThread(@NonNull Runnable r) {
- if (mContentCaptureHandler == null) {
- Log.e(TAG, "content capture thread is not initiallized!");
- // fall back to UI thread
- runOnUiThread(r);
- return;
- }
if (!mContentCaptureHandler.getLooper().isCurrentThread()) {
mContentCaptureHandler.post(r);
} else {
@@ -1241,12 +1147,6 @@
}
private void clearAndRunOnContentCaptureThread(@NonNull Runnable r, int what) {
- if (mContentCaptureHandler == null) {
- Log.e(TAG, "content capture thread is not initiallized!");
- // fall back to UI thread
- runOnUiThread(r);
- return;
- }
if (!mContentCaptureHandler.getLooper().isCurrentThread()) {
mContentCaptureHandler.removeMessages(what);
mContentCaptureHandler.post(r);
diff --git a/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig b/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig
index 9df8350..e7bc004 100644
--- a/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig
+++ b/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig
@@ -15,14 +15,3 @@
bug: "380381249"
is_exported: true
}
-
-flag {
- name: "post_create_android_bg_thread"
- namespace: "pixel_state_server"
- description: "Feature flag to post create the bg thread when an app is in the allowlist"
- bug: "376468525"
- is_fixed_read_only: true
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 0e329c2..ec0d915 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -159,6 +159,7 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -719,6 +720,11 @@
// Nothing to visit by default.
}
+ /** See {@link RemoteViews#visitIcons(Consumer)}. **/
+ public void visitIcons(@NonNull Consumer<Icon> visitor) {
+ // Nothing to visit by default.
+ }
+
public abstract void writeToParcel(Parcel dest, int flags);
/**
@@ -849,6 +855,29 @@
}
/**
+ * Note all {@link Icon} that are referenced internally.
+ * @hide
+ */
+ public void visitIcons(@NonNull Consumer<Icon> visitor) {
+ if (mActions != null) {
+ for (int i = 0; i < mActions.size(); i++) {
+ mActions.get(i).visitIcons(visitor);
+ }
+ }
+ if (mSizedRemoteViews != null) {
+ for (int i = 0; i < mSizedRemoteViews.size(); i++) {
+ mSizedRemoteViews.get(i).visitIcons(visitor);
+ }
+ }
+ if (mLandscape != null) {
+ mLandscape.visitIcons(visitor);
+ }
+ if (mPortrait != null) {
+ mPortrait.visitIcons(visitor);
+ }
+ }
+
+ /**
* @hide
* @return True if there is a change
*/
@@ -1312,6 +1341,19 @@
}
@Override
+ public void visitIcons(Consumer<Icon> visitor) {
+ if (mItems == null) {
+ RemoteCollectionItems cachedItems = mCollectionCache.getItemsForId(mIntentId);
+ if (cachedItems != null) {
+ cachedItems.visitIcons(visitor);
+ }
+ return;
+ }
+
+ mItems.visitIcons(visitor);
+ }
+
+ @Override
public boolean canWriteToProto() {
// Skip actions that do not contain items (intent only actions)
return mItems != null;
@@ -2385,7 +2427,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
ArrayList<Bitmap> mBitmaps;
SparseIntArray mBitmapHashes;
- int mBitmapMemory = -1;
+ long mBitmapMemory = -1;
public BitmapCache() {
mBitmaps = new ArrayList<>();
@@ -2449,7 +2491,7 @@
}
}
- public int getBitmapMemory() {
+ public long getBitmapMemory() {
if (mBitmapMemory < 0) {
mBitmapMemory = 0;
int count = mBitmaps.size();
@@ -2735,6 +2777,13 @@
// TODO(b/281044385): Should we do anything about type BUNDLE?
}
}
+
+ @Override
+ public void visitIcons(@NonNull Consumer<Icon> visitor) {
+ if (mType == ICON && getParameterValue(null) instanceof Icon icon) {
+ visitor.accept(icon);
+ }
+ }
}
/** Class for the reflection actions. */
@@ -4139,6 +4188,11 @@
}
@Override
+ public void visitIcons(@NonNull Consumer<Icon> visitor) {
+ mNestedViews.visitIcons(visitor);
+ }
+
+ @Override
public boolean canWriteToProto() {
return true;
}
@@ -6392,15 +6446,43 @@
}
/**
- * Returns an estimate of the bitmap heap memory usage for this RemoteViews.
+ * Returns an estimate of the bitmap heap memory usage by setBitmap and setImageViewBitmap in
+ * this RemoteViews.
+ *
+ * @hide
*/
- /** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public int estimateMemoryUsage() {
+ public long estimateMemoryUsage() {
return mBitmapCache.getBitmapMemory();
}
/**
+ * Returns an estimate of bitmap heap memory usage by setIcon and setImageViewIcon in this
+ * RemoteViews. Note that this function will count duplicate Icons in its estimate.
+ *
+ * @hide
+ */
+ public long estimateIconMemoryUsage() {
+ AtomicLong total = new AtomicLong(0);
+ visitIcons(icon -> {
+ if (icon.getType() == Icon.TYPE_BITMAP || icon.getType() == Icon.TYPE_ADAPTIVE_BITMAP) {
+ total.addAndGet(icon.getBitmap().getAllocationByteCount());
+ }
+ });
+ return total.get();
+ }
+
+ /**
+ * Returns an estimate of the bitmap heap memory usage for all Icon and Bitmap actions in this
+ * RemoteViews.
+ *
+ * @hide
+ */
+ public long estimateTotalBitmapMemoryUsage() {
+ return estimateMemoryUsage() + estimateIconMemoryUsage();
+ }
+
+ /**
* Add an action to be executed on the remote side when apply is called.
*
* @param a The action to add
@@ -9768,6 +9850,15 @@
view.visitUris(visitor);
}
}
+
+ /**
+ * See {@link RemoteViews#visitIcons(Consumer)}.
+ */
+ private void visitIcons(@NonNull Consumer<Icon> visitor) {
+ for (RemoteViews view : mViews) {
+ view.visitIcons(visitor);
+ }
+ }
}
/**
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index 222088e..51d488f 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -593,3 +593,10 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "enable_non_default_display_split"
+ namespace: "lse_desktop_experience"
+ description: "Enables split screen on non default displays"
+ bug: "384999213"
+}
diff --git a/core/proto/android/service/appwidget.proto b/core/proto/android/service/appwidget.proto
index fb90719..5dc90e0 100644
--- a/core/proto/android/service/appwidget.proto
+++ b/core/proto/android/service/appwidget.proto
@@ -39,6 +39,7 @@
optional int32 maxWidth = 8;
optional int32 maxHeight = 9;
optional bool restoreCompleted = 10;
+ optional int32 views_bitmap_memory = 11;
}
// represents a set of widget previews for a particular provider
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
index f9d449c..4ad6708 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
@@ -191,7 +191,7 @@
.fuzzFractions()
.mapNotNull{ FontScaleConverterFactory.forScale(it) }
.flatMap{ table ->
- generateSequenceOfFractions(-2000f..2000f, step = 0.1f)
+ generateSequenceOfFractions(-20f..100f, step = 0.1f)
.fuzzFractions()
.map{ Pair(table, it) }
}
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
index ee8d428..f87b699 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
@@ -224,7 +224,7 @@
}
@Override
- void internalFlush(int reason) {
+ void flush(int reason) {
throw new UnsupportedOperationException("should not have been called");
}
diff --git a/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java
index a1d7f87..b42bcee 100644
--- a/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/MainContentCaptureSessionTest.java
@@ -263,7 +263,7 @@
session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
session.mDirectServiceInterface = mMockContentCaptureDirectManager;
- session.internalFlush(REASON);
+ session.flush(REASON);
mTestableLooper.processAllMessages();
verifyZeroInteractions(mMockContentProtectionEventProcessor);
@@ -280,7 +280,7 @@
session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
session.mDirectServiceInterface = mMockContentCaptureDirectManager;
- session.internalFlush(REASON);
+ session.flush(REASON);
mTestableLooper.processAllMessages();
verifyZeroInteractions(mMockContentProtectionEventProcessor);
@@ -298,7 +298,7 @@
session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
session.mDirectServiceInterface = mMockContentCaptureDirectManager;
- session.internalFlush(REASON);
+ session.flush(REASON);
mTestableLooper.processAllMessages();
verifyZeroInteractions(mMockContentProtectionEventProcessor);
@@ -316,7 +316,7 @@
session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
session.mDirectServiceInterface = mMockContentCaptureDirectManager;
- session.internalFlush(REASON);
+ session.flush(REASON);
mTestableLooper.processAllMessages();
verifyZeroInteractions(mMockContentProtectionEventProcessor);
@@ -499,57 +499,6 @@
assertThat(session.mEventProcessQueue).hasSize(1);
}
- @Test
- public void notifyContentCaptureEvents_beforeSessionPerformStart() throws RemoteException {
- ContentCaptureOptions options =
- createOptions(
- /* enableContentCaptureReceiver= */ true,
- /* enableContentProtectionReceiver= */ true);
- MainContentCaptureSession session = createSession(options);
- session.mContentCaptureHandler = null;
- session.mDirectServiceInterface = null;
-
- notifyContentCaptureEvents(session);
- mTestableLooper.processAllMessages();
-
- assertThat(session.mEvents).isNull();
- assertThat(session.mEventProcessQueue).hasSize(7); // 5 view events + 2 view tree events
- }
-
- @Test
- public void notifyViewAppeared_beforeSessionPerformStart() throws RemoteException {
- ContentCaptureOptions options =
- createOptions(
- /* enableContentCaptureReceiver= */ true,
- /* enableContentProtectionReceiver= */ true);
- MainContentCaptureSession session = createSession(options);
- session.mContentCaptureHandler = null;
- session.mDirectServiceInterface = null;
-
- View view = prepareView(session);
- session.notifyViewAppeared(session.newViewStructure(view));
-
- assertThat(session.mEvents).isNull();
- assertThat(session.mEventProcessQueue).hasSize(1);
- }
-
- @Test
- public void flush_beforeSessionPerformStart() throws Exception {
- ContentCaptureOptions options =
- createOptions(
- /* enableContentCaptureReceiver= */ true,
- /* enableContentProtectionReceiver= */ true);
- MainContentCaptureSession session = createSession(options);
- session.mEvents = new ArrayList<>(Arrays.asList(EVENT));
- session.mContentCaptureHandler = null;
- session.mDirectServiceInterface = null;
-
- session.internalFlush(REASON);
-
- assertThat(session.mEvents).hasSize(1);
- assertThat(session.mEventProcessQueue).isEmpty();
- }
-
/** Simulates the regular content capture events sequence. */
private void notifyContentCaptureEvents(final MainContentCaptureSession session) {
final ArrayList<Object> events = new ArrayList<>(
@@ -612,8 +561,8 @@
sStrippedContext,
manager,
testHandler,
+ testHandler,
mMockSystemServerInterface);
- session.mContentCaptureHandler = testHandler;
session.mComponentName = COMPONENT_NAME;
return session;
}
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 2880ecf..8b0d315 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -36,6 +36,7 @@
import android.appwidget.AppWidgetHostView;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AsyncTask;
@@ -934,6 +935,136 @@
assertEquals(testText, replacedTextView.getText());
}
+ @Test
+ public void estimateMemoryUsage() {
+ Bitmap b1 = Bitmap.createBitmap(1024, 768, Bitmap.Config.ARGB_8888);
+ int b1Memory = b1.getAllocationByteCount();
+ Bitmap b2 = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888);
+ int b2Memory = b2.getAllocationByteCount();
+ Bitmap b3 = Bitmap.createBitmap(800, 600, Bitmap.Config.ARGB_8888);
+ int b3Memory = b3.getAllocationByteCount();
+
+ final RemoteViews rv = new RemoteViews(mPackage, R.layout.remote_views_test);
+ assertEquals(0, rv.estimateMemoryUsage());
+ assertEquals(0, rv.estimateIconMemoryUsage());
+ assertEquals(0, rv.estimateTotalBitmapMemoryUsage());
+
+ rv.setBitmap(R.id.view, "", b1);
+ rv.setImageViewBitmap(R.id.view, b1); // second instance of b1 is cached
+ rv.setBitmap(R.id.view, "", b2);
+ assertEquals(b1Memory + b2Memory, rv.estimateMemoryUsage());
+ assertEquals(0, rv.estimateIconMemoryUsage());
+ assertEquals(b1Memory + b2Memory, rv.estimateTotalBitmapMemoryUsage());
+
+ rv.setIcon(R.id.view, "", Icon.createWithBitmap(b2));
+ rv.setIcon(R.id.view, "", Icon.createWithBitmap(b3));
+ rv.setImageViewIcon(R.id.view, Icon.createWithBitmap(b3));
+ assertEquals(b1Memory + b2Memory, rv.estimateMemoryUsage());
+ assertEquals(b2Memory + (2 * b3Memory), rv.estimateIconMemoryUsage());
+ assertEquals(b1Memory + (2 * b2Memory) + (2 * b3Memory),
+ rv.estimateTotalBitmapMemoryUsage());
+ }
+
+ @Test
+ public void estimateMemoryUsage_landscapePortrait() {
+ Bitmap b1 = Bitmap.createBitmap(1024, 768, Bitmap.Config.ARGB_8888);
+ int b1Memory = b1.getAllocationByteCount();
+ Bitmap b2 = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888);
+ int b2Memory = b2.getAllocationByteCount();
+ Bitmap b3 = Bitmap.createBitmap(800, 600, Bitmap.Config.ARGB_8888);
+ int b3Memory = b3.getAllocationByteCount();
+ Bitmap b4 = Bitmap.createBitmap(320, 240, Bitmap.Config.ARGB_8888);
+ int b4Memory = b4.getAllocationByteCount();
+
+ // Landscape and portrait using same bitmaps get counted twice.
+ final RemoteViews rv = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv.setBitmap(R.id.view, "", b1);
+ rv.setIcon(R.id.view, "", Icon.createWithBitmap(b2));
+ RemoteViews landscapePortraitViews = new RemoteViews(rv, rv);
+ assertEquals(b1Memory, landscapePortraitViews.estimateMemoryUsage());
+ assertEquals(2 * b2Memory, landscapePortraitViews.estimateIconMemoryUsage());
+ assertEquals(b1Memory + (2 * b2Memory),
+ landscapePortraitViews.estimateTotalBitmapMemoryUsage());
+
+ final RemoteViews rv2 = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv.setBitmap(R.id.view, "", b3);
+ rv.setIcon(R.id.view, "", Icon.createWithBitmap(b4));
+ landscapePortraitViews = new RemoteViews(rv, rv2);
+ assertEquals(b1Memory + b3Memory, landscapePortraitViews.estimateMemoryUsage());
+ assertEquals(b2Memory + b4Memory, landscapePortraitViews.estimateIconMemoryUsage());
+ assertEquals(b1Memory + b2Memory + b3Memory + b4Memory,
+ landscapePortraitViews.estimateTotalBitmapMemoryUsage());
+ }
+
+ @Test
+ public void estimateMemoryUsage_sizedViews() {
+ Bitmap b1 = Bitmap.createBitmap(1024, 768, Bitmap.Config.ARGB_8888);
+ int b1Memory = b1.getAllocationByteCount();
+ Bitmap b2 = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888);
+ int b2Memory = b2.getAllocationByteCount();
+ Bitmap b3 = Bitmap.createBitmap(800, 600, Bitmap.Config.ARGB_8888);
+ int b3Memory = b3.getAllocationByteCount();
+ Bitmap b4 = Bitmap.createBitmap(320, 240, Bitmap.Config.ARGB_8888);
+ int b4Memory = b4.getAllocationByteCount();
+
+ // Sized views using same bitmaps do not get counted twice.
+ final RemoteViews rv = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv.setBitmap(R.id.view, "", b1);
+ rv.setIcon(R.id.view, "", Icon.createWithBitmap(b2));
+ RemoteViews sizedViews = new RemoteViews(
+ Map.of(new SizeF(0f, 0f), rv, new SizeF(1f, 1f), rv));
+ assertEquals(b1Memory, sizedViews.estimateMemoryUsage());
+ assertEquals(2 * b2Memory, sizedViews.estimateIconMemoryUsage());
+ assertEquals(b1Memory + (2 * b2Memory), sizedViews.estimateTotalBitmapMemoryUsage());
+
+ final RemoteViews rv2 = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv.setBitmap(R.id.view, "", b3);
+ rv.setIcon(R.id.view, "", Icon.createWithBitmap(b4));
+ sizedViews = new RemoteViews(Map.of(new SizeF(0f, 0f), rv, new SizeF(1f, 1f), rv2));
+ assertEquals(b1Memory + b3Memory, sizedViews.estimateMemoryUsage());
+ assertEquals(b2Memory + b4Memory, sizedViews.estimateIconMemoryUsage());
+ assertEquals(b1Memory + b2Memory + b3Memory + b4Memory,
+ sizedViews.estimateTotalBitmapMemoryUsage());
+ }
+
+ @Test
+ public void estimateMemoryUsage_nestedViews() {
+ Bitmap b1 = Bitmap.createBitmap(1024, 768, Bitmap.Config.ARGB_8888);
+ int b1Memory = b1.getAllocationByteCount();
+ Bitmap b2 = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888);
+ int b2Memory = b2.getAllocationByteCount();
+
+ final RemoteViews rv1 = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv1.setBitmap(R.id.view, "", b1);
+ final RemoteViews rv2 = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv2.setIcon(R.id.view, "", Icon.createWithBitmap(b2));
+ final RemoteViews rv = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv.addView(R.id.view, rv1);
+ rv.addView(R.id.view, rv2);
+ assertEquals(b1Memory, rv.estimateMemoryUsage());
+ assertEquals(b2Memory, rv.estimateIconMemoryUsage());
+ assertEquals(b1Memory + b2Memory, rv.estimateTotalBitmapMemoryUsage());
+ }
+
+ @Test
+ public void estimateMemoryUsage_remoteCollectionItems() {
+ Bitmap b1 = Bitmap.createBitmap(1024, 768, Bitmap.Config.ARGB_8888);
+ int b1Memory = b1.getAllocationByteCount();
+ Bitmap b2 = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888);
+ int b2Memory = b2.getAllocationByteCount();
+
+ final RemoteViews rv1 = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv1.setBitmap(R.id.view, "", b1);
+ final RemoteViews rv2 = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv2.setIcon(R.id.view, "", Icon.createWithBitmap(b2));
+ final RemoteViews rv = new RemoteViews(mPackage, R.layout.remote_views_test);
+ rv.setRemoteAdapter(R.id.view, new RemoteViews.RemoteCollectionItems.Builder().addItem(0L,
+ rv1).addItem(1L, rv2).build());
+ assertEquals(b1Memory, rv.estimateMemoryUsage());
+ assertEquals(b2Memory, rv.estimateIconMemoryUsage());
+ assertEquals(b1Memory + b2Memory, rv.estimateTotalBitmapMemoryUsage());
+ }
+
private static LayoutInflater.Factory2 createLayoutInflaterFactory(String viewTypeToReplace,
View replacementView) {
return new LayoutInflater.Factory2() {
diff --git a/libs/WindowManager/Shell/aconfig/multitasking.aconfig b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
index 0656446..13d0169 100644
--- a/libs/WindowManager/Shell/aconfig/multitasking.aconfig
+++ b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
@@ -177,10 +177,3 @@
description: "Factor task-view state tracking out of taskviewtransitions"
bug: "384976265"
}
-
-flag {
- name: "enable_non_default_display_split"
- namespace: "multitasking"
- description: "Enables split screen on non default displays"
- bug: "384999213"
-}
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 cd5c135..bd89f5c 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
@@ -394,11 +394,19 @@
* Returns the divider position as a fraction from 0 to 1.
*/
public float getDividerPositionAsFraction() {
- return Math.min(1f, Math.max(0f, mIsLeftRightSplit
- ? (float) ((getTopLeftBounds().right + getBottomRightBounds().left) / 2f)
- / getBottomRightBounds().right
- : (float) ((getTopLeftBounds().bottom + getBottomRightBounds().top) / 2f)
- / getBottomRightBounds().bottom));
+ if (Flags.enableFlexibleTwoAppSplit()) {
+ return Math.min(1f, Math.max(0f, mIsLeftRightSplit
+ ? (getTopLeftBounds().right + getBottomRightBounds().left) / 2f
+ / getDisplayWidth()
+ : (getTopLeftBounds().bottom + getBottomRightBounds().top) / 2f
+ / getDisplayHeight()));
+ } else {
+ return Math.min(1f, Math.max(0f, mIsLeftRightSplit
+ ? (float) ((getTopLeftBounds().right + getBottomRightBounds().left) / 2f)
+ / getBottomRightBounds().right
+ : (float) ((getTopLeftBounds().bottom + getBottomRightBounds().top) / 2f)
+ / getBottomRightBounds().bottom));
+ }
}
private void updateInvisibleRect() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java
index 2f93715..d735375 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTaskListener.java
@@ -133,7 +133,9 @@
taskInfo.topActivity, mPipTransitionState, mPictureInPictureParams, params);
setPictureInPictureParams(params);
float newAspectRatio = mPictureInPictureParams.getAspectRatioFloat();
- if (PipUtils.aspectRatioChanged(newAspectRatio, mPipBoundsState.getAspectRatio())) {
+ if (params.hasSetAspectRatio()
+ && mPipBoundsAlgorithm.isValidPictureInPictureAspectRatio(newAspectRatio)
+ && PipUtils.aspectRatioChanged(newAspectRatio, mPipBoundsState.getAspectRatio())) {
mPipTransitionState.setOnIdlePipTransitionStateRunnable(() -> {
onAspectRatioChanged(newAspectRatio);
});
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
index 03327bf..2299624 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
@@ -725,6 +725,12 @@
mPipTransitionState.getPipTaskToken());
mFinishCallback = finishCallback;
+ if (isPipClosing(info)) {
+ // If PiP is removed via a close (e.g. finishing of the activity), then
+ // clear out the PiP cache related to that activity component (e.g. reentry state).
+ mPipBoundsState.setLastPipComponentName(null /* lastPipComponentName */);
+ }
+
finishTransaction.setAlpha(pipChange.getLeash(), 0f);
if (mPendingRemoveWithFadeout) {
PipAlphaAnimator animator = new PipAlphaAnimator(mContext, pipChange.getLeash(),
@@ -952,13 +958,29 @@
boolean isPipMovedToBack = info.getType() == TRANSIT_TO_BACK
&& pipChange.getMode() == TRANSIT_TO_BACK;
- boolean isPipClosed = info.getType() == TRANSIT_CLOSE
- && pipChange.getMode() == TRANSIT_CLOSE;
// If PiP is dismissed by user (i.e. via dismiss button in PiP menu)
boolean isPipDismissed = info.getType() == TRANSIT_REMOVE_PIP
&& pipChange.getMode() == TRANSIT_TO_BACK;
// PiP is being removed if the pinned task is either moved to back, closed, or dismissed.
- return isPipMovedToBack || isPipClosed || isPipDismissed;
+ return isPipMovedToBack || isPipClosing(info) || isPipDismissed;
+ }
+
+ private boolean isPipClosing(@NonNull TransitionInfo info) {
+ if (mPipTransitionState.getPipTaskToken() == null) {
+ // PiP removal makes sense if enter-PiP has cached a valid pinned task token.
+ return false;
+ }
+ TransitionInfo.Change pipChange = info.getChange(mPipTransitionState.getPipTaskToken());
+ TransitionInfo.Change pipActivityChange = info.getChanges().stream().filter(change ->
+ change.getTaskInfo() == null && change.getParent() != null
+ && change.getParent() == mPipTransitionState.getPipTaskToken())
+ .findFirst().orElse(null);
+
+ boolean isPipTaskClosed = pipChange != null
+ && pipChange.getMode() == TRANSIT_CLOSE;
+ boolean isPipActivityClosed = pipActivityChange != null
+ && pipActivityChange.getMode() == TRANSIT_CLOSE;
+ return isPipTaskClosed || isPipActivityClosed;
}
private void prepareConfigAtEndActivity(@NonNull SurfaceControl.Transaction startTx,
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 722494c..2174017 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
@@ -109,6 +109,7 @@
import android.util.IntArray;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseIntArray;
import android.view.Choreographer;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
@@ -3012,11 +3013,18 @@
final int transitType = info.getType();
TransitionInfo.Change pipChange = null;
int closingSplitTaskId = -1;
- // This array tracks where we are sending stages (TO_BACK/TO_FRONT) in this transition.
- // TODO (b/349828130): Update for n apps (needs to handle different indices than 0/1).
- // Also make sure having multiple changes per stage (2+ tasks in one stage) is being
- // handled properly.
- int[] stageChanges = new int[2];
+ // This array tracks if we are sending stages TO_BACK/TO_FRONT in this transition.
+ // TODO (b/349828130): Also make sure having multiple changes per stage (2+ tasks in
+ // one stage) is being handled properly.
+ SparseIntArray stageChanges = new SparseIntArray();
+ if (enableFlexibleSplit()) {
+ mStageOrderOperator.getActiveStages()
+ .forEach(stage -> stageChanges.put(stage.getId(), -1));
+ } else {
+ stageChanges.put(STAGE_TYPE_MAIN, -1);
+ stageChanges.put(STAGE_TYPE_SIDE, -1);
+ }
+
for (int iC = 0; iC < info.getChanges().size(); ++iC) {
final TransitionInfo.Change change = info.getChanges().get(iC);
@@ -3090,14 +3098,12 @@
// we'll break split
closingSplitTaskId = taskId;
}
- if (transitType == WindowManager.TRANSIT_WAKE) {
- // Record which stages are receiving which changes
- if ((change.getMode() == TRANSIT_TO_BACK
- || change.getMode() == TRANSIT_TO_FRONT)
- && (stageOfTaskId == STAGE_TYPE_MAIN
- || stageOfTaskId == STAGE_TYPE_SIDE)) {
- stageChanges[stageOfTaskId] = change.getMode();
- }
+ // Record which stages are receiving which changes
+ if ((change.getMode() == TRANSIT_TO_BACK
+ || change.getMode() == TRANSIT_TO_FRONT)
+ && (stageOfTaskId == STAGE_TYPE_MAIN
+ || stageOfTaskId == STAGE_TYPE_SIDE)) {
+ stageChanges.put(getStageOfTask(taskId), change.getMode());
}
}
@@ -3126,8 +3132,16 @@
// If keyguard is active, check to see if we have all our stages showing. If one stage
// was moved but not the other (which can happen with SHOW_ABOVE_LOCKED apps), we should
// break split.
- if (mKeyguardActive && stageChanges[STAGE_TYPE_MAIN] != stageChanges[STAGE_TYPE_SIDE]) {
- dismissSplitKeepingLastActiveStage(EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
+ if (mKeyguardActive && stageChanges.size() > 0) {
+ int firstChangeMode = stageChanges.valueAt(0);
+ for (int i = 0; i < stageChanges.size(); i++) {
+ int changeMode = stageChanges.valueAt(i);
+ // Compare each changeMode to the first one. If any are different, break split.
+ if (changeMode != firstChangeMode) {
+ dismissSplitKeepingLastActiveStage(EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
+ break;
+ }
+ }
}
final ArraySet<StageTaskListener> dismissStages = record.getShouldDismissedStage();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java
index 89cb729..3923a1e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipTaskListenerTest.java
@@ -22,6 +22,7 @@
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.Mockito.when;
import static org.mockito.kotlin.MatchersKt.eq;
@@ -193,6 +194,12 @@
mMockPipTransitionState, mMockPipScheduler, mMockPipBoundsState,
mMockPipBoundsAlgorithm, mMockShellExecutor);
mPipTaskListener.addParamsChangedListener(mMockPipParamsChangedCallback);
+
+ // For this test case, any aspect ratio passed is considered within allowed range.
+ when(mMockPipBoundsAlgorithm
+ .isValidPictureInPictureAspectRatio(anyFloat()))
+ .thenReturn(true);
+
Rational aspectRatio = new Rational(4, 3);
when(mMockPipBoundsState.getAspectRatio()).thenReturn(aspectRatio.toFloat());
String action1 = "action1";
@@ -227,6 +234,29 @@
}
@Test
+ public void onTaskInfoChanged_nonValidAspectRatio_doesNotCallbackAspectRatioChanged() {
+ mPipTaskListener = new PipTaskListener(mMockContext, mMockShellTaskOrganizer,
+ mMockPipTransitionState, mMockPipScheduler, mMockPipBoundsState,
+ mMockPipBoundsAlgorithm, mMockShellExecutor);
+ mPipTaskListener.addParamsChangedListener(mMockPipParamsChangedCallback);
+
+ String action1 = "action1";
+ mPipTaskListener.onTaskInfoChanged(getTaskInfo(null, action1));
+ verify(mMockPipTransitionState, times(0))
+ .setOnIdlePipTransitionStateRunnable(any(Runnable.class));
+
+ // Define an invalid aspect ratio and try and update the params with it.
+ Rational aspectRatio = new Rational(100, 3);
+ when(mMockPipBoundsAlgorithm
+ .isValidPictureInPictureAspectRatio(eq(aspectRatio.floatValue())))
+ .thenReturn(false);
+
+ mPipTaskListener.onTaskInfoChanged(getTaskInfo(aspectRatio, action1));
+ verify(mMockPipTransitionState, times(0))
+ .setOnIdlePipTransitionStateRunnable(any(Runnable.class));
+ }
+
+ @Test
public void onPipTransitionStateChanged_scheduledBoundsChangeWithAspectRatioChange_schedule() {
mPipTaskListener = new PipTaskListener(mMockContext, mMockShellTaskOrganizer,
mMockPipTransitionState, mMockPipScheduler, mMockPipBoundsState,
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 8bc66a0..f308ce9 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -18,6 +18,7 @@
import static android.media.audio.Flags.FLAG_DOLBY_AC4_LEVEL4_ENCODING_API;
import static android.media.audio.Flags.FLAG_IAMF_DEFINITIONS_API;
+import static android.media.audio.Flags.FLAG_SONY_360RA_MPEGH_3D_FORMAT;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
@@ -718,8 +719,9 @@
* Same as 9.1.4 with the addition of left and right top side channels */
public static final int CHANNEL_OUT_9POINT1POINT6 = (CHANNEL_OUT_9POINT1POINT4
| CHANNEL_OUT_TOP_SIDE_LEFT | CHANNEL_OUT_TOP_SIDE_RIGHT);
- /** @hide */
- public static final int CHANNEL_OUT_13POINT_360RA = (
+ /** Output channel mask for 13.0 */
+ @FlaggedApi(FLAG_SONY_360RA_MPEGH_3D_FORMAT)
+ public static final int CHANNEL_OUT_13POINT0 = (
CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_FRONT_RIGHT |
CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT |
CHANNEL_OUT_TOP_FRONT_LEFT | CHANNEL_OUT_TOP_FRONT_CENTER |
@@ -915,7 +917,7 @@
case CHANNEL_OUT_9POINT1POINT6:
result.append("9.1.6");
break;
- case CHANNEL_OUT_13POINT_360RA:
+ case CHANNEL_OUT_13POINT0:
result.append("360RA 13ch");
break;
case CHANNEL_OUT_22POINT2:
diff --git a/media/java/android/media/audio/common/AidlConversion.java b/media/java/android/media/audio/common/AidlConversion.java
index 8521d1c..b831e4f 100644
--- a/media/java/android/media/audio/common/AidlConversion.java
+++ b/media/java/android/media/audio/common/AidlConversion.java
@@ -366,8 +366,8 @@
return AudioFormat.CHANNEL_OUT_9POINT1POINT4;
case AudioChannelLayout.LAYOUT_9POINT1POINT6:
return AudioFormat.CHANNEL_OUT_9POINT1POINT6;
- case AudioChannelLayout.LAYOUT_13POINT_360RA:
- return AudioFormat.CHANNEL_OUT_13POINT_360RA;
+ case AudioChannelLayout.LAYOUT_13POINT0:
+ return AudioFormat.CHANNEL_OUT_13POINT0;
case AudioChannelLayout.LAYOUT_22POINT2:
return AudioFormat.CHANNEL_OUT_22POINT2;
case AudioChannelLayout.LAYOUT_MONO_HAPTIC_A:
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
index 9300964..3f2e78c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
@@ -39,6 +39,8 @@
import androidx.test.filters.SmallTest
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -85,11 +87,13 @@
private lateinit var powerInteractor: PowerInteractor
private lateinit var transitionRepository: FakeKeyguardTransitionRepository
+ private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
@Before
fun setup() {
powerInteractor = kosmos.powerInteractor
transitionRepository = kosmos.fakeKeyguardTransitionRepositorySpy
+ bouncerRepository = kosmos.fakeKeyguardBouncerRepository
underTest = kosmos.fromAodTransitionInteractor
underTest.start()
@@ -304,6 +308,29 @@
}
@Test
+ fun testWakeAndUnlock_transitionsToGone_evenIfBouncerShows() =
+ testScope.runTest {
+ kosmos.fakeKeyguardRepository.setBiometricUnlockState(
+ BiometricUnlockMode.WAKE_AND_UNLOCK
+ )
+ runCurrent()
+ bouncerRepository.setPrimaryShow(true)
+ runCurrent()
+ powerInteractor.setAwakeForTest()
+ runCurrent()
+
+ // Waking up from wake and unlock should not start any transitions, we'll wait for the
+ // dismiss call.
+ assertThat(transitionRepository).noTransitionsStarted()
+
+ underTest.dismissAod()
+ advanceTimeBy(100) // account for debouncing
+
+ assertThat(transitionRepository)
+ .startedTransition(from = KeyguardState.AOD, to = KeyguardState.GONE)
+ }
+
+ @Test
fun testTransitionToOccluded_onWake() =
testScope.runTest {
kosmos.fakeKeyguardRepository.setKeyguardOccluded(true)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
index 555c717..93d1f59 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
@@ -78,6 +78,7 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -220,6 +221,7 @@
mock(),
{ configurationForwarder },
brightnessMirrorShowingInteractor,
+ UnconfinedTestDispatcher(),
)
controller.setupExpandedStatusBar()
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/TableLogBufferBase.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/TableLogBufferBase.kt
index 50b3f78..8a962f9 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/TableLogBufferBase.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/TableLogBufferBase.kt
@@ -25,34 +25,34 @@
*
* For Java overloading.
*/
- fun logChange(prefix: String, columnName: String, value: String?) {
+ fun logChange(prefix: String = "", columnName: String, value: String?) {
logChange(prefix, columnName, value, isInitial = false)
}
/** Logs a String? change. */
- fun logChange(prefix: String, columnName: String, value: String?, isInitial: Boolean)
+ fun logChange(prefix: String = "", columnName: String, value: String?, isInitial: Boolean)
/**
* Logs a Boolean change.
*
* For Java overloading.
*/
- fun logChange(prefix: String, columnName: String, value: Boolean) {
+ fun logChange(prefix: String = "", columnName: String, value: Boolean) {
logChange(prefix, columnName, value, isInitial = false)
}
/** Logs a Boolean change. */
- fun logChange(prefix: String, columnName: String, value: Boolean, isInitial: Boolean)
+ fun logChange(prefix: String = "", columnName: String, value: Boolean, isInitial: Boolean)
/**
* Logs an Int? change.
*
* For Java overloading.
*/
- fun logChange(prefix: String, columnName: String, value: Int?) {
+ fun logChange(prefix: String = "", columnName: String, value: Int?) {
logChange(prefix, columnName, value, isInitial = false)
}
/** Logs an Int? change. */
- fun logChange(prefix: String, columnName: String, value: Int?, isInitial: Boolean)
+ fun logChange(prefix: String = "", columnName: String, value: Int?, isInitial: Boolean)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
index 7174379..4ad04be 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
@@ -193,7 +193,10 @@
if (SceneContainerFlag.isEnabled) return
scope.launch("$TAG#listenForAodToPrimaryBouncer") {
keyguardInteractor.primaryBouncerShowing
- .filterRelevantKeyguardStateAnd { primaryBouncerShowing -> primaryBouncerShowing }
+ .filterRelevantKeyguardStateAnd { primaryBouncerShowing ->
+ !isWakeAndUnlock(keyguardInteractor.biometricUnlockState.value.mode) &&
+ primaryBouncerShowing
+ }
.collect { startTransitionTo(KeyguardState.PRIMARY_BOUNCER) }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt b/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt
index baa07c1..9fddbfb 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/Diffable.kt
@@ -65,7 +65,7 @@
*/
fun <T : Diffable<T>> Flow<T>.logDiffsForTable(
tableLogBuffer: TableLogBuffer,
- columnPrefix: String,
+ columnPrefix: String = "",
initialValue: T,
): Flow<T> {
// Fully log the initial value to the table.
@@ -87,7 +87,7 @@
/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
fun Flow<Boolean>.logDiffsForTable(
tableLogBuffer: TableLogBuffer,
- columnPrefix: String,
+ columnPrefix: String = "",
columnName: String,
initialValue: Boolean,
): Flow<Boolean> {
@@ -106,7 +106,7 @@
/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
fun Flow<Int>.logDiffsForTable(
tableLogBuffer: TableLogBuffer,
- columnPrefix: String,
+ columnPrefix: String = "",
columnName: String,
initialValue: Int,
): Flow<Int> {
@@ -125,7 +125,7 @@
/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
fun Flow<Int?>.logDiffsForTable(
tableLogBuffer: TableLogBuffer,
- columnPrefix: String,
+ columnPrefix: String = "",
columnName: String,
initialValue: Int?,
): Flow<Int?> {
@@ -144,7 +144,7 @@
/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
fun Flow<String?>.logDiffsForTable(
tableLogBuffer: TableLogBuffer,
- columnPrefix: String,
+ columnPrefix: String = "",
columnName: String,
initialValue: String?,
): Flow<String?> {
@@ -163,7 +163,7 @@
/** See [logDiffsForTable(TableLogBuffer, String, T)]. */
fun <T> Flow<List<T>>.logDiffsForTable(
tableLogBuffer: TableLogBuffer,
- columnPrefix: String,
+ columnPrefix: String = "",
columnName: String,
initialValue: List<T>,
): Flow<List<T>> {
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
index 89a599a..3d1623b 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -124,7 +124,7 @@
* the separator token for parsing, so it can't be present in any part of the column name.
*/
@Synchronized
- fun <T : Diffable<T>> logDiffs(columnPrefix: String, prevVal: T, newVal: T) {
+ fun <T : Diffable<T>> logDiffs(columnPrefix: String = "", prevVal: T, newVal: T) {
val row = tempRow
row.timestamp = systemClock.currentTimeMillis()
row.columnPrefix = columnPrefix
@@ -136,6 +136,7 @@
/**
* Logs change(s) to the buffer using [rowInitializer].
*
+ * @param columnPrefix see [logDiffs].
* @param rowInitializer a function that will be called immediately to store relevant data on
* the row.
* @param isInitial true if this change represents the starting value for a particular column
@@ -145,9 +146,9 @@
*/
@Synchronized
fun logChange(
- columnPrefix: String,
+ columnPrefix: String = "",
isInitial: Boolean = false,
- rowInitializer: (TableRowLogger) -> Unit
+ rowInitializer: (TableRowLogger) -> Unit,
) {
val row = tempRow
row.timestamp = systemClock.currentTimeMillis()
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index 255494f0..10a9fd2 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -45,6 +45,7 @@
import com.android.systemui.bouncer.ui.binder.BouncerViewBinder;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlagsClassic;
@@ -87,6 +88,8 @@
import com.android.systemui.window.ui.WindowRootViewBinder;
import com.android.systemui.window.ui.viewmodel.WindowRootViewModel;
+import kotlinx.coroutines.CoroutineDispatcher;
+import kotlinx.coroutines.ExperimentalCoroutinesApi;
import kotlinx.coroutines.flow.Flow;
import java.io.PrintWriter;
@@ -119,6 +122,7 @@
private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
private final AlternateBouncerInteractor mAlternateBouncerInteractor;
private final QuickSettingsController mQuickSettingsController;
+ private final CoroutineDispatcher mMainDispatcher;
private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
private final GlanceableHubContainerController
mGlanceableHubContainerController;
@@ -204,7 +208,8 @@
AlternateBouncerInteractor alternateBouncerInteractor,
BouncerViewBinder bouncerViewBinder,
@ShadeDisplayAware Provider<ConfigurationForwarder> configurationForwarder,
- BrightnessMirrorShowingInteractor brightnessMirrorShowingInteractor) {
+ BrightnessMirrorShowingInteractor brightnessMirrorShowingInteractor,
+ @Main CoroutineDispatcher mainDispatcher) {
mLockscreenShadeTransitionController = transitionController;
mFalsingCollector = falsingCollector;
mStatusBarStateController = statusBarStateController;
@@ -232,6 +237,7 @@
mPrimaryBouncerInteractor = primaryBouncerInteractor;
mAlternateBouncerInteractor = alternateBouncerInteractor;
mQuickSettingsController = quickSettingsController;
+ mMainDispatcher = mainDispatcher;
// This view is not part of the newly inflated expanded status bar.
mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container);
@@ -286,7 +292,7 @@
if (SceneContainerFlag.isEnabled()) return;
WindowRootViewBinder.INSTANCE.bind(mView, windowRootViewModelFactory, blurUtils,
- choreographer);
+ choreographer, mMainDispatcher);
}
private void bindBouncer(BouncerViewBinder bouncerViewBinder) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepository.kt
index 9f1395a..f82e681 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepository.kt
@@ -81,12 +81,7 @@
awaitClose { observer.isListening = false }
}
.distinctUntilChanged()
- .logDiffsForTable(
- logger,
- columnPrefix = "",
- columnName = "isAirplaneMode",
- initialValue = false,
- )
+ .logDiffsForTable(logger, columnName = "isAirplaneMode", initialValue = false)
.stateIn(
scope,
started = SharingStarted.WhileSubscribed(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
index bd18f4b..2cef54f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
@@ -59,7 +59,6 @@
.distinctUntilChanged()
.logDiffsForTable(
logger,
- columnPrefix = "",
columnName = "isAirplaneModeIconVisible",
initialValue = false,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt
index be3977e..410389a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt
@@ -64,9 +64,8 @@
_carrierId
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_CARRIER_ID,
- _carrierId.value,
+ initialValue = _carrierId.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _carrierId.value)
@@ -75,9 +74,8 @@
_inflateSignalStrength
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = "inflate",
- _inflateSignalStrength.value,
+ initialValue = _inflateSignalStrength.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _inflateSignalStrength.value)
@@ -89,9 +87,8 @@
_isEmergencyOnly
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_EMERGENCY,
- _isEmergencyOnly.value,
+ initialValue = _isEmergencyOnly.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _isEmergencyOnly.value)
@@ -100,9 +97,8 @@
_isRoaming
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_ROAMING,
- _isRoaming.value,
+ initialValue = _isRoaming.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _isRoaming.value)
@@ -111,9 +107,8 @@
_operatorAlphaShort
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_OPERATOR,
- _operatorAlphaShort.value,
+ initialValue = _operatorAlphaShort.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _operatorAlphaShort.value)
@@ -122,9 +117,8 @@
_isInService
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_IS_IN_SERVICE,
- _isInService.value,
+ initialValue = _isInService.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _isInService.value)
@@ -133,21 +127,15 @@
_isNonTerrestrial
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_IS_NTN,
- _isNonTerrestrial.value,
+ initialValue = _isNonTerrestrial.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _isNonTerrestrial.value)
private val _isGsm = MutableStateFlow(false)
override val isGsm =
_isGsm
- .logDiffsForTable(
- tableLogBuffer,
- columnPrefix = "",
- columnName = COL_IS_GSM,
- _isGsm.value,
- )
+ .logDiffsForTable(tableLogBuffer, columnName = COL_IS_GSM, initialValue = _isGsm.value)
.stateIn(scope, SharingStarted.WhileSubscribed(), _isGsm.value)
private val _cdmaLevel = MutableStateFlow(CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN)
@@ -155,9 +143,8 @@
_cdmaLevel
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_CDMA_LEVEL,
- _cdmaLevel.value,
+ initialValue = _cdmaLevel.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _cdmaLevel.value)
@@ -166,9 +153,8 @@
_primaryLevel
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_PRIMARY_LEVEL,
- _primaryLevel.value,
+ initialValue = _primaryLevel.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _primaryLevel.value)
@@ -177,23 +163,22 @@
_satelliteLevel
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_SATELLITE_LEVEL,
- _satelliteLevel.value,
+ initialValue = _satelliteLevel.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _satelliteLevel.value)
private val _dataConnectionState = MutableStateFlow(DataConnectionState.Disconnected)
override val dataConnectionState =
_dataConnectionState
- .logDiffsForTable(tableLogBuffer, columnPrefix = "", _dataConnectionState.value)
+ .logDiffsForTable(tableLogBuffer, initialValue = _dataConnectionState.value)
.stateIn(scope, SharingStarted.WhileSubscribed(), _dataConnectionState.value)
private val _dataActivityDirection =
MutableStateFlow(DataActivityModel(hasActivityIn = false, hasActivityOut = false))
override val dataActivityDirection =
_dataActivityDirection
- .logDiffsForTable(tableLogBuffer, columnPrefix = "", _dataActivityDirection.value)
+ .logDiffsForTable(tableLogBuffer, initialValue = _dataActivityDirection.value)
.stateIn(scope, SharingStarted.WhileSubscribed(), _dataActivityDirection.value)
private val _carrierNetworkChangeActive = MutableStateFlow(false)
@@ -201,9 +186,8 @@
_carrierNetworkChangeActive
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_CARRIER_NETWORK_CHANGE,
- _carrierNetworkChangeActive.value,
+ initialValue = _carrierNetworkChangeActive.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), _carrierNetworkChangeActive.value)
@@ -211,7 +195,7 @@
MutableStateFlow(ResolvedNetworkType.UnknownNetworkType)
override val resolvedNetworkType =
_resolvedNetworkType
- .logDiffsForTable(tableLogBuffer, columnPrefix = "", _resolvedNetworkType.value)
+ .logDiffsForTable(tableLogBuffer, initialValue = _resolvedNetworkType.value)
.stateIn(scope, SharingStarted.WhileSubscribed(), _resolvedNetworkType.value)
override val numberOfLevels =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
index 21a3410..5094bc7e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
@@ -73,7 +73,6 @@
_isCarrierMerged
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = "isCarrierMerged",
initialValue = startingIsCarrierMerged,
)
@@ -128,9 +127,8 @@
.flatMapLatest { it.isEmergencyOnly }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_EMERGENCY,
- activeRepo.value.isEmergencyOnly.value,
+ initialValue = activeRepo.value.isEmergencyOnly.value,
)
.stateIn(
scope,
@@ -143,9 +141,8 @@
.flatMapLatest { it.isRoaming }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_ROAMING,
- activeRepo.value.isRoaming.value,
+ initialValue = activeRepo.value.isRoaming.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isRoaming.value)
@@ -154,9 +151,8 @@
.flatMapLatest { it.operatorAlphaShort }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_OPERATOR,
- activeRepo.value.operatorAlphaShort.value,
+ initialValue = activeRepo.value.operatorAlphaShort.value,
)
.stateIn(
scope,
@@ -169,9 +165,8 @@
.flatMapLatest { it.isInService }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_IS_IN_SERVICE,
- activeRepo.value.isInService.value,
+ initialValue = activeRepo.value.isInService.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isInService.value)
@@ -180,9 +175,8 @@
.flatMapLatest { it.isNonTerrestrial }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_IS_NTN,
- activeRepo.value.isNonTerrestrial.value,
+ initialValue = activeRepo.value.isNonTerrestrial.value,
)
.stateIn(
scope,
@@ -195,9 +189,8 @@
.flatMapLatest { it.isGsm }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_IS_GSM,
- activeRepo.value.isGsm.value,
+ initialValue = activeRepo.value.isGsm.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isGsm.value)
@@ -206,9 +199,8 @@
.flatMapLatest { it.cdmaLevel }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_CDMA_LEVEL,
- activeRepo.value.cdmaLevel.value,
+ initialValue = activeRepo.value.cdmaLevel.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.cdmaLevel.value)
@@ -217,9 +209,8 @@
.flatMapLatest { it.primaryLevel }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_PRIMARY_LEVEL,
- activeRepo.value.primaryLevel.value,
+ initialValue = activeRepo.value.primaryLevel.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.primaryLevel.value)
@@ -228,9 +219,8 @@
.flatMapLatest { it.satelliteLevel }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_SATELLITE_LEVEL,
- activeRepo.value.satelliteLevel.value,
+ initialValue = activeRepo.value.satelliteLevel.value,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.satelliteLevel.value)
@@ -239,8 +229,7 @@
.flatMapLatest { it.dataConnectionState }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
- activeRepo.value.dataConnectionState.value,
+ initialValue = activeRepo.value.dataConnectionState.value,
)
.stateIn(
scope,
@@ -253,8 +242,7 @@
.flatMapLatest { it.dataActivityDirection }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
- activeRepo.value.dataActivityDirection.value,
+ initialValue = activeRepo.value.dataActivityDirection.value,
)
.stateIn(
scope,
@@ -267,9 +255,8 @@
.flatMapLatest { it.carrierNetworkChangeActive }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = COL_CARRIER_NETWORK_CHANGE,
- activeRepo.value.carrierNetworkChangeActive.value,
+ initialValue = activeRepo.value.carrierNetworkChangeActive.value,
)
.stateIn(
scope,
@@ -282,8 +269,7 @@
.flatMapLatest { it.resolvedNetworkType }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
- activeRepo.value.resolvedNetworkType.value,
+ initialValue = activeRepo.value.resolvedNetworkType.value,
)
.stateIn(
scope,
@@ -296,7 +282,6 @@
.flatMapLatest { it.dataEnabled }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = "dataEnabled",
initialValue = activeRepo.value.dataEnabled.value,
)
@@ -307,7 +292,6 @@
.flatMapLatest { it.inflateSignalStrength }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = "inflate",
initialValue = activeRepo.value.inflateSignalStrength.value,
)
@@ -322,7 +306,6 @@
.flatMapLatest { it.allowNetworkSliceIndicator }
.logDiffsForTable(
tableLogBuffer,
- columnPrefix = "",
columnName = "allowSlice",
initialValue = activeRepo.value.allowNetworkSliceIndicator.value,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index 6337110..d336903 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -380,7 +380,6 @@
.distinctUntilChanged()
.logDiffsForTable(
tableLogger,
- columnPrefix = "",
columnName = "defaultConnectionIsValidated",
initialValue = false,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
index 36de2c1..a1f7a81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
@@ -238,7 +238,6 @@
.distinctUntilChanged()
.logDiffsForTable(
tableLogBuffer = tableLogBuffer,
- columnPrefix = "",
initialValue = DefaultIcon(defaultMobileIconGroup.value),
)
.stateIn(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
index be9d8f7..171e4f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
@@ -191,7 +191,6 @@
.distinctUntilChanged()
.logDiffsForTable(
iconInteractor.tableLogBuffer,
- columnPrefix = "",
columnName = "visible",
initialValue = false,
)
@@ -249,7 +248,6 @@
.distinctUntilChanged()
.logDiffsForTable(
iconInteractor.tableLogBuffer,
- columnPrefix = "",
columnName = "showNetworkTypeIcon",
initialValue = false,
)
@@ -293,7 +291,6 @@
iconInteractor.isRoaming
.logDiffsForTable(
iconInteractor.tableLogBuffer,
- columnPrefix = "",
columnName = "roaming",
initialValue = false,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
index 88b4802..569e02c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
@@ -63,12 +63,7 @@
flowOf(false)
}
.distinctUntilChanged()
- .logDiffsForTable(
- tableLog,
- columnPrefix = "",
- columnName = COL_ALLOWED,
- initialValue = false,
- )
+ .logDiffsForTable(tableLog, columnName = COL_ALLOWED, initialValue = false)
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
/** See [SatelliteConnectionState] for relevant states */
@@ -80,11 +75,7 @@
flowOf(SatelliteConnectionState.Off)
}
.distinctUntilChanged()
- .logDiffsForTable(
- tableLog,
- columnPrefix = "",
- initialValue = SatelliteConnectionState.Off,
- )
+ .logDiffsForTable(tableLog, initialValue = SatelliteConnectionState.Off)
.stateIn(scope, SharingStarted.WhileSubscribed(), SatelliteConnectionState.Off)
/** 0-4 description of the connection strength */
@@ -95,7 +86,7 @@
flowOf(0)
}
.distinctUntilChanged()
- .logDiffsForTable(tableLog, columnPrefix = "", columnName = COL_LEVEL, initialValue = 0)
+ .logDiffsForTable(tableLog, columnName = COL_LEVEL, initialValue = 0)
.stateIn(scope, SharingStarted.WhileSubscribed(), 0)
val isSatelliteProvisioned = repo.isSatelliteProvisioned
@@ -119,12 +110,7 @@
isOosAndNotEmergencyAndNotSatellite.all { it }
}
.distinctUntilChanged()
- .logDiffsForTable(
- tableLog,
- columnPrefix = "",
- columnName = COL_ALL_OOS,
- initialValue = true,
- )
+ .logDiffsForTable(tableLog, columnName = COL_ALL_OOS, initialValue = true)
/** When all connections are considered OOS, satellite connectivity is potentially valid */
val areAllConnectionsOutOfService =
@@ -152,12 +138,7 @@
flowOf(false)
}
.distinctUntilChanged()
- .logDiffsForTable(
- tableLog,
- columnPrefix = "",
- columnName = COL_FULL_OOS,
- initialValue = true,
- )
+ .logDiffsForTable(tableLog, columnName = COL_FULL_OOS, initialValue = true)
.stateIn(scope, SharingStarted.WhileSubscribed(), true)
/** True if any known mobile network is currently using a non terrestrial network */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
index 5acedf1..a59d95f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
@@ -195,7 +195,6 @@
.distinctUntilChanged()
.logDiffsForTable(
tableLogBuffer = tableLogger,
- columnPrefix = "",
columnName = COL_LOCK_TO_OCCLUDED,
initialValue = false,
)
@@ -228,7 +227,6 @@
.distinctUntilChanged()
.logDiffsForTable(
tableLogBuffer = tableLogger,
- columnPrefix = "",
columnName = COL_ALLOWED_BY_SCENE,
initialValue = false,
)
@@ -248,7 +246,6 @@
}
.logDiffsForTable(
tableLogBuffer = tableLogger,
- columnPrefix = "",
columnName = COL_NOTIF_LIGHTS_OUT,
initialValue = false,
)
@@ -306,7 +303,6 @@
.distinctUntilChanged()
.logDiffsForTable(
tableLogBuffer = tableLogger,
- columnPrefix = "",
columnName = COL_VISIBLE,
initialValue = false,
)
@@ -350,7 +346,6 @@
.distinctUntilChanged()
.logDiffsForTable(
tableLogBuffer = tableLogger,
- columnPrefix = "",
columnName = COL_SHOW_OPERATOR_NAME,
initialValue = false,
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index 115de28..f9bba9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -300,19 +300,14 @@
wifiPickerTrackerInfo
.map { it.state == WifiManager.WIFI_STATE_ENABLED }
.distinctUntilChanged()
- .logDiffsForTable(
- tableLogger,
- columnPrefix = "",
- columnName = COL_NAME_IS_ENABLED,
- initialValue = false,
- )
+ .logDiffsForTable(tableLogger, columnName = COL_NAME_IS_ENABLED, initialValue = false)
.stateIn(scope, SharingStarted.Eagerly, false)
override val wifiNetwork: StateFlow<WifiNetworkModel> =
wifiPickerTrackerInfo
.map { it.primaryNetwork }
.distinctUntilChanged()
- .logDiffsForTable(tableLogger, columnPrefix = "", initialValue = WIFI_NETWORK_DEFAULT)
+ .logDiffsForTable(tableLogger, initialValue = WIFI_NETWORK_DEFAULT)
.stateIn(scope, SharingStarted.Eagerly, WIFI_NETWORK_DEFAULT)
override val secondaryNetworks: StateFlow<List<WifiNetworkModel>> =
@@ -321,7 +316,6 @@
.distinctUntilChanged()
.logDiffsForTable(
tableLogger,
- columnPrefix = "",
columnName = "secondaryNetworks",
initialValue = emptyList(),
)
@@ -400,12 +394,7 @@
wifiPickerTrackerInfo
.map { it.isDefault }
.distinctUntilChanged()
- .logDiffsForTable(
- tableLogger,
- columnPrefix = "",
- columnName = COL_NAME_IS_DEFAULT,
- initialValue = false,
- )
+ .logDiffsForTable(tableLogger, columnName = COL_NAME_IS_DEFAULT, initialValue = false)
.stateIn(scope, SharingStarted.Eagerly, false)
override val wifiActivity: StateFlow<DataActivityModel> =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
index f9556d2..986068b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
@@ -89,7 +89,7 @@
else -> WifiIcon.Hidden
}
}
- .logDiffsForTable(wifiTableLogBuffer, columnPrefix = "", initialValue = WifiIcon.Hidden)
+ .logDiffsForTable(wifiTableLogBuffer, initialValue = WifiIcon.Hidden)
.stateIn(
scope,
started = SharingStarted.WhileSubscribed(),
diff --git a/packages/SystemUI/src/com/android/systemui/window/ui/WindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/window/ui/WindowRootViewBinder.kt
index 7f4bfb0..e09a74c 100644
--- a/packages/SystemUI/src/com/android/systemui/window/ui/WindowRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/window/ui/WindowRootViewBinder.kt
@@ -26,6 +26,7 @@
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.statusbar.BlurUtils
import com.android.systemui.window.ui.viewmodel.WindowRootViewModel
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
@@ -42,11 +43,12 @@
viewModelFactory: WindowRootViewModel.Factory,
blurUtils: BlurUtils?,
choreographer: Choreographer?,
+ mainDispatcher: CoroutineDispatcher,
) {
if (!Flags.bouncerUiRevamp() && !Flags.glanceableHubBlurredBackground()) return
if (blurUtils == null || choreographer == null) return
- view.repeatWhenAttached {
+ view.repeatWhenAttached(mainDispatcher) {
Log.d(TAG, "Binding root view")
var frameCallbackPendingExecution: FrameCallback? = null
view.viewModel(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
index b5eb904..676d8fa0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
@@ -235,6 +235,7 @@
modifyNotification(context).also {
it.setSmallIcon(android.R.drawable.ic_media_pause)
it.setStyle(MediaStyle().apply { setMediaSession(session.sessionToken) })
+ it.setContentIntent(getNewPendingIntent())
}
build()
}
@@ -2156,6 +2157,28 @@
verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY))
}
+ @Test
+ @EnableFlags(Flags.FLAG_MEDIA_CONTROLS_POSTS_OPTIMIZATION)
+ fun postDifferentIntentNotifications_CallsListeners() {
+ addNotificationAndLoad()
+ reset(listener)
+ mediaNotification =
+ mediaNotification.also { it.notification.contentIntent = getNewPendingIntent() }
+ mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+
+ testScope.assertRunAllReady(foreground = 1, background = 1)
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(KEY),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false),
+ )
+ verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY))
+ }
+
private fun TestScope.assertRunAllReady(foreground: Int = 0, background: Int = 0) {
runCurrent()
if (Flags.mediaLoadMetadataViaMediaDataLoader()) {
@@ -2235,4 +2258,14 @@
backgroundExecutor.runAllReady()
foregroundExecutor.runAllReady()
}
+
+ private fun getNewPendingIntent(): PendingIntent {
+ val intent = Intent().setAction(null)
+ return PendingIntent.getBroadcast(
+ mContext,
+ 1,
+ intent,
+ PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE,
+ )
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
index 042d30e..496b319 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
@@ -251,6 +251,7 @@
verify(mediaTimeoutListener).stateCallback = capture(stateCallbackCaptor)
verify(mediaTimeoutListener).sessionCallback = capture(sessionCallbackCaptor)
session = MediaSession(context, "MediaDataProcessorTestSession")
+
mediaNotification =
SbnBuilder().run {
setUser(UserHandle(USER_ID))
@@ -258,6 +259,7 @@
modifyNotification(context).also {
it.setSmallIcon(android.R.drawable.ic_media_pause)
it.setStyle(MediaStyle().apply { setMediaSession(session.sessionToken) })
+ it.setContentIntent(getNewPendingIntent())
}
build()
}
@@ -2250,6 +2252,33 @@
verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY))
}
+ @Test
+ @EnableFlags(Flags.FLAG_MEDIA_CONTROLS_POSTS_OPTIMIZATION)
+ fun postDifferentIntentNotifications_CallsListeners() {
+ whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
+ whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
+
+ mediaDataProcessor.addInternalListener(mediaDataFilter)
+ mediaDataFilter.mediaDataProcessor = mediaDataProcessor
+ addNotificationAndLoad()
+ reset(listener)
+ mediaNotification =
+ mediaNotification.also { it.notification.contentIntent = getNewPendingIntent() }
+ mediaDataProcessor.onNotificationAdded(KEY, mediaNotification)
+
+ testScope.assertRunAllReady(foreground = 1, background = 1)
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(KEY),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false),
+ )
+ verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY))
+ }
+
private fun TestScope.assertRunAllReady(foreground: Int = 0, background: Int = 0) {
runCurrent()
if (Flags.mediaLoadMetadataViaMediaDataLoader()) {
@@ -2329,4 +2358,14 @@
runCurrent()
advanceUntilIdle()
}
+
+ private fun getNewPendingIntent(): PendingIntent {
+ val intent = Intent().setAction(null)
+ return PendingIntent.getBroadcast(
+ mContext,
+ 1,
+ intent,
+ PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE,
+ )
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index 70450d2..49d6909 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -254,6 +254,7 @@
mock(BouncerViewBinder::class.java),
{ mock(ConfigurationForwarder::class.java) },
brightnessMirrorShowingInteractor,
+ kosmos.testDispatcher,
)
underTest.setupExpandedStatusBar()
underTest.setDragDownHelper(dragDownHelper)
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 8ef44ad..aef1c08 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1095,6 +1095,10 @@
proto.write(WidgetProto.MAX_HEIGHT,
widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, 0));
}
+ if (widget.views != null) {
+ proto.write(WidgetProto.VIEWS_BITMAP_MEMORY,
+ widget.views.estimateTotalBitmapMemoryUsage());
+ }
proto.end(token);
}
@@ -2846,7 +2850,7 @@
// For a full update we replace the RemoteViews completely.
widget.views = views;
}
- int memoryUsage;
+ long memoryUsage;
if ((UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) &&
(widget.views != null) &&
((memoryUsage = widget.views.estimateMemoryUsage()) > mMaxWidgetBitmapMemory)) {
@@ -3503,6 +3507,8 @@
}
if (widget.views != null) {
pw.print(" views="); pw.println(widget.views);
+ pw.print(" views_bitmap_memory=");
+ pw.println(widget.views.estimateTotalBitmapMemoryUsage());
}
}
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index 2d802b2..b6768c9 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -38,7 +38,6 @@
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.ComponentInfoInternal;
-import android.hardware.biometrics.Flags;
import android.hardware.biometrics.IAuthService;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.IBiometricService;
@@ -399,12 +398,6 @@
final long identity = Binder.clearCallingIdentity();
try {
- // We can't do this above because we need the READ_DEVICE_CONFIG permission, which
- // the calling user may not possess.
- if (!Flags.lastAuthenticationTime()) {
- throw new UnsupportedOperationException();
- }
-
return mBiometricService.getLastAuthenticationTime(userId, authenticators);
} finally {
Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 15b1f22..a5058dd 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -44,7 +44,6 @@
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricStateListener;
-import android.hardware.biometrics.Flags;
import android.hardware.biometrics.IBiometricAuthenticator;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.IBiometricSensorReceiver;
@@ -906,10 +905,6 @@
int userId, @Authenticators.Types int authenticators) {
super.getLastAuthenticationTime_enforcePermission();
- if (!Flags.lastAuthenticationTime()) {
- throw new UnsupportedOperationException();
- }
-
Slogf.d(TAG, "getLastAuthenticationTime(userId=%d, authenticators=0x%x)",
userId, authenticators);
diff --git a/services/core/java/com/android/server/media/quality/MediaQualityService.java b/services/core/java/com/android/server/media/quality/MediaQualityService.java
index f6c94a7..d23a863 100644
--- a/services/core/java/com/android/server/media/quality/MediaQualityService.java
+++ b/services/core/java/com/android/server/media/quality/MediaQualityService.java
@@ -73,6 +73,7 @@
import android.util.Slog;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.server.SystemService;
import com.android.server.utils.Slogf;
@@ -122,6 +123,13 @@
private SharedPreferences mPictureProfileSharedPreference;
private SharedPreferences mSoundProfileSharedPreference;
+ // A global lock for picture profile objects.
+ private final Object mPictureProfileLock = new Object();
+ // A global lock for sound profile objects.
+ private final Object mSoundProfileLock = new Object();
+ // A global lock for ambient backlight objects.
+ private final Object mAmbientBacklightLock = new Object();
+
public MediaQualityService(Context context) {
super(context);
mContext = context;
@@ -254,6 +262,7 @@
// TODO: Add additional APIs. b/373951081
private final class BinderService extends IMediaQualityManager.Stub {
+ @GuardedBy("mPictureProfileLock")
@Override
public PictureProfile createPictureProfile(PictureProfile pp, UserHandle user) {
if ((pp.getPackageName() != null && !pp.getPackageName().isEmpty()
@@ -263,24 +272,27 @@
Binder.getCallingUid(), Binder.getCallingPid());
}
- SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
+ synchronized (mPictureProfileLock) {
+ SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
- ContentValues values = getContentValues(null,
- pp.getProfileType(),
- pp.getName(),
- pp.getPackageName() == null || pp.getPackageName().isEmpty()
- ? getPackageOfCallingUid() : pp.getPackageName(),
- pp.getInputId(),
- pp.getParameters());
+ ContentValues values = getContentValues(null,
+ pp.getProfileType(),
+ pp.getName(),
+ pp.getPackageName() == null || pp.getPackageName().isEmpty()
+ ? getPackageOfCallingUid() : pp.getPackageName(),
+ pp.getInputId(),
+ pp.getParameters());
- // id is auto-generated by SQLite upon successful insertion of row
- Long id = db.insert(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
- null, values);
- populateTempIdMap(mPictureProfileTempIdMap, id);
- String value = mPictureProfileTempIdMap.getValue(id);
- pp.setProfileId(value);
- notifyOnPictureProfileAdded(value, pp, Binder.getCallingUid(), Binder.getCallingPid());
- return pp;
+ // id is auto-generated by SQLite upon successful insertion of row
+ Long id = db.insert(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
+ null, values);
+ populateTempIdMap(mPictureProfileTempIdMap, id);
+ String value = mPictureProfileTempIdMap.getValue(id);
+ pp.setProfileId(value);
+ notifyOnPictureProfileAdded(value, pp, Binder.getCallingUid(),
+ Binder.getCallingPid());
+ return pp;
+ }
}
private void notifyHalOnPictureProfileChange(Long dbId, PersistableBundle params) {
@@ -307,6 +319,7 @@
return toReturn;
}
+ @GuardedBy("mPictureProfileLock")
@Override
public void updatePictureProfile(String id, PictureProfile pp, UserHandle user) {
Long dbId = mPictureProfileTempIdMap.getKey(id);
@@ -315,12 +328,13 @@
Binder.getCallingUid(), Binder.getCallingPid());
}
- ContentValues values = getContentValues(dbId,
- pp.getProfileType(),
- pp.getName(),
- pp.getPackageName(),
- pp.getInputId(),
- pp.getParameters());
+ synchronized (mPictureProfileLock) {
+ ContentValues values = getContentValues(dbId,
+ pp.getProfileType(),
+ pp.getName(),
+ pp.getPackageName(),
+ pp.getInputId(),
+ pp.getParameters());
SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
db.replace(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
@@ -328,6 +342,7 @@
notifyOnPictureProfileUpdated(mPictureProfileTempIdMap.getValue(dbId),
getPictureProfile(dbId), Binder.getCallingUid(), Binder.getCallingPid());
notifyHalOnPictureProfileChange(dbId, pp.getParameters());
+ }
}
private boolean hasPermissionToUpdatePictureProfile(Long dbId, PictureProfile toUpdate) {
@@ -338,30 +353,33 @@
&& fromDb.getName().equals(getPackageOfCallingUid());
}
+ @GuardedBy("mPictureProfileLock")
@Override
public void removePictureProfile(String id, UserHandle user) {
- Long dbId = mPictureProfileTempIdMap.getKey(id);
+ synchronized (mPictureProfileLock) {
+ Long dbId = mPictureProfileTempIdMap.getKey(id);
- PictureProfile toDelete = getPictureProfile(dbId);
- if (!hasPermissionToRemovePictureProfile(toDelete)) {
- notifyOnPictureProfileError(id, PictureProfile.ERROR_NO_PERMISSION,
- Binder.getCallingUid(), Binder.getCallingPid());
- }
-
- if (dbId != null) {
- SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
- String selection = BaseParameters.PARAMETER_ID + " = ?";
- String[] selectionArgs = {Long.toString(dbId)};
- int result = db.delete(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME, selection,
- selectionArgs);
- if (result == 0) {
- notifyOnPictureProfileError(id, PictureProfile.ERROR_INVALID_ARGUMENT,
+ PictureProfile toDelete = getPictureProfile(dbId);
+ if (!hasPermissionToRemovePictureProfile(toDelete)) {
+ notifyOnPictureProfileError(id, PictureProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
}
- notifyOnPictureProfileRemoved(mPictureProfileTempIdMap.getValue(dbId), toDelete,
- Binder.getCallingUid(), Binder.getCallingPid());
- mPictureProfileTempIdMap.remove(dbId);
- notifyHalOnPictureProfileChange(dbId, null);
+
+ if (dbId != null) {
+ SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
+ String selection = BaseParameters.PARAMETER_ID + " = ?";
+ String[] selectionArgs = {Long.toString(dbId)};
+ int result = db.delete(mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
+ selection, selectionArgs);
+ if (result == 0) {
+ notifyOnPictureProfileError(id, PictureProfile.ERROR_INVALID_ARGUMENT,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ }
+ notifyOnPictureProfileRemoved(mPictureProfileTempIdMap.getValue(dbId), toDelete,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ mPictureProfileTempIdMap.remove(dbId);
+ notifyHalOnPictureProfileChange(dbId, null);
+ }
}
}
@@ -372,6 +390,7 @@
return false;
}
+ @GuardedBy("mPictureProfileLock")
@Override
public PictureProfile getPictureProfile(int type, String name, Bundle options,
UserHandle user) {
@@ -382,23 +401,27 @@
+ BaseParameters.PARAMETER_PACKAGE + " = ?";
String[] selectionArguments = {Integer.toString(type), name, getPackageOfCallingUid()};
- try (
- Cursor cursor = getCursorAfterQuerying(
- mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
- getMediaProfileColumns(includeParams), selection, selectionArguments)
- ) {
- int count = cursor.getCount();
- if (count == 0) {
- return null;
+ synchronized (mPictureProfileLock) {
+ try (
+ Cursor cursor = getCursorAfterQuerying(
+ mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME,
+ getMediaProfileColumns(includeParams), selection,
+ selectionArguments)
+ ) {
+ int count = cursor.getCount();
+ if (count == 0) {
+ return null;
+ }
+ if (count > 1) {
+ Log.wtf(TAG, TextUtils.formatSimple(String.valueOf(Locale.US), "%d "
+ + "entries found for type=%d and name=%s in %s. Should"
+ + " only ever be 0 or 1.", count, type, name,
+ mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME));
+ return null;
+ }
+ cursor.moveToFirst();
+ return convertCursorToPictureProfileWithTempId(cursor);
}
- if (count > 1) {
- Log.wtf(TAG, String.format(Locale.US, "%d entries found for type=%d and name=%s"
- + " in %s. Should only ever be 0 or 1.", count, type, name,
- mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME));
- return null;
- }
- cursor.moveToFirst();
- return convertCursorToPictureProfileWithTempId(cursor);
}
}
@@ -416,9 +439,9 @@
return null;
}
if (count > 1) {
- Log.wtf(TAG, String.format(Locale.US, "%d entries found for id=%d"
- + " in %s. Should only ever be 0 or 1.", count, dbId,
- mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME));
+ Log.wtf(TAG, TextUtils.formatSimple(String.valueOf(Locale.US), "%d entries "
+ + "found for id=%d in %s. Should only ever be 0 or 1.",
+ count, dbId, mMediaQualityDbHelper.PICTURE_QUALITY_TABLE_NAME));
return null;
}
cursor.moveToFirst();
@@ -426,6 +449,7 @@
}
}
+ @GuardedBy("mPictureProfileLock")
@Override
public List<PictureProfile> getPictureProfilesByPackage(
String packageName, Bundle options, UserHandle user) {
@@ -434,14 +458,17 @@
Binder.getCallingUid(), Binder.getCallingPid());
}
- boolean includeParams =
- options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
- String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
- String[] selectionArguments = {packageName};
- return getPictureProfilesBasedOnConditions(getMediaProfileColumns(includeParams),
- selection, selectionArguments);
+ synchronized (mPictureProfileLock) {
+ boolean includeParams =
+ options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
+ String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
+ String[] selectionArguments = {packageName};
+ return getPictureProfilesBasedOnConditions(getMediaProfileColumns(includeParams),
+ selection, selectionArguments);
+ }
}
+ @GuardedBy("mPictureProfileLock")
@Override
public List<PictureProfile> getAvailablePictureProfiles(Bundle options, UserHandle user) {
String packageName = getPackageOfCallingUid();
@@ -451,6 +478,7 @@
return new ArrayList<>();
}
+ @GuardedBy("mPictureProfileLock")
@Override
public boolean setDefaultPictureProfile(String profileId, UserHandle user) {
if (!hasGlobalPictureQualityServicePermission()) {
@@ -810,6 +838,7 @@
return (PictureParameter[]) pictureParams.toArray();
}
+ @GuardedBy("mPictureProfileLock")
@Override
public List<String> getPictureProfilePackageNames(UserHandle user) {
if (!hasGlobalPictureQualityServicePermission()) {
@@ -817,42 +846,51 @@
Binder.getCallingUid(), Binder.getCallingPid());
}
String [] column = {BaseParameters.PARAMETER_PACKAGE};
- List<PictureProfile> pictureProfiles = getPictureProfilesBasedOnConditions(column,
- null, null);
- return pictureProfiles.stream()
- .map(PictureProfile::getPackageName)
- .distinct()
- .collect(Collectors.toList());
+ synchronized (mPictureProfileLock) {
+ List<PictureProfile> pictureProfiles = getPictureProfilesBasedOnConditions(column,
+ null, null);
+ return pictureProfiles.stream()
+ .map(PictureProfile::getPackageName)
+ .distinct()
+ .collect(Collectors.toList());
+ }
}
+ @GuardedBy("mPictureProfileLock")
@Override
public List<PictureProfileHandle> getPictureProfileHandle(String[] ids, UserHandle user) {
List<PictureProfileHandle> toReturn = new ArrayList<>();
- for (String id : ids) {
- Long key = mPictureProfileTempIdMap.getKey(id);
- if (key != null) {
- toReturn.add(new PictureProfileHandle(key));
- } else {
- toReturn.add(null);
+ synchronized (mPictureProfileLock) {
+ for (String id : ids) {
+ Long key = mPictureProfileTempIdMap.getKey(id);
+ if (key != null) {
+ toReturn.add(new PictureProfileHandle(key));
+ } else {
+ toReturn.add(null);
+ }
}
}
return toReturn;
}
+ @GuardedBy("mSoundProfileLock")
@Override
public List<SoundProfileHandle> getSoundProfileHandle(String[] ids, UserHandle user) {
List<SoundProfileHandle> toReturn = new ArrayList<>();
- for (String id : ids) {
- Long key = mSoundProfileTempIdMap.getKey(id);
- if (key != null) {
- toReturn.add(new SoundProfileHandle(key));
- } else {
- toReturn.add(null);
+ synchronized (mSoundProfileLock) {
+ for (String id : ids) {
+ Long key = mSoundProfileTempIdMap.getKey(id);
+ if (key != null) {
+ toReturn.add(new SoundProfileHandle(key));
+ } else {
+ toReturn.add(null);
+ }
}
}
return toReturn;
}
+ @GuardedBy("mSoundProfileLock")
@Override
public SoundProfile createSoundProfile(SoundProfile sp, UserHandle user) {
if ((sp.getPackageName() != null && !sp.getPackageName().isEmpty()
@@ -861,24 +899,28 @@
notifyOnSoundProfileError(null, SoundProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
}
- SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
- ContentValues values = getContentValues(null,
- sp.getProfileType(),
- sp.getName(),
- sp.getPackageName() == null || sp.getPackageName().isEmpty()
- ? getPackageOfCallingUid() : sp.getPackageName(),
- sp.getInputId(),
- sp.getParameters());
+ synchronized (mSoundProfileLock) {
+ SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
- // id is auto-generated by SQLite upon successful insertion of row
- Long id = db.insert(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
- null, values);
- populateTempIdMap(mSoundProfileTempIdMap, id);
- String value = mSoundProfileTempIdMap.getValue(id);
- sp.setProfileId(value);
- notifyOnSoundProfileAdded(value, sp, Binder.getCallingUid(), Binder.getCallingPid());
- return sp;
+ ContentValues values = getContentValues(null,
+ sp.getProfileType(),
+ sp.getName(),
+ sp.getPackageName() == null || sp.getPackageName().isEmpty()
+ ? getPackageOfCallingUid() : sp.getPackageName(),
+ sp.getInputId(),
+ sp.getParameters());
+
+ // id is auto-generated by SQLite upon successful insertion of row
+ Long id = db.insert(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
+ null, values);
+ populateTempIdMap(mSoundProfileTempIdMap, id);
+ String value = mSoundProfileTempIdMap.getValue(id);
+ sp.setProfileId(value);
+ notifyOnSoundProfileAdded(value, sp, Binder.getCallingUid(),
+ Binder.getCallingPid());
+ return sp;
+ }
}
private void notifyHalOnSoundProfileChange(Long dbId, PersistableBundle params) {
@@ -903,6 +945,7 @@
return toReturn;
}
+ @GuardedBy("mSoundProfileLock")
@Override
public void updateSoundProfile(String id, SoundProfile sp, UserHandle user) {
Long dbId = mSoundProfileTempIdMap.getKey(id);
@@ -911,18 +954,20 @@
Binder.getCallingUid(), Binder.getCallingPid());
}
- ContentValues values = getContentValues(dbId,
- sp.getProfileType(),
- sp.getName(),
- sp.getPackageName(),
- sp.getInputId(),
- sp.getParameters());
+ synchronized (mSoundProfileLock) {
+ ContentValues values = getContentValues(dbId,
+ sp.getProfileType(),
+ sp.getName(),
+ sp.getPackageName(),
+ sp.getInputId(),
+ sp.getParameters());
SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
db.replace(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME, null, values);
notifyOnSoundProfileUpdated(mSoundProfileTempIdMap.getValue(dbId),
getSoundProfile(dbId), Binder.getCallingUid(), Binder.getCallingPid());
notifyHalOnSoundProfileChange(dbId, sp.getParameters());
+ }
}
private boolean hasPermissionToUpdateSoundProfile(Long dbId, SoundProfile sp) {
@@ -933,29 +978,32 @@
&& fromDb.getName().equals(getPackageOfCallingUid());
}
+ @GuardedBy("mSoundProfileLock")
@Override
public void removeSoundProfile(String id, UserHandle user) {
- Long dbId = mSoundProfileTempIdMap.getKey(id);
- SoundProfile toDelete = getSoundProfile(dbId);
- if (!hasPermissionToRemoveSoundProfile(toDelete)) {
- notifyOnSoundProfileError(id, SoundProfile.ERROR_NO_PERMISSION,
- Binder.getCallingUid(), Binder.getCallingPid());
- }
-
- if (dbId != null) {
- SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
- String selection = BaseParameters.PARAMETER_ID + " = ?";
- String[] selectionArgs = {Long.toString(dbId)};
- int result = db.delete(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME, selection,
- selectionArgs);
- if (result == 0) {
- notifyOnSoundProfileError(id, SoundProfile.ERROR_INVALID_ARGUMENT,
+ synchronized (mSoundProfileLock) {
+ Long dbId = mSoundProfileTempIdMap.getKey(id);
+ SoundProfile toDelete = getSoundProfile(dbId);
+ if (!hasPermissionToRemoveSoundProfile(toDelete)) {
+ notifyOnSoundProfileError(id, SoundProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
}
- notifyOnSoundProfileRemoved(mSoundProfileTempIdMap.getValue(dbId), toDelete,
- Binder.getCallingUid(), Binder.getCallingPid());
- mSoundProfileTempIdMap.remove(dbId);
- notifyHalOnSoundProfileChange(dbId, null);
+ if (dbId != null) {
+ SQLiteDatabase db = mMediaQualityDbHelper.getWritableDatabase();
+ String selection = BaseParameters.PARAMETER_ID + " = ?";
+ String[] selectionArgs = {Long.toString(dbId)};
+ int result = db.delete(mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
+ selection,
+ selectionArgs);
+ if (result == 0) {
+ notifyOnSoundProfileError(id, SoundProfile.ERROR_INVALID_ARGUMENT,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ }
+ notifyOnSoundProfileRemoved(mSoundProfileTempIdMap.getValue(dbId), toDelete,
+ Binder.getCallingUid(), Binder.getCallingPid());
+ mSoundProfileTempIdMap.remove(dbId);
+ notifyHalOnSoundProfileChange(dbId, null);
+ }
}
}
@@ -966,6 +1014,7 @@
return false;
}
+ @GuardedBy("mSoundProfileLock")
@Override
public SoundProfile getSoundProfile(int type, String name, Bundle options,
UserHandle user) {
@@ -976,23 +1025,27 @@
+ BaseParameters.PARAMETER_PACKAGE + " = ?";
String[] selectionArguments = {String.valueOf(type), name, getPackageOfCallingUid()};
- try (
- Cursor cursor = getCursorAfterQuerying(
- mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
- getMediaProfileColumns(includeParams), selection, selectionArguments)
- ) {
- int count = cursor.getCount();
- if (count == 0) {
- return null;
+ synchronized (mSoundProfileLock) {
+ try (
+ Cursor cursor = getCursorAfterQuerying(
+ mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME,
+ getMediaProfileColumns(includeParams), selection,
+ selectionArguments)
+ ) {
+ int count = cursor.getCount();
+ if (count == 0) {
+ return null;
+ }
+ if (count > 1) {
+ Log.wtf(TAG, TextUtils.formatSimple(String.valueOf(Locale.US), "%d "
+ + "entries found for name=%s in %s. Should only ever "
+ + "be 0 or 1.", String.valueOf(count), name,
+ mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME));
+ return null;
+ }
+ cursor.moveToFirst();
+ return convertCursorToSoundProfileWithTempId(cursor);
}
- if (count > 1) {
- Log.wtf(TAG, String.format(Locale.US, "%d entries found for name=%s"
- + " in %s. Should only ever be 0 or 1.", count, name,
- mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME));
- return null;
- }
- cursor.moveToFirst();
- return convertCursorToSoundProfileWithTempId(cursor);
}
}
@@ -1010,9 +1063,9 @@
return null;
}
if (count > 1) {
- Log.wtf(TAG, String.format(Locale.US, "%d entries found for id=%s "
- + "in %s. Should only ever be 0 or 1.", count, dbId,
- mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME));
+ Log.wtf(TAG, TextUtils.formatSimple(String.valueOf(Locale.US), "%d entries "
+ + "found for id=%s in %s. Should only ever be 0 or 1.", count,
+ dbId, mMediaQualityDbHelper.SOUND_QUALITY_TABLE_NAME));
return null;
}
cursor.moveToFirst();
@@ -1020,6 +1073,7 @@
}
}
+ @GuardedBy("mSoundProfileLock")
@Override
public List<SoundProfile> getSoundProfilesByPackage(
String packageName, Bundle options, UserHandle user) {
@@ -1028,14 +1082,17 @@
Binder.getCallingUid(), Binder.getCallingPid());
}
- boolean includeParams =
- options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
- String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
- String[] selectionArguments = {packageName};
- return getSoundProfilesBasedOnConditions(getMediaProfileColumns(includeParams),
- selection, selectionArguments);
+ synchronized (mSoundProfileLock) {
+ boolean includeParams =
+ options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false);
+ String selection = BaseParameters.PARAMETER_PACKAGE + " = ?";
+ String[] selectionArguments = {packageName};
+ return getSoundProfilesBasedOnConditions(getMediaProfileColumns(includeParams),
+ selection, selectionArguments);
+ }
}
+ @GuardedBy("mSoundProfileLock")
@Override
public List<SoundProfile> getAvailableSoundProfiles(Bundle options, UserHandle user) {
String packageName = getPackageOfCallingUid();
@@ -1045,6 +1102,7 @@
return new ArrayList<>();
}
+ @GuardedBy("mSoundProfileLock")
@Override
public boolean setDefaultSoundProfile(String profileId, UserHandle user) {
if (!hasGlobalSoundQualityServicePermission()) {
@@ -1161,6 +1219,7 @@
return (SoundParameter[]) soundParams.toArray();
}
+ @GuardedBy("mSoundProfileLock")
@Override
public List<String> getSoundProfilePackageNames(UserHandle user) {
if (!hasGlobalSoundQualityServicePermission()) {
@@ -1168,12 +1227,15 @@
Binder.getCallingUid(), Binder.getCallingPid());
}
String [] column = {BaseParameters.PARAMETER_NAME};
- List<SoundProfile> soundProfiles = getSoundProfilesBasedOnConditions(column,
- null, null);
- return soundProfiles.stream()
- .map(SoundProfile::getPackageName)
- .distinct()
- .collect(Collectors.toList());
+
+ synchronized (mSoundProfileLock) {
+ List<SoundProfile> soundProfiles = getSoundProfilesBasedOnConditions(column,
+ null, null);
+ return soundProfiles.stream()
+ .map(SoundProfile::getPackageName)
+ .distinct()
+ .collect(Collectors.toList());
+ }
}
private String getPackageOfCallingUid() {
@@ -1539,6 +1601,7 @@
userState.mSoundProfileCallbacks.finishBroadcast();
}
+ //TODO: need lock here?
@Override
public void registerPictureProfileCallback(final IPictureProfileCallback callback) {
int callingPid = Binder.getCallingPid();
@@ -1549,6 +1612,7 @@
Pair.create(callingPid, callingUid));
}
+ //TODO: need lock here?
@Override
public void registerSoundProfileCallback(final ISoundProfileCallback callback) {
int callingPid = Binder.getCallingPid();
@@ -1586,6 +1650,7 @@
}
}
+ @GuardedBy("mAmbientBacklightLock")
@Override
public void setAmbientBacklightSettings(
AmbientBacklightSettings settings, UserHandle user) {
@@ -1624,6 +1689,7 @@
}
}
+ @GuardedBy("mAmbientBacklightLock")
@Override
public void setAmbientBacklightEnabled(boolean enabled, UserHandle user) {
if (DEBUG) {
@@ -1643,12 +1709,14 @@
}
}
+ //TODO: do I need a lock here?
@Override
public List<ParameterCapability> getParameterCapabilities(
List<String> names, UserHandle user) {
return new ArrayList<>();
}
+ @GuardedBy("mPictureProfileLock")
@Override
public List<String> getPictureProfileAllowList(UserHandle user) {
if (!hasGlobalPictureQualityServicePermission()) {
@@ -1663,6 +1731,7 @@
return new ArrayList<>();
}
+ @GuardedBy("mPictureProfileLock")
@Override
public void setPictureProfileAllowList(List<String> packages, UserHandle user) {
if (!hasGlobalPictureQualityServicePermission()) {
@@ -1674,6 +1743,7 @@
editor.commit();
}
+ @GuardedBy("mSoundProfileLock")
@Override
public List<String> getSoundProfileAllowList(UserHandle user) {
if (!hasGlobalSoundQualityServicePermission()) {
@@ -1688,6 +1758,7 @@
return new ArrayList<>();
}
+ @GuardedBy("mSoundProfileLock")
@Override
public void setSoundProfileAllowList(List<String> packages, UserHandle user) {
if (!hasGlobalSoundQualityServicePermission()) {
@@ -1704,70 +1775,81 @@
return false;
}
+ @GuardedBy("mPictureProfileLock")
@Override
public void setAutoPictureQualityEnabled(boolean enabled, UserHandle user) {
if (!hasGlobalPictureQualityServicePermission()) {
notifyOnPictureProfileError(null, PictureProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
}
-
- try {
- if (mMediaQuality != null) {
- if (mMediaQuality.isAutoPqSupported()) {
- mMediaQuality.setAutoPqEnabled(enabled);
+ synchronized (mPictureProfileLock) {
+ try {
+ if (mMediaQuality != null) {
+ if (mMediaQuality.isAutoPqSupported()) {
+ mMediaQuality.setAutoPqEnabled(enabled);
+ }
}
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to set auto picture quality", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to set auto picture quality", e);
}
}
+ @GuardedBy("mPictureProfileLock")
@Override
public boolean isAutoPictureQualityEnabled(UserHandle user) {
- try {
- if (mMediaQuality != null) {
- if (mMediaQuality.isAutoPqSupported()) {
- return mMediaQuality.getAutoPqEnabled();
+ synchronized (mPictureProfileLock) {
+ try {
+ if (mMediaQuality != null) {
+ if (mMediaQuality.isAutoPqSupported()) {
+ return mMediaQuality.getAutoPqEnabled();
+ }
}
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to get auto picture quality", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to get auto picture quality", e);
+ return false;
}
- return false;
}
+ @GuardedBy("mPictureProfileLock")
@Override
public void setSuperResolutionEnabled(boolean enabled, UserHandle user) {
if (!hasGlobalPictureQualityServicePermission()) {
notifyOnPictureProfileError(null, PictureProfile.ERROR_NO_PERMISSION,
Binder.getCallingUid(), Binder.getCallingPid());
}
-
- try {
- if (mMediaQuality != null) {
- if (mMediaQuality.isAutoSrSupported()) {
- mMediaQuality.setAutoSrEnabled(enabled);
+ synchronized (mPictureProfileLock) {
+ try {
+ if (mMediaQuality != null) {
+ if (mMediaQuality.isAutoSrSupported()) {
+ mMediaQuality.setAutoSrEnabled(enabled);
+ }
}
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to set super resolution", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to set super resolution", e);
}
}
+ @GuardedBy("mPictureProfileLock")
@Override
public boolean isSuperResolutionEnabled(UserHandle user) {
- try {
- if (mMediaQuality != null) {
- if (mMediaQuality.isAutoSrSupported()) {
- return mMediaQuality.getAutoSrEnabled();
+ synchronized (mPictureProfileLock) {
+ try {
+ if (mMediaQuality != null) {
+ if (mMediaQuality.isAutoSrSupported()) {
+ return mMediaQuality.getAutoSrEnabled();
+ }
}
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to get super resolution", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to get super resolution", e);
+ return false;
}
- return false;
}
+ @GuardedBy("mSoundProfileLock")
@Override
public void setAutoSoundQualityEnabled(boolean enabled, UserHandle user) {
if (!hasGlobalSoundQualityServicePermission()) {
@@ -1775,31 +1857,37 @@
Binder.getCallingUid(), Binder.getCallingPid());
}
- try {
- if (mMediaQuality != null) {
- if (mMediaQuality.isAutoAqSupported()) {
- mMediaQuality.setAutoAqEnabled(enabled);
+ synchronized (mSoundProfileLock) {
+ try {
+ if (mMediaQuality != null) {
+ if (mMediaQuality.isAutoAqSupported()) {
+ mMediaQuality.setAutoAqEnabled(enabled);
+ }
}
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to set auto sound quality", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to set auto sound quality", e);
}
}
+ @GuardedBy("mSoundProfileLock")
@Override
public boolean isAutoSoundQualityEnabled(UserHandle user) {
- try {
- if (mMediaQuality != null) {
- if (mMediaQuality.isAutoAqSupported()) {
- return mMediaQuality.getAutoAqEnabled();
+ synchronized (mSoundProfileLock) {
+ try {
+ if (mMediaQuality != null) {
+ if (mMediaQuality.isAutoAqSupported()) {
+ return mMediaQuality.getAutoAqEnabled();
+ }
}
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to get auto sound quality", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to get auto sound quality", e);
+ return false;
}
- return false;
}
+ @GuardedBy("mAmbientBacklightLock")
@Override
public boolean isAmbientBacklightEnabled(UserHandle user) {
return false;
@@ -1853,6 +1941,7 @@
}
}
+ //TODO: used by both picture and sound. can i add both locks?
private UserState getOrCreateUserStateLocked(int userId) {
UserState userState = getUserStateLocked(userId);
if (userState == null) {
@@ -1862,6 +1951,7 @@
return userState;
}
+ //TODO: used by both picture and sound. can i add both locks?
private UserState getUserStateLocked(int userId) {
return mUserStates.get(userId);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 2305f1b..a16b122 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -8898,7 +8898,7 @@
if (contentView == null) {
return false;
}
- final int contentViewSize = contentView.estimateMemoryUsage();
+ final long contentViewSize = contentView.estimateMemoryUsage();
if (contentViewSize > mWarnRemoteViewsSizeBytes
&& contentViewSize < mStripRemoteViewsSizeBytes) {
Slog.w(TAG, "RemoteViews too large on pkg: " + pkg + " tag: " + tag + " id: " + id
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index b8b49f3e..f9758fc 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -26,13 +26,13 @@
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
import android.util.Pair;
import android.util.Slog;
import android.util.Xml;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.CollectionUtils;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
@@ -49,7 +49,6 @@
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
-import java.util.stream.Stream;
/**
* Data structure representing the current state of all overlay packages in the
@@ -358,26 +357,29 @@
}
void dump(@NonNull final PrintWriter p, @NonNull DumpState dumpState) {
- // select items to display
- Stream<SettingsItem> items = mItems.stream();
- if (dumpState.getUserId() != UserHandle.USER_ALL) {
- items = items.filter(item -> item.mUserId == dumpState.getUserId());
- }
- if (dumpState.getPackageName() != null) {
- items = items.filter(item -> item.mOverlay.getPackageName()
- .equals(dumpState.getPackageName()));
- }
- if (dumpState.getOverlayName() != null) {
- items = items.filter(item -> item.mOverlay.getOverlayName()
- .equals(dumpState.getOverlayName()));
- }
+ final int userId = dumpState.getUserId();
+ final String packageName = dumpState.getPackageName();
+ final String overlayName = dumpState.getOverlayName();
+ final String field = dumpState.getField();
+ final var pw = new IndentingPrintWriter(p, " ");
- // display items
- final IndentingPrintWriter pw = new IndentingPrintWriter(p, " ");
- if (dumpState.getField() != null) {
- items.forEach(item -> dumpSettingsItemField(pw, item, dumpState.getField()));
- } else {
- items.forEach(item -> dumpSettingsItem(pw, item));
+ for (int i = 0; i < mItems.size(); i++) {
+ final var item = mItems.get(i);
+ if (userId != UserHandle.USER_ALL && userId != item.mUserId) {
+ continue;
+ }
+ if (packageName != null && !packageName.equals(item.mOverlay.getPackageName())) {
+ continue;
+ }
+ if (overlayName != null && !overlayName.equals(item.mOverlay.getOverlayName())) {
+ continue;
+ }
+
+ if (field != null) {
+ dumpSettingsItemField(pw, item, field);
+ } else {
+ dumpSettingsItem(pw, item);
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
index 605fed0..c7efa31 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
@@ -45,7 +45,6 @@
import android.content.res.Resources;
import android.hardware.biometrics.AuthenticationStateListener;
import android.hardware.biometrics.BiometricManager;
-import android.hardware.biometrics.Flags;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.IBiometricService;
import android.hardware.biometrics.IBiometricServiceReceiver;
@@ -504,23 +503,9 @@
eq(callback));
}
- @Test(expected = UnsupportedOperationException.class)
- public void testGetLastAuthenticationTime_flaggedOff_throwsUnsupportedOperationException()
- throws Exception {
- mSetFlagsRule.disableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME);
- setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */);
-
- mAuthService = new AuthService(mContext, mInjector);
- mAuthService.onStart();
-
- mAuthService.mImpl.getLastAuthenticationTime(0,
- BiometricManager.Authenticators.BIOMETRIC_STRONG);
- }
-
@Test
- public void testGetLastAuthenticationTime_flaggedOn_callsBiometricService()
+ public void testGetLastAuthenticationTime_callsBiometricService()
throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME);
setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */);
mAuthService = new AuthService(mContext, mInjector);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index acca4cc..9918a9a 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -2014,20 +2014,9 @@
verifyNoMoreInteractions(callback);
}
- @Test(expected = UnsupportedOperationException.class)
- public void testGetLastAuthenticationTime_flagOff_throwsUnsupportedOperationException()
- throws RemoteException {
- mSetFlagsRule.disableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME);
-
- mBiometricService = new BiometricService(mContext, mInjector, mBiometricHandlerProvider);
- mBiometricService.mImpl.getLastAuthenticationTime(0, Authenticators.BIOMETRIC_STRONG);
- }
-
@Test
- public void testGetLastAuthenticationTime_flagOn_callsKeystoreAuthorization()
+ public void testGetLastAuthenticationTime_callsKeystoreAuthorization()
throws RemoteException {
- mSetFlagsRule.enableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME);
-
final int[] hardwareAuthenticators = new int[] {
HardwareAuthenticatorType.PASSWORD,
HardwareAuthenticatorType.FINGERPRINT
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 0cd809c..c1c8211 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -12007,7 +12007,8 @@
@Test
@DisableFlags(android.app.Flags.FLAG_REMOVE_REMOTE_VIEWS)
public void testRemoveLargeRemoteViews() throws Exception {
- int removeSize = mContext.getResources().getInteger(
+ // Cast to long to mock RemoteViews.estimateMemoryUsage which returns long.
+ long removeSize = mContext.getResources().getInteger(
com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
RemoteViews rv = mock(RemoteViews.class);
diff --git a/tests/testables/src/android/testing/TestableLooper.java b/tests/testables/src/android/testing/TestableLooper.java
index 7d07d42..3ee6dc4 100644
--- a/tests/testables/src/android/testing/TestableLooper.java
+++ b/tests/testables/src/android/testing/TestableLooper.java
@@ -16,13 +16,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.Instrumentation;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
-import android.os.SystemClock;
import android.os.TestLooperManager;
import android.util.ArrayMap;
@@ -34,7 +32,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import java.util.LinkedList;
+import java.lang.reflect.Field;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -58,6 +56,9 @@
* catch crashes.
*/
public static final boolean HOLD_MAIN_THREAD = false;
+ private static final Field MESSAGE_QUEUE_MESSAGES_FIELD;
+ private static final Field MESSAGE_NEXT_FIELD;
+ private static final Field MESSAGE_WHEN_FIELD;
private Looper mLooper;
private MessageQueue mQueue;
@@ -66,6 +67,19 @@
private Handler mHandler;
private TestLooperManager mQueueWrapper;
+ static {
+ try {
+ MESSAGE_QUEUE_MESSAGES_FIELD = MessageQueue.class.getDeclaredField("mMessages");
+ MESSAGE_QUEUE_MESSAGES_FIELD.setAccessible(true);
+ MESSAGE_NEXT_FIELD = Message.class.getDeclaredField("next");
+ MESSAGE_NEXT_FIELD.setAccessible(true);
+ MESSAGE_WHEN_FIELD = Message.class.getDeclaredField("when");
+ MESSAGE_WHEN_FIELD.setAccessible(true);
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException("Failed to initialize TestableLooper", e);
+ }
+ }
+
public TestableLooper(Looper l) throws Exception {
this(acquireLooperManager(l), l);
}
@@ -208,17 +222,29 @@
}
public void moveTimeForward(long milliSeconds) {
- long futureWhen = SystemClock.uptimeMillis() + milliSeconds;
- // Find messages in the queue enqueued within the future time, and execute them now.
- while (true) {
- Long peekWhen = mQueueWrapper.peekWhen();
- if (peekWhen == null || peekWhen > futureWhen) {
- break;
+ try {
+ Message msg = getMessageLinkedList();
+ while (msg != null) {
+ long updatedWhen = msg.getWhen() - milliSeconds;
+ if (updatedWhen < 0) {
+ updatedWhen = 0;
+ }
+ MESSAGE_WHEN_FIELD.set(msg, updatedWhen);
+ msg = (Message) MESSAGE_NEXT_FIELD.get(msg);
}
- Message message = mQueueWrapper.poll();
- if (message != null) {
- mQueueWrapper.execute(message);
- }
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Access failed in TestableLooper: set - Message.when", e);
+ }
+ }
+
+ private Message getMessageLinkedList() {
+ try {
+ MessageQueue queue = mLooper.getQueue();
+ return (Message) MESSAGE_QUEUE_MESSAGES_FIELD.get(queue);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(
+ "Access failed in TestableLooper: get - MessageQueue.mMessages",
+ e);
}
}