Merge "Fix LightBarController's dark/light logic for the Navigation Bar" into udc-dev
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index b732da2..19a4766 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -24,11 +24,9 @@
import android.annotation.NonNull;
import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.IStopUserCallback;
-import android.app.WaitResult;
import android.app.WallpaperManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -69,6 +67,7 @@
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* Perf tests for user life cycle events.
@@ -101,7 +100,6 @@
private static final long TIMEOUT_MAX_TEST_TIME_MS = 24 * 60_000;
private static final int TIMEOUT_IN_SECOND = 30;
- private static final int CHECK_USER_REMOVED_INTERVAL_MS = 200;
/** Name of users/profiles in the test. Users with this name may be freely removed. */
private static final String TEST_USER_NAME = "UserLifecycleTests_test_user";
@@ -1261,15 +1259,13 @@
* <p> This should always be used for profiles since profiles cannot be started in foreground.
*/
private void startUserInBackgroundAndWaitForUnlock(int userId) {
- final ProgressWaiter waiter = new ProgressWaiter();
- boolean success = false;
try {
- mIam.startUserInBackgroundWithListener(userId, waiter);
- success = waiter.waitForFinish(TIMEOUT_IN_SECOND);
- } catch (RemoteException e) {
- Log.e(TAG, "startUserInBackgroundAndWaitForUnlock failed", e);
+ attestTrue("Failed to start user " + userId + " in background.",
+ ShellHelper.runShellCommandWithTimeout("am start-user -w " + userId,
+ TIMEOUT_IN_SECOND).startsWith("Success:"));
+ } catch (TimeoutException e) {
+ fail("Could not start user " + userId + " in " + TIMEOUT_IN_SECOND + " seconds");
}
- attestTrue("Failed to start user " + userId + " in background.", success);
}
/** Starts the given user in the foreground. */
@@ -1389,14 +1385,20 @@
* Launches the given package in the given user.
* Make sure the keyguard has been dismissed prior to calling.
*/
- private void startApp(int userId, String packageName) throws RemoteException {
- final Context context = InstrumentationRegistry.getContext();
- final WaitResult result = ActivityTaskManager.getService().startActivityAndWait(null,
- context.getPackageName(), context.getAttributionTag(),
- context.getPackageManager().getLaunchIntentForPackage(packageName), null, null,
- null, 0, 0, null, null, userId);
- attestTrue("User " + userId + " failed to start " + packageName,
- result.result == ActivityManager.START_SUCCESS);
+ private void startApp(int userId, String packageName) {
+ final String failMessage = "User " + userId + " failed to start " + packageName;
+ final String component = InstrumentationRegistry.getContext().getPackageManager()
+ .getLaunchIntentForPackage(packageName).getComponent().flattenToShortString();
+ try {
+ final String result = ShellHelper.runShellCommandWithTimeout(
+ "am start -W -n " + component + " --user " + userId, TIMEOUT_IN_SECOND);
+ assertTrue(failMessage + ", component=" + component + ", result=" + result,
+ result.contains("Status: ok")
+ && !result.contains("Warning:")
+ && !result.contains("Error:"));
+ } catch (TimeoutException e) {
+ fail(failMessage + " in " + TIMEOUT_IN_SECOND + " seconds");
+ }
}
private class ProgressWaiter extends IProgressListener.Stub {
@@ -1471,17 +1473,11 @@
private void removeUser(int userId) throws RemoteException {
stopUserAfterWaitingForBroadcastIdle(userId, true);
try {
- mUm.removeUser(userId);
- final long startTime = System.currentTimeMillis();
- final long timeoutInMs = TIMEOUT_IN_SECOND * 1000;
- while (mUm.getUserInfo(userId) != null &&
- System.currentTimeMillis() - startTime < timeoutInMs) {
- TimeUnit.MILLISECONDS.sleep(CHECK_USER_REMOVED_INTERVAL_MS);
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- } catch (Exception e) {
- // Ignore
+ ShellHelper.runShellCommandWithTimeout("pm remove-user -w " + userId,
+ TIMEOUT_IN_SECOND);
+ } catch (TimeoutException e) {
+ Log.e(TAG, String.format("Could not remove user %d in %d seconds",
+ userId, TIMEOUT_IN_SECOND), e);
}
if (mUm.getUserInfo(userId) != null) {
mUsersToRemove.add(userId);
@@ -1544,7 +1540,11 @@
}
private void waitForBroadcastIdle() {
- ShellHelper.runShellCommand("am wait-for-broadcast-idle");
+ try {
+ ShellHelper.runShellCommandWithTimeout("am wait-for-broadcast-idle", TIMEOUT_IN_SECOND);
+ } catch (TimeoutException e) {
+ Log.e(TAG, "Ending waitForBroadcastIdle because it is taking too long", e);
+ }
}
private void sleep(long ms) {
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java b/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java
index 7b52576..a35899a 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java
@@ -24,6 +24,10 @@
import androidx.test.InstrumentationRegistry;
import java.io.FileInputStream;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
/**
* Provides Shell-based utilities such as running a command.
@@ -31,6 +35,43 @@
public final class ShellHelper {
/**
+ * Runs a Shell command with a timeout, returning a trimmed response.
+ */
+ @NonNull
+ public static String runShellCommandWithTimeout(@NonNull String command, long timeoutInSecond)
+ throws TimeoutException {
+ AtomicReference<Exception> exception = new AtomicReference<>(null);
+ AtomicReference<String> result = new AtomicReference<>(null);
+
+ CountDownLatch latch = new CountDownLatch(1);
+
+ new Thread(() -> {
+ try {
+ result.set(runShellCommandRaw(command));
+ } catch (Exception e) {
+ exception.set(e);
+ } finally {
+ latch.countDown();
+ }
+ }).start();
+
+ try {
+ if (!latch.await(timeoutInSecond, TimeUnit.SECONDS)) {
+ throw new TimeoutException("Command: '" + command + "' could not run in "
+ + timeoutInSecond + " seconds");
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+
+ if (exception.get() != null) {
+ throw new AndroidRuntimeException(exception.get());
+ }
+
+ return result.get();
+ }
+
+ /**
* Runs a Shell command, returning a trimmed response.
*/
@NonNull
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
index 430a1e2..4d646de 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
@@ -292,6 +292,10 @@
return "permission";
case EXACT_ALLOW_REASON_POLICY_PERMISSION:
return "policy_permission";
+ case EXACT_ALLOW_REASON_LISTENER:
+ return "listener";
+ case EXACT_ALLOW_REASON_PRIORITIZED:
+ return "prioritized";
case EXACT_ALLOW_REASON_NOT_APPLICABLE:
return "N/A";
default:
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index ae63816..332c53c 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -536,6 +536,12 @@
field @NonNull public static final android.app.admin.DeviceAdminAuthority DEVICE_ADMIN_AUTHORITY;
}
+ public final class DevicePolicyIdentifiers {
+ field public static final String PERMITTED_INPUT_METHODS_POLICY = "permittedInputMethods";
+ field public static final String PERSONAL_APPS_SUSPENDED_POLICY = "personalAppsSuspended";
+ field public static final String SCREEN_CAPTURE_DISABLED_POLICY = "screenCaptureDisabled";
+ }
+
public class DevicePolicyManager {
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void acknowledgeNewUserDisclaimer();
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void calculateHasIncompatibleAccounts();
@@ -3783,6 +3789,7 @@
method @NonNull @RequiresPermission(value=android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional=true) public java.util.List<android.view.inputmethod.InputMethodInfo> getInputMethodListAsUser(int);
method public boolean hasActiveInputConnection(@Nullable android.view.View);
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean hasPendingImeVisibilityRequests();
+ method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean isCurrentRootView(@NonNull android.view.View);
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean isInputMethodPickerShown();
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public void setStylusWindowIdleTimeoutForTest(long);
field public static final long CLEAR_SHOW_FORCED_FLAG_WHEN_LEAVING = 214016041L; // 0xcc1a029L
diff --git a/core/java/android/app/admin/DevicePolicyCache.java b/core/java/android/app/admin/DevicePolicyCache.java
index b6e83c8..29f657e 100644
--- a/core/java/android/app/admin/DevicePolicyCache.java
+++ b/core/java/android/app/admin/DevicePolicyCache.java
@@ -19,8 +19,8 @@
import com.android.server.LocalServices;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Collections;
+import java.util.Map;
/**
* Stores a copy of the set of device policies maintained by {@link DevicePolicyManager} that
@@ -64,10 +64,11 @@
public abstract boolean canAdminGrantSensorsPermissions();
/**
- * Returns a list of package names for which all launcher shortcuts should be modified to be
- * launched in the managed profile and badged accordingly.
+ * Returns a map of package names to package names, for which all launcher shortcuts which
+ * match a key package name should be modified to launch the corresponding value package
+ * name in the managed profile. The overridden shortcut should be badged accordingly.
*/
- public abstract List<String> getLauncherShortcutOverrides();
+ public abstract Map<String, String> getLauncherShortcutOverrides();
/**
* Empty implementation.
@@ -95,8 +96,8 @@
return false;
}
@Override
- public List<String> getLauncherShortcutOverrides() {
- return new ArrayList<>();
+ public Map<String, String> getLauncherShortcutOverrides() {
+ return Collections.EMPTY_MAP;
}
}
}
diff --git a/core/java/android/app/admin/DevicePolicyIdentifiers.java b/core/java/android/app/admin/DevicePolicyIdentifiers.java
index 9b0a70d..aeac59b 100644
--- a/core/java/android/app/admin/DevicePolicyIdentifiers.java
+++ b/core/java/android/app/admin/DevicePolicyIdentifiers.java
@@ -17,6 +17,7 @@
package android.app.admin;
import android.annotation.NonNull;
+import android.annotation.TestApi;
import android.os.UserManager;
import java.util.Objects;
@@ -118,6 +119,7 @@
*
* @hide
*/
+ @TestApi
public static final String PERMITTED_INPUT_METHODS_POLICY = "permittedInputMethods";
/**
@@ -125,6 +127,7 @@
*
* @hide
*/
+ @TestApi
public static final String PERSONAL_APPS_SUSPENDED_POLICY = "personalAppsSuspended";
/**
@@ -132,6 +135,7 @@
*
* @hide
*/
+ @TestApi
public static final String SCREEN_CAPTURE_DISABLED_POLICY = "screenCaptureDisabled";
/**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 27f5545..e0364cb 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -13401,11 +13401,10 @@
/**
* Called by a device admin or holder of the permission
* {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE} to set the short
- * support message. This will be displayed to the user
- * in settings screens where funtionality has been disabled by the admin. The message should be
- * limited to a short statement such as "This setting is disabled by your administrator. Contact
- * someone@example.com for support." If the message is longer than 200 characters it may be
- * truncated.
+ * support message. This will be displayed to the user in settings screens where functionality
+ * has been disabled by the admin. The message should be limited to a short statement such as
+ * "This setting is disabled by your administrator. Contact someone@example.com for support."
+ * If the message is longer than 200 characters it may be truncated.
* <p>
* If the short support message needs to be localized, it is the responsibility of the
* {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
@@ -13460,7 +13459,8 @@
/**
* Called by a device admin to set the long support message. This will be displayed to the user
- * in the device administators settings screen.
+ * in the device administrators settings screen. If the message is longer than 20000 characters
+ * it may be truncated.
* <p>
* If the long support message needs to be localized, it is the responsibility of the
* {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
index a1d74df..37c5213 100644
--- a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
+++ b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
@@ -61,36 +61,42 @@
* This variant is intended for use when the caller is acting an originator, rather than on
* behalf of a different entity, as far as authorization goes.
*/
- SoundTriggerModule(@NonNull ISoundTriggerMiddlewareService service,
+ public SoundTriggerModule(@NonNull ISoundTriggerMiddlewareService service,
int moduleId, @NonNull SoundTrigger.StatusListener listener, @NonNull Looper looper,
- @NonNull Identity originatorIdentity)
- throws RemoteException {
+ @NonNull Identity originatorIdentity) {
mId = moduleId;
mEventHandlerDelegate = new EventHandlerDelegate(listener, looper);
-
- try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- mService = service.attachAsOriginator(moduleId, originatorIdentity,
- mEventHandlerDelegate);
+ try {
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ mService = service.attachAsOriginator(moduleId, originatorIdentity,
+ mEventHandlerDelegate);
+ }
+ mService.asBinder().linkToDeath(mEventHandlerDelegate, 0);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- mService.asBinder().linkToDeath(mEventHandlerDelegate, 0);
}
/**
* This variant is intended for use when the caller is acting as a middleman, i.e. on behalf of
* a different entity, as far as authorization goes.
*/
- SoundTriggerModule(@NonNull ISoundTriggerMiddlewareService service,
+ public SoundTriggerModule(@NonNull ISoundTriggerMiddlewareService service,
int moduleId, @NonNull SoundTrigger.StatusListener listener, @NonNull Looper looper,
- @NonNull Identity middlemanIdentity, @NonNull Identity originatorIdentity)
- throws RemoteException {
+ @NonNull Identity middlemanIdentity, @NonNull Identity originatorIdentity) {
mId = moduleId;
mEventHandlerDelegate = new EventHandlerDelegate(listener, looper);
- try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- mService = service.attachAsMiddleman(moduleId, middlemanIdentity, originatorIdentity,
- mEventHandlerDelegate);
+ try {
+ try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+ mService = service.attachAsMiddleman(moduleId, middlemanIdentity,
+ originatorIdentity,
+ mEventHandlerDelegate);
+ }
+ mService.asBinder().linkToDeath(mEventHandlerDelegate, 0);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- mService.asBinder().linkToDeath(mEventHandlerDelegate, 0);
}
@Override
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 3487b01..79e7574 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11496,6 +11496,8 @@
public static final int DEVICE_STATE_ROTATION_KEY_HALF_FOLDED = 1;
/** @hide */
public static final int DEVICE_STATE_ROTATION_KEY_UNFOLDED = 2;
+ /** @hide */
+ public static final int DEVICE_STATE_ROTATION_KEY_REAR_DISPLAY = 3;
/**
* The different postures that can be used as keys with
@@ -11507,6 +11509,7 @@
DEVICE_STATE_ROTATION_KEY_FOLDED,
DEVICE_STATE_ROTATION_KEY_HALF_FOLDED,
DEVICE_STATE_ROTATION_KEY_UNFOLDED,
+ DEVICE_STATE_ROTATION_KEY_REAR_DISPLAY,
})
@Retention(RetentionPolicy.SOURCE)
public @interface DeviceStateRotationLockKey {
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 79a4f54..6061a0f 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -913,8 +913,6 @@
* sandboxed process.
* @param callback The callback to notify of detection events.
* @return An instanece of {@link VisualQueryDetector}.
- * @throws UnsupportedOperationException if only single detector is supported. Multiple detector
- * is only available for apps targeting {@link Build.VERSION_CODES#TIRAMISU} and above.
* @throws IllegalStateException when there is an existing {@link VisualQueryDetector}, or when
* there is a non-trusted hotword detector running.
*
@@ -935,21 +933,16 @@
throw new IllegalStateException("Not available until onReady() is called");
}
synchronized (mLock) {
- if (!CompatChanges.isChangeEnabled(MULTIPLE_ACTIVE_HOTWORD_DETECTORS)) {
- throw new UnsupportedOperationException("VisualQueryDetector is only available if "
- + "multiple detectors are allowed");
- } else {
- if (mActiveVisualQueryDetector != null) {
+ if (mActiveVisualQueryDetector != null) {
+ throw new IllegalStateException(
+ "There is already an active VisualQueryDetector. "
+ + "It must be destroyed to create a new one.");
+ }
+ for (HotwordDetector detector : mActiveDetectors) {
+ if (!detector.isUsingSandboxedDetectionService()) {
throw new IllegalStateException(
- "There is already an active VisualQueryDetector. "
- + "It must be destroyed to create a new one.");
- }
- for (HotwordDetector detector : mActiveDetectors) {
- if (!detector.isUsingSandboxedDetectionService()) {
- throw new IllegalStateException(
- "It disallows to create trusted and non-trusted detectors "
- + "at the same time.");
- }
+ "It disallows to create trusted and non-trusted detectors "
+ + "at the same time.");
}
}
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index f2373fb..d8fa533 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -360,6 +360,14 @@
public SparseArray<SurfaceControl.RefreshRateRange> thermalRefreshRateThrottling =
new SparseArray<>();
+ /**
+ * The ID of the brightness throttling data that should be used. This can change e.g. in
+ * concurrent displays mode in which a stricter brightness throttling policy might need to be
+ * used.
+ */
+ @Nullable
+ public String thermalBrightnessThrottlingDataId;
+
public static final @android.annotation.NonNull Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
@Override
public DisplayInfo createFromParcel(Parcel source) {
@@ -437,7 +445,9 @@
&& Objects.equals(displayShape, other.displayShape)
&& Objects.equals(layoutLimitedRefreshRate, other.layoutLimitedRefreshRate)
&& BrightnessSynchronizer.floatEquals(hdrSdrRatio, other.hdrSdrRatio)
- && thermalRefreshRateThrottling.contentEquals(other.thermalRefreshRateThrottling);
+ && thermalRefreshRateThrottling.contentEquals(other.thermalRefreshRateThrottling)
+ && Objects.equals(
+ thermalBrightnessThrottlingDataId, other.thermalBrightnessThrottlingDataId);
}
@Override
@@ -495,6 +505,7 @@
layoutLimitedRefreshRate = other.layoutLimitedRefreshRate;
hdrSdrRatio = other.hdrSdrRatio;
thermalRefreshRateThrottling = other.thermalRefreshRateThrottling;
+ thermalBrightnessThrottlingDataId = other.thermalBrightnessThrottlingDataId;
}
public void readFromParcel(Parcel source) {
@@ -559,6 +570,7 @@
hdrSdrRatio = source.readFloat();
thermalRefreshRateThrottling = source.readSparseArray(null,
SurfaceControl.RefreshRateRange.class);
+ thermalBrightnessThrottlingDataId = source.readString8();
}
@Override
@@ -620,6 +632,7 @@
dest.writeTypedObject(layoutLimitedRefreshRate, flags);
dest.writeFloat(hdrSdrRatio);
dest.writeSparseArray(thermalRefreshRateThrottling);
+ dest.writeString8(thermalBrightnessThrottlingDataId);
}
@Override
@@ -889,6 +902,8 @@
}
sb.append(", thermalRefreshRateThrottling ");
sb.append(thermalRefreshRateThrottling);
+ sb.append(", thermalBrightnessThrottlingDataId ");
+ sb.append(thermalBrightnessThrottlingDataId);
sb.append("}");
return sb.toString();
}
diff --git a/core/java/android/view/IRemoteAnimationRunner.aidl b/core/java/android/view/IRemoteAnimationRunner.aidl
index 1981c9d..1f64fb8 100644
--- a/core/java/android/view/IRemoteAnimationRunner.aidl
+++ b/core/java/android/view/IRemoteAnimationRunner.aidl
@@ -46,5 +46,5 @@
* won't have any effect anymore.
*/
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
- void onAnimationCancelled(boolean isKeyguardOccluded);
+ void onAnimationCancelled();
}
diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java
index 43828d5..9714896 100644
--- a/core/java/android/view/ImeFocusController.java
+++ b/core/java/android/view/ImeFocusController.java
@@ -86,9 +86,12 @@
void onPreWindowFocus(boolean hasWindowFocus, WindowManager.LayoutParams windowAttribute) {
mHasImeFocus = WindowManager.LayoutParams.mayUseInputMethod(windowAttribute.flags);
if (!hasWindowFocus || !mHasImeFocus || isInLocalFocusMode(windowAttribute)) {
- return;
+ if (!hasWindowFocus) {
+ getImmDelegate().onWindowLostFocus(mViewRootImpl);
+ }
+ } else {
+ getImmDelegate().onPreWindowGainedFocus(mViewRootImpl);
}
- getImmDelegate().onPreWindowGainedFocus(mViewRootImpl);
}
@UiThread
@@ -163,6 +166,7 @@
void onPreWindowGainedFocus(ViewRootImpl viewRootImpl);
void onPostWindowGainedFocus(View viewForWindowFocus,
@NonNull WindowManager.LayoutParams windowAttribute);
+ void onWindowLostFocus(@NonNull ViewRootImpl viewRootImpl);
void onViewFocusChanged(@NonNull View view, boolean hasFocus);
void onScheduledCheckFocus(@NonNull ViewRootImpl viewRootImpl);
void onViewDetachedFromWindow(View view, ViewRootImpl viewRootImpl);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index c0ac04c..8f20e2d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -961,12 +961,20 @@
}
sAnrReported = true;
+ // If we're making an in-process call to ActivityManagerService
+ // and the previous binder call on this thread was oneway, the
+ // calling PID will be 0. Clearing the calling identity fixes
+ // this and ensures ActivityManager gets the correct calling
+ // pid.
+ final long identityToken = Binder.clearCallingIdentity();
try {
ActivityManager.getService().appNotResponding(reason);
} catch (RemoteException e) {
// We asked the system to crash us, but the system
// already crashed. Unfortunately things may be
// out of control.
+ } finally {
+ Binder.restoreCallingIdentity(identityToken);
}
}
};
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 82cf073..41ef44e 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -482,13 +482,21 @@
private View mNextServedView;
/**
- * This is the root view of the overall window that currently has input
- * method focus.
+ * The latest {@link ViewRootImpl} that has, or most recently had, input method focus.
+ *
+ * <p>This value will be cleared when it becomes inactive and no longer has window focus.
*/
+ @Nullable
@GuardedBy("mH")
ViewRootImpl mCurRootView;
/**
+ * Whether the {@link #mCurRootView} currently has window focus.
+ */
+ @GuardedBy("mH")
+ boolean mCurRootViewWindowFocused;
+
+ /**
* This is set when we are in the process of connecting, to determine
* when we have actually finished.
*/
@@ -745,6 +753,7 @@
public void onPreWindowGainedFocus(ViewRootImpl viewRootImpl) {
synchronized (mH) {
setCurrentRootViewLocked(viewRootImpl);
+ mCurRootViewWindowFocused = true;
}
}
@@ -822,6 +831,17 @@
}
@Override
+ public void onWindowLostFocus(@NonNull ViewRootImpl viewRootImpl) {
+ synchronized (mH) {
+ if (mCurRootView == viewRootImpl) {
+ mCurRootViewWindowFocused = false;
+
+ clearCurRootViewIfNeeded();
+ }
+ }
+ }
+
+ @Override
public void onViewFocusChanged(@Nullable View view, boolean hasFocus) {
onViewFocusChangedInternal(view, hasFocus);
}
@@ -1114,6 +1134,10 @@
// Note that finishComposingText() is allowed to run
// even when we are not active.
mFallbackInputConnection.finishComposingTextFromImm();
+
+ if (clearCurRootViewIfNeeded()) {
+ return;
+ }
}
// Check focus again in case that "onWindowFocus" is called before
// handling this message.
@@ -1756,8 +1780,7 @@
}
/**
- * Return true if the given view is the currently active view for the
- * input method.
+ * Return {@code true} if the given view is the currently active view for the input method.
*/
public boolean isActive(View view) {
// Re-dispatch if there is a context mismatch.
@@ -1773,7 +1796,7 @@
}
/**
- * Return true if any view is currently active in the input method.
+ * Return {@code true} if any view is currently active for the input method.
*/
public boolean isActive() {
checkFocus();
@@ -1783,6 +1806,20 @@
}
/**
+ * Returns {@code true} if the given view's {@link ViewRootImpl} is the currently active one
+ * for the {@code InputMethodManager}.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(Manifest.permission.TEST_INPUT_METHOD)
+ public boolean isCurrentRootView(@NonNull View attachedView) {
+ synchronized (mH) {
+ return mCurRootView == attachedView.getViewRootImpl();
+ }
+ }
+
+ /**
* Return {@code true} if the currently served view is accepting full text edits.
* If {@code false}, it has no input connection, so it can only handle raw key events.
*/
@@ -1908,6 +1945,24 @@
mImeDispatcher.clear();
}
+ /**
+ * Clears the {@link #mCurRootView} if it's no longer window focused and the connection is
+ * no longer active.
+ *
+ * @return {@code} true iff it was cleared.
+ */
+ @GuardedBy("mH")
+ private boolean clearCurRootViewIfNeeded() {
+ if (!mActive && !mCurRootViewWindowFocused) {
+ finishInputLocked();
+ mDelegate.setCurrentRootViewLocked(null);
+
+ return true;
+ }
+
+ return false;
+ }
+
public void displayCompletions(View view, CompletionInfo[] completions) {
// Re-dispatch if there is a context mismatch.
final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
diff --git a/core/java/android/view/inputmethod/TextBoundsInfo.java b/core/java/android/view/inputmethod/TextBoundsInfo.java
index d42d94e..d9f59d6 100644
--- a/core/java/android/view/inputmethod/TextBoundsInfo.java
+++ b/core/java/android/view/inputmethod/TextBoundsInfo.java
@@ -1025,6 +1025,7 @@
mEnd = -1;
mCharacterBounds = null;
mCharacterFlags = null;
+ mCharacterBidiLevels = null;
mLineSegmentFinder = null;
mWordSegmentFinder = null;
mGraphemeSegmentFinder = null;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 7931d1a..2dbff58 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -724,7 +724,10 @@
}
getPositionListener().addSubscriber(mCursorAnchorInfoNotifier, true);
- makeBlink();
+ // Call resumeBlink here instead of makeBlink to ensure that if mBlink is not null the
+ // Blink object is uncancelled. This ensures when a view is removed and added back the
+ // cursor will resume blinking.
+ resumeBlink();
}
void onDetachedFromWindow() {
@@ -1094,8 +1097,10 @@
private void resumeBlink() {
if (mBlink != null) {
mBlink.uncancel();
- makeBlink();
}
+ // Moving makeBlink outside of the null check block ensures that mBlink object gets
+ // instantiated when the view is added to the window if mBlink is still null.
+ makeBlink();
}
void adjustInputType(boolean password, boolean passwordInputType,
@@ -2921,6 +2926,9 @@
if (shouldBlink()) {
mShowCursor = SystemClock.uptimeMillis();
if (mBlink == null) mBlink = new Blink();
+ // Call uncancel as mBlink could have previously been cancelled and cursor will not
+ // resume blinking unless uncancelled.
+ mBlink.uncancel();
mTextView.removeCallbacks(mBlink);
mTextView.postDelayed(mBlink, BLINK);
} else {
diff --git a/core/java/android/window/TaskConstants.java b/core/java/android/window/TaskConstants.java
index e18fd50..69d79b4 100644
--- a/core/java/android/window/TaskConstants.java
+++ b/core/java/android/window/TaskConstants.java
@@ -73,6 +73,13 @@
*/
public static final int TASK_CHILD_LAYER_TASK_OVERLAY = 4 * TASK_CHILD_LAYER_REGION_SIZE;
+
+ /**
+ * Veil to cover task surface and other window decorations during resizes.
+ * @hide
+ */
+ public static final int TASK_CHILD_LAYER_RESIZE_VEIL = 6 * TASK_CHILD_LAYER_REGION_SIZE;
+
/**
* Z-orders of task child layers other than activities, task fragments and layers interleaved
* with them, e.g. IME windows. [-10000, 10000) is reserved for these layers.
@@ -84,7 +91,8 @@
TASK_CHILD_LAYER_COMPAT_UI,
TASK_CHILD_LAYER_WINDOW_DECORATIONS,
TASK_CHILD_LAYER_RECENTS_ANIMATION_PIP_OVERLAY,
- TASK_CHILD_LAYER_TASK_OVERLAY
+ TASK_CHILD_LAYER_TASK_OVERLAY,
+ TASK_CHILD_LAYER_RESIZE_VEIL
})
public @interface TaskChildLayer {}
}
diff --git a/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
index 3a8f427..4f9fc39 100644
--- a/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
+++ b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
@@ -32,6 +32,9 @@
import android.os.Build;
import android.os.UserHandle;
import android.provider.Settings;
+import android.telecom.TelecomManager;
+import android.telephony.Annotation;
+import android.telephony.TelephonyManager;
import android.text.ParcelableSpan;
import android.text.Spanned;
import android.text.TextUtils;
@@ -204,6 +207,32 @@
}
/**
+ * Intercepts the {@link AccessibilityService#GLOBAL_ACTION_KEYCODE_HEADSETHOOK} action
+ * by directly interacting with TelecomManager if a call is incoming or in progress.
+ *
+ * <p>
+ * Provided here in shared utils to be used by both the legacy and modern (SysUI)
+ * system action implementations.
+ * </p>
+ *
+ * @return True if the action was propagated to TelecomManager, otherwise false.
+ */
+ public static boolean interceptHeadsetHookForActiveCall(Context context) {
+ final TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
+ @Annotation.CallState final int callState =
+ telecomManager != null ? telecomManager.getCallState()
+ : TelephonyManager.CALL_STATE_IDLE;
+ if (callState == TelephonyManager.CALL_STATE_RINGING) {
+ telecomManager.acceptRingingCall();
+ return true;
+ } else if (callState == TelephonyManager.CALL_STATE_OFFHOOK) {
+ telecomManager.endCall();
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Indicates whether the current user has completed setup via the setup wizard.
* {@link android.provider.Settings.Secure#USER_SETUP_COMPLETE}
*
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 499d38c..50f393b 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1725,16 +1725,17 @@
if (inWorkProfile) {
((TextView) findViewById(R.id.open_cross_profile)).setText(
- devicePolicyResourcesManager.getString(MINIRESOLVER_OPEN_IN_WORK,
- () -> getString(R.string.miniresolver_open_in_work, targetDisplayLabel),
+ devicePolicyResourcesManager.getString(MINIRESOLVER_OPEN_IN_PERSONAL,
+ () -> getString(R.string.miniresolver_open_in_personal,
+ targetDisplayLabel),
targetDisplayLabel));
((Button) findViewById(R.id.use_same_profile_browser)).setText(
devicePolicyResourcesManager.getString(MINIRESOLVER_USE_WORK_BROWSER,
() -> getString(R.string.miniresolver_use_work_browser)));
} else {
((TextView) findViewById(R.id.open_cross_profile)).setText(
- devicePolicyResourcesManager.getString(MINIRESOLVER_OPEN_IN_PERSONAL,
- () -> getString(R.string.miniresolver_open_in_personal,
+ devicePolicyResourcesManager.getString(MINIRESOLVER_OPEN_IN_WORK,
+ () -> getString(R.string.miniresolver_open_in_work,
targetDisplayLabel),
targetDisplayLabel));
((Button) findViewById(R.id.use_same_profile_browser)).setText(
diff --git a/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java b/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
index 86c2893..853fe2f 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
@@ -76,7 +76,7 @@
/** Gating the removal of sorting-notifications-by-interruptiveness. */
public static final Flag NO_SORT_BY_INTERRUPTIVENESS =
- releasedFlag("persist.sysui.notification.no_sort_by_interruptiveness");
+ devFlag("persist.sysui.notification.no_sort_by_interruptiveness");
/** Gating the logging of DND state change events. */
public static final Flag LOG_DND_STATE_EVENTS =
@@ -115,7 +115,7 @@
}
/**
- * Creates a flag that is disabled by default in debuggable builds.
+ * Creates a flag that is enabled by default in debuggable builds.
* It can be enabled by setting this flag's SystemProperty to 1.
*
* This flag is ALWAYS disabled in release builds.
diff --git a/core/java/com/android/internal/util/TraceBuffer.java b/core/java/com/android/internal/util/TraceBuffer.java
index bfcd65d..fcc77bd4 100644
--- a/core/java/com/android/internal/util/TraceBuffer.java
+++ b/core/java/com/android/internal/util/TraceBuffer.java
@@ -103,6 +103,10 @@
this(bufferCapacity, new ProtoOutputStreamProvider(), null);
}
+ public TraceBuffer(int bufferCapacity, Consumer<T> protoDequeuedCallback) {
+ this(bufferCapacity, new ProtoOutputStreamProvider(), protoDequeuedCallback);
+ }
+
public TraceBuffer(int bufferCapacity, ProtoProvider protoProvider,
Consumer<T> protoDequeuedCallback) {
mBufferCapacity = bufferCapacity;
diff --git a/core/java/com/android/internal/widget/NotificationActionListLayout.java b/core/java/com/android/internal/widget/NotificationActionListLayout.java
index 302d2e7..a7a69c9 100644
--- a/core/java/com/android/internal/widget/NotificationActionListLayout.java
+++ b/core/java/com/android/internal/widget/NotificationActionListLayout.java
@@ -50,6 +50,8 @@
private boolean mEmphasizedMode;
private int mDefaultPaddingBottom;
private int mDefaultPaddingTop;
+ private int mEmphasizedPaddingTop;
+ private int mEmphasizedPaddingBottom;
private int mEmphasizedHeight;
private int mRegularHeight;
@DimenRes private int mCollapsibleIndentDimen = R.dimen.notification_actions_padding_start;
@@ -322,13 +324,16 @@
}
private void updateHeights() {
- int paddingTop = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin);
+ int inset = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.button_inset_vertical_material);
+ mEmphasizedPaddingTop = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_content_margin) - inset;
// same padding on bottom and at end
- int paddingBottom = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin_end);
- mEmphasizedHeight = paddingBottom + paddingTop + getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_action_emphasized_height);
+ mEmphasizedPaddingBottom = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_content_margin_end) - inset;
+ mEmphasizedHeight = mEmphasizedPaddingTop + mEmphasizedPaddingBottom
+ + getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_action_emphasized_height);
mRegularHeight = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_action_list_height);
}
@@ -356,18 +361,10 @@
mEmphasizedMode = emphasizedMode;
int height;
if (emphasizedMode) {
- int paddingTop = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin);
- // same padding on bottom and at end
- int paddingBottom = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin_end);
- int buttonPaddingInternal = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.button_inset_vertical_material);
setPaddingRelative(getPaddingStart(),
- paddingTop - buttonPaddingInternal,
+ mEmphasizedPaddingTop,
getPaddingEnd(),
- paddingBottom - buttonPaddingInternal);
-
+ mEmphasizedPaddingBottom);
setMinimumHeight(mEmphasizedHeight);
height = ViewGroup.LayoutParams.WRAP_CONTENT;
} else {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 31220b4..fefa79f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -8067,16 +8067,6 @@
</intent-filter>
</receiver>
- <!-- Broadcast Receiver listen to sufficient verifier requests from Package Manager
- when install new SDK, to verifier SDK code during installation time
- and terminate install if SDK not compatible with privacy sandbox restrictions. -->
- <receiver android:name="com.android.server.sdksandbox.SdkSandboxVerifierReceiver"
- android:exported="false">
- <intent-filter>
- <action android:name="android.intent.action.PACKAGE_NEEDS_VERIFICATION"/>
- </intent-filter>
- </receiver>
-
<service android:name="android.hardware.location.GeofenceHardwareService"
android:permission="android.permission.LOCATION_HARDWARE"
android:exported="false" />
@@ -8204,6 +8194,10 @@
android:permission="android.permission.BIND_JOB_SERVICE">
</service>
+ <service android:name="com.android.server.healthconnect.backuprestore.BackupRestore$BackupRestoreJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE">
+ </service>
+
<service android:name="com.android.server.pm.PackageManagerShellCommandDataLoader"
android:exported="false">
<intent-filter>
@@ -8228,6 +8222,8 @@
<service android:name="com.android.server.companion.datatransfer.contextsync.CallMetadataSyncInCallService"
android:permission="android.permission.BIND_INCALL_SERVICE"
android:exported="true">
+ <meta-data android:name="android.telecom.INCLUDE_SELF_MANAGED_CALLS"
+ android:value="true" />
<intent-filter>
<action android:name="android.telecom.InCallService"/>
</intent-filter>
diff --git a/core/res/res/values-mcc310/config.xml b/core/res/res/values-mcc310/config.xml
index df398f9..76abcee 100644
--- a/core/res/res/values-mcc310/config.xml
+++ b/core/res/res/values-mcc310/config.xml
@@ -22,4 +22,7 @@
<!-- Whether safe headphone volume is enabled or not (country specific). -->
<bool name="config_safe_media_volume_enabled">false</bool>
+ <!-- Whether safe headphone sound dosage warning is enabled or not (country specific). -->
+ <bool name="config_safe_sound_dosage_mcc_enabled">false</bool>
+
</resources>
diff --git a/core/res/res/values-mcc311/config.xml b/core/res/res/values-mcc311/config.xml
index df398f9..6e0b678 100644
--- a/core/res/res/values-mcc311/config.xml
+++ b/core/res/res/values-mcc311/config.xml
@@ -22,4 +22,7 @@
<!-- Whether safe headphone volume is enabled or not (country specific). -->
<bool name="config_safe_media_volume_enabled">false</bool>
+ <!-- Whether safe headphone sound dosage warning is enabled or not (country specific). -->
+ <bool name="config_safe_sound_dosage_enabled">false</bool>
+
</resources>
diff --git a/core/res/res/values-mcc312/config.xml b/core/res/res/values-mcc312/config.xml
index df398f9..6e0b678 100644
--- a/core/res/res/values-mcc312/config.xml
+++ b/core/res/res/values-mcc312/config.xml
@@ -22,4 +22,7 @@
<!-- Whether safe headphone volume is enabled or not (country specific). -->
<bool name="config_safe_media_volume_enabled">false</bool>
+ <!-- Whether safe headphone sound dosage warning is enabled or not (country specific). -->
+ <bool name="config_safe_sound_dosage_enabled">false</bool>
+
</resources>
diff --git a/core/res/res/values-mcc313/config.xml b/core/res/res/values-mcc313/config.xml
index df398f9..6e0b678 100644
--- a/core/res/res/values-mcc313/config.xml
+++ b/core/res/res/values-mcc313/config.xml
@@ -22,4 +22,7 @@
<!-- Whether safe headphone volume is enabled or not (country specific). -->
<bool name="config_safe_media_volume_enabled">false</bool>
+ <!-- Whether safe headphone sound dosage warning is enabled or not (country specific). -->
+ <bool name="config_safe_sound_dosage_enabled">false</bool>
+
</resources>
diff --git a/core/res/res/values-mcc314/config.xml b/core/res/res/values-mcc314/config.xml
index df398f9..6e0b678 100644
--- a/core/res/res/values-mcc314/config.xml
+++ b/core/res/res/values-mcc314/config.xml
@@ -22,4 +22,7 @@
<!-- Whether safe headphone volume is enabled or not (country specific). -->
<bool name="config_safe_media_volume_enabled">false</bool>
+ <!-- Whether safe headphone sound dosage warning is enabled or not (country specific). -->
+ <bool name="config_safe_sound_dosage_enabled">false</bool>
+
</resources>
diff --git a/core/res/res/values-mcc315/config.xml b/core/res/res/values-mcc315/config.xml
index df398f9..6e0b678 100644
--- a/core/res/res/values-mcc315/config.xml
+++ b/core/res/res/values-mcc315/config.xml
@@ -22,4 +22,7 @@
<!-- Whether safe headphone volume is enabled or not (country specific). -->
<bool name="config_safe_media_volume_enabled">false</bool>
+ <!-- Whether safe headphone sound dosage warning is enabled or not (country specific). -->
+ <bool name="config_safe_sound_dosage_enabled">false</bool>
+
</resources>
diff --git a/core/res/res/values-mcc316/config.xml b/core/res/res/values-mcc316/config.xml
index df398f9..6e0b678 100644
--- a/core/res/res/values-mcc316/config.xml
+++ b/core/res/res/values-mcc316/config.xml
@@ -22,4 +22,7 @@
<!-- Whether safe headphone volume is enabled or not (country specific). -->
<bool name="config_safe_media_volume_enabled">false</bool>
+ <!-- Whether safe headphone sound dosage warning is enabled or not (country specific). -->
+ <bool name="config_safe_sound_dosage_enabled">false</bool>
+
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c5f7ea6..7bc3ab8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -558,6 +558,9 @@
docked if the dock is configured to enable the accelerometer. -->
<bool name="config_supportAutoRotation">true</bool>
+ <!-- If true, allows rotation resolver service to help resolve screen rotation. -->
+ <bool name="config_allowRotationResolver">true</bool>
+
<!-- If true, the screen can be rotated via the accelerometer in all 4
rotations as the default behavior. -->
<bool name="config_allowAllRotations">false</bool>
@@ -2102,9 +2105,6 @@
<!-- The default volume for the ring stream -->
<integer name="config_audio_ring_vol_default">5</integer>
- <!-- Enable sound dose computation and warnings -->
- <bool name="config_audio_csd_enabled_default">true</bool>
-
<!-- The default value for whether head tracking for
spatial audio is enabled for a newly connected audio device -->
<bool name="config_spatial_audio_head_tracking_enabled_default">false</bool>
@@ -2936,6 +2936,9 @@
<!-- Whether safe headphone volume is enabled or not (country specific). -->
<bool name="config_safe_media_volume_enabled">true</bool>
+ <!-- Whether safe headphone sound dosage warning is enabled or not (country specific). -->
+ <bool name="config_safe_sound_dosage_enabled">true</bool>
+
<!-- Whether safe headphone volume warning dialog is disabled on Vol+ (operator specific). -->
<bool name="config_safe_media_disable_on_volume_up">true</bool>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index b1b1edf..bc0af12 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -257,8 +257,8 @@
<!-- The margin of the notification action list at the top -->
<dimen name="notification_action_list_margin_top">0dp</dimen>
- <!-- The visual height of the emphasized notification action -->
- <dimen name="notification_action_emphasized_height">36dp</dimen>
+ <!-- The overall height of the emphasized notification action -->
+ <dimen name="notification_action_emphasized_height">48dp</dimen>
<!-- The padding of the actions in non-conversation layout. For conversations, the analogous
value is calculated in ConversationLayout#updateActionListPadding() -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ae107fd..e25425d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -283,7 +283,6 @@
<java-symbol type="attr" name="autofillSaveCustomSubtitleMaxHeight"/>
<java-symbol type="bool" name="action_bar_embed_tabs" />
<java-symbol type="bool" name="action_bar_expanded_action_views_exclusive" />
- <java-symbol type="bool" name="config_audio_csd_enabled_default" />
<java-symbol type="integer" name="config_audio_notif_vol_default" />
<java-symbol type="integer" name="config_audio_notif_vol_steps" />
<java-symbol type="integer" name="config_audio_ring_vol_default" />
@@ -349,6 +348,7 @@
<java-symbol type="bool" name="config_useDevInputEventForAudioJack" />
<java-symbol type="bool" name="config_safe_media_volume_enabled" />
<java-symbol type="bool" name="config_safe_media_disable_on_volume_up" />
+ <java-symbol type="bool" name="config_safe_sound_dosage_enabled" />
<java-symbol type="bool" name="config_camera_sound_forced" />
<java-symbol type="bool" name="config_dontPreferApn" />
<java-symbol type="bool" name="config_restartRadioAfterProvisioning" />
@@ -1715,6 +1715,7 @@
<java-symbol type="integer" name="config_motionPredictionOffsetNanos" />
<java-symbol type="bool" name="config_showNavigationBar" />
<java-symbol type="bool" name="config_supportAutoRotation" />
+ <java-symbol type="bool" name="config_allowRotationResolver" />
<java-symbol type="bool" name="config_dockedStackDividerFreeSnapMode" />
<java-symbol type="dimen" name="docked_stack_divider_thickness" />
<java-symbol type="dimen" name="docked_stack_divider_insets" />
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/RadioServiceUserControllerTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/RadioServiceUserControllerTest.java
index 3e9e992..516253b 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/RadioServiceUserControllerTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/RadioServiceUserControllerTest.java
@@ -58,7 +58,7 @@
}
@Test
- public void isCurrentUser_forCurrentUser_returnsFalse() {
+ public void isCurrentOrSystemUser_forCurrentUser_returnsFalse() {
when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
assertWithMessage("Current user")
@@ -66,7 +66,7 @@
}
@Test
- public void isCurrentUser_forNonCurrentUser_returnsFalse() {
+ public void isCurrentOrSystemUser_forNonCurrentUser_returnsFalse() {
when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_2);
assertWithMessage("Non-current user")
@@ -74,7 +74,8 @@
}
@Test
- public void isCurrentUser_forSystemUser_returnsTrue() {
+ public void isCurrentOrSystemUser_forSystemUser_returnsTrue() {
+ when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
when(mUserHandleMock.getIdentifier()).thenReturn(UserHandle.USER_SYSTEM);
assertWithMessage("System user")
@@ -82,10 +83,26 @@
}
@Test
- public void isCurrentUser_withActivityManagerFails_returnsFalse() {
- doThrow(new RuntimeException()).when(() -> ActivityManager.getCurrentUser());
+ public void isCurrentOrSystemUser_withActivityManagerFailure_returnsFalse() {
+ when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
+ doThrow(new RuntimeException()).when(ActivityManager::getCurrentUser);
assertWithMessage("User when activity manager fails")
.that(RadioServiceUserController.isCurrentOrSystemUser()).isFalse();
}
+
+ @Test
+ public void getCurrentUser() {
+ assertWithMessage("Current user")
+ .that(RadioServiceUserController.getCurrentUser()).isEqualTo(USER_ID_1);
+ }
+
+ @Test
+ public void getCurrentUser_withActivityManagerFailure_returnsUserNull() {
+ when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
+ doThrow(new RuntimeException()).when(ActivityManager::getCurrentUser);
+
+ assertWithMessage("Current user when activity manager fails")
+ .that(RadioServiceUserController.getCurrentUser()).isEqualTo(UserHandle.USER_NULL);
+ }
}
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
index cce1b2b..6c70192 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
@@ -80,7 +80,7 @@
/* vendorIds= */ null);
}
- static android.hardware.broadcastradio.ProgramSelector makeHalFmSelector(int freq) {
+ static android.hardware.broadcastradio.ProgramSelector makeHalFmSelector(long freq) {
ProgramIdentifier halId = makeHalIdentifier(IdentifierType.AMFM_FREQUENCY_KHZ, freq);
return makeHalSelector(halId, /* secondaryIds= */ new ProgramIdentifier[0]);
}
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsResultTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsResultTest.java
index df3ddfd..b54c156 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsResultTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsResultTest.java
@@ -52,6 +52,7 @@
{Result.INVALID_STATE, RadioTuner.TUNER_RESULT_INVALID_STATE},
{Result.NOT_SUPPORTED, RadioTuner.TUNER_RESULT_NOT_SUPPORTED},
{Result.TIMEOUT, RadioTuner.TUNER_RESULT_TIMEOUT},
+ {Result.CANCELED, RadioTuner.TUNER_RESULT_CANCELED},
{Result.UNKNOWN_ERROR, RadioTuner.TUNER_RESULT_UNKNOWN_ERROR}
});
}
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
index aea0178..2ef923d 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
@@ -27,11 +27,13 @@
import android.hardware.broadcastradio.ProgramInfo;
import android.hardware.broadcastradio.ProgramListChunk;
import android.hardware.broadcastradio.Properties;
+import android.hardware.broadcastradio.Result;
import android.hardware.broadcastradio.VendorKeyValue;
import android.hardware.radio.Announcement;
import android.hardware.radio.ProgramList;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
+import android.os.ServiceSpecificException;
import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
import com.android.server.broadcastradio.ExtendedRadioMockitoTestCase;
@@ -153,6 +155,16 @@
}
@Test
+ public void throwOnError_withCancelException() {
+ ServiceSpecificException halException = new ServiceSpecificException(Result.CANCELED);
+
+ RuntimeException thrown = ConversionUtils.throwOnError(halException, "tune");
+
+ expect.withMessage("Exception thrown for canceling error").that(thrown)
+ .hasMessageThat().contains("tune: CANCELED");
+ }
+
+ @Test
public void propertiesFromHalProperties_idsMatch() {
expect.withMessage("Properties id")
.that(MODULE_PROPERTIES.getId()).isEqualTo(TEST_ID);
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
index 78b5a4a..84aa864 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
@@ -47,9 +47,11 @@
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
import android.hardware.radio.RadioTuner;
+import android.os.Binder;
import android.os.ParcelableException;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -73,6 +75,8 @@
*/
public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
+ private static final int USER_ID_1 = 11;
+ private static final int USER_ID_2 = 12;
private static final VerificationWithTimeout CALLBACK_TIMEOUT =
timeout(/* millis= */ 200);
private static final int SIGNAL_QUALITY = 90;
@@ -109,7 +113,10 @@
SIGNAL_QUALITY);
// Mocks
- @Mock private IBroadcastRadio mBroadcastRadioMock;
+ @Mock
+ private UserHandle mUserHandleMock;
+ @Mock
+ private IBroadcastRadio mBroadcastRadioMock;
private android.hardware.radio.ITunerCallback[] mAidlTunerCallbackMocks;
// RadioModule under test
@@ -124,14 +131,18 @@
@Override
protected void initializeSession(StaticMockitoSessionBuilder builder) {
- builder.spyStatic(RadioServiceUserController.class).spyStatic(CompatChanges.class);
+ builder.spyStatic(RadioServiceUserController.class).spyStatic(CompatChanges.class)
+ .spyStatic(Binder.class);
}
@Before
public void setup() throws Exception {
+ when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
doReturn(true).when(() -> CompatChanges.isChangeEnabled(
eq(ConversionUtils.RADIO_U_VERSION_REQUIRED), anyInt()));
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
+ doReturn(USER_ID_1).when(() -> RadioServiceUserController.getCurrentUser());
+ doReturn(mUserHandleMock).when(() -> Binder.getCallingUserHandle());
mRadioModule = new RadioModule(mBroadcastRadioMock,
AidlTestUtils.makeDefaultModuleProperties());
@@ -421,6 +432,21 @@
}
@Test
+ public void tune_forSystemUser() throws Exception {
+ when(mUserHandleMock.getIdentifier()).thenReturn(UserHandle.USER_SYSTEM);
+ doReturn(mUserHandleMock).when(() -> Binder.getCallingUserHandle());
+ doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
+ ProgramSelector initialSel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
+ RadioManager.ProgramInfo tuneInfo =
+ AidlTestUtils.makeProgramInfo(initialSel, SIGNAL_QUALITY);
+ openAidlClients(/* numClients= */ 1);
+
+ mTunerSessions[0].tune(initialSel);
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onCurrentProgramInfoChanged(tuneInfo);
+ }
+
+ @Test
public void tune_withUnknownErrorFromHal_fails() throws Exception {
openAidlClients(/* numClients= */ 1);
ProgramSelector sel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
@@ -1136,6 +1162,35 @@
}
@Test
+ public void onCurrentProgramInfoChanged_withNoncurrentUser_doesNotInvokeCallback()
+ throws Exception {
+ openAidlClients(1);
+ doReturn(USER_ID_2).when(() -> RadioServiceUserController.getCurrentUser());
+
+ mHalTunerCallback.onCurrentProgramInfoChanged(AidlTestUtils.makeHalProgramInfo(
+ AidlTestUtils.makeHalFmSelector(AM_FM_FREQUENCY_LIST[1]), SIGNAL_QUALITY));
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ .onCurrentProgramInfoChanged(any());
+ }
+
+ @Test
+ public void onTuneFailed_forTunerCallback() throws Exception {
+ int numSessions = 3;
+ openAidlClients(numSessions);
+ android.hardware.broadcastradio.ProgramSelector halSel = AidlTestUtils.makeHalFmSelector(
+ AM_FM_FREQUENCY_LIST[1]);
+ ProgramSelector sel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
+
+ mHalTunerCallback.onTuneFailed(Result.CANCELED, halSel);
+
+ for (int index = 0; index < numSessions; index++) {
+ verify(mAidlTunerCallbackMocks[index], CALLBACK_TIMEOUT)
+ .onTuneFailed(RadioTuner.TUNER_RESULT_CANCELED, sel);
+ }
+ }
+
+ @Test
public void onAntennaStateChange_forTunerCallback() throws Exception {
int numSessions = 3;
openAidlClients(numSessions);
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
index 3815008..fac9eaa 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
@@ -46,8 +46,10 @@
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
import android.hardware.radio.RadioTuner;
+import android.os.Binder;
import android.os.ParcelableException;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -74,6 +76,8 @@
@RunWith(MockitoJUnitRunner.class)
public final class TunerSessionHidlTest extends ExtendedRadioMockitoTestCase {
+ private static final int USER_ID_1 = 11;
+ private static final int USER_ID_2 = 12;
private static final VerificationWithTimeout CALLBACK_TIMEOUT =
timeout(/* millis= */ 200);
private static final int SIGNAL_QUALITY = 1;
@@ -94,18 +98,25 @@
private ProgramInfo mHalCurrentInfo;
private TunerSession[] mTunerSessions;
- @Mock private IBroadcastRadio mBroadcastRadioMock;
- @Mock ITunerSession mHalTunerSessionMock;
+ @Mock
+ private UserHandle mUserHandleMock;
+ @Mock
+ private IBroadcastRadio mBroadcastRadioMock;
+ @Mock
+ ITunerSession mHalTunerSessionMock;
private android.hardware.radio.ITunerCallback[] mAidlTunerCallbackMocks;
@Override
protected void initializeSession(StaticMockitoSessionBuilder builder) {
- builder.spyStatic(RadioServiceUserController.class);
+ builder.spyStatic(RadioServiceUserController.class).spyStatic(Binder.class);
}
@Before
public void setup() throws Exception {
+ when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
+ doReturn(mUserHandleMock).when(() -> Binder.getCallingUserHandle());
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
+ doReturn(USER_ID_1).when(() -> RadioServiceUserController.getCurrentUser());
mRadioModule = new RadioModule(mBroadcastRadioMock,
TestUtils.makeDefaultModuleProperties());
@@ -387,6 +398,20 @@
}
@Test
+ public void tune_forSystemUser() throws Exception {
+ when(mUserHandleMock.getIdentifier()).thenReturn(UserHandle.USER_SYSTEM);
+ doReturn(mUserHandleMock).when(() -> Binder.getCallingUserHandle());
+ doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
+ ProgramSelector initialSel = TestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
+ RadioManager.ProgramInfo tuneInfo = TestUtils.makeProgramInfo(initialSel, SIGNAL_QUALITY);
+ openAidlClients(/* numClients= */ 1);
+
+ mTunerSessions[0].tune(initialSel);
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onCurrentProgramInfoChanged(tuneInfo);
+ }
+
+ @Test
public void step_withDirectionUp() throws Exception {
long initFreq = AM_FM_FREQUENCY_LIST[1];
ProgramSelector initialSel = TestUtils.makeFmSelector(initFreq);
@@ -858,6 +883,19 @@
}
@Test
+ public void onCurrentProgramInfoChanged_withNoncurrentUser_doesNotInvokeCallback()
+ throws Exception {
+ openAidlClients(1);
+ doReturn(USER_ID_2).when(() -> RadioServiceUserController.getCurrentUser());
+
+ mHalTunerCallback.onCurrentProgramInfoChanged(TestUtils.makeHalProgramInfo(
+ TestUtils.makeHalFmSelector(/* freq= */ 97300), SIGNAL_QUALITY));
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ .onCurrentProgramInfoChanged(any());
+ }
+
+ @Test
public void onConfigFlagUpdated_forTunerCallback() throws Exception {
int numSessions = 3;
openAidlClients(numSessions);
diff --git a/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java b/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
index bf8c7c6..72969f7 100644
--- a/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
+++ b/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
@@ -112,6 +112,7 @@
Paths.get("/data/misc/wmtrace/layers_trace.winscope"),
Paths.get("/data/misc/wmtrace/transactions_trace.winscope"),
Paths.get("/data/misc/wmtrace/transition_trace.winscope"),
+ Paths.get("/data/misc/wmtrace/shell_transition_trace.winscope"),
};
private static final Path[] UI_TRACES_GENERATED_DURING_BUGREPORT = {
Paths.get("/data/misc/wmtrace/layers_trace_from_transactions.winscope"),
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 67842f0..ab500f7 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -59,6 +59,7 @@
"print-test-util-lib",
"testng",
"servicestests-utils",
+ "device-time-shell-utils",
],
libs: [
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index fb0f3d4..af81957 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -62,7 +62,6 @@
import android.view.Display;
import android.view.View;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
@@ -616,7 +615,6 @@
}
@Test
- @FlakyTest(bugId = 176134235)
public void testHandleConfigurationChanged_DoesntOverrideActivityConfig() {
final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
diff --git a/core/tests/coretests/src/android/app/time/TimeManagerTest.java b/core/tests/coretests/src/android/app/time/TimeManagerTest.java
new file mode 100644
index 0000000..6370f3b
--- /dev/null
+++ b/core/tests/coretests/src/android/app/time/TimeManagerTest.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.time;
+
+import static android.app.time.Capabilities.CAPABILITY_NOT_ALLOWED;
+import static android.app.time.Capabilities.CAPABILITY_POSSESSED;
+import static android.app.time.cts.shell.DeviceConfigKeys.NAMESPACE_SYSTEM_TIME;
+import static android.app.time.cts.shell.DeviceConfigKeys.TimeZoneDetector.KEY_TIME_ZONE_DETECTOR_AUTO_DETECTION_ENABLED_DEFAULT;
+import static android.app.time.cts.shell.DeviceConfigShellHelper.SYNC_DISABLED_MODE_UNTIL_REBOOT;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Instrumentation;
+import android.app.time.cts.shell.DeviceConfigShellHelper;
+import android.app.time.cts.shell.DeviceShellCommandExecutor;
+import android.app.time.cts.shell.TimeZoneDetectorShellHelper;
+import android.app.time.cts.shell.device.InstrumentationShellCommandExecutor;
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/**
+ * Tests for non-SDK methods / internal behavior related to {@link TimeManager}.
+ * Also see {@link android.app.time.cts.TimeManagerTest}
+ */
+public class TimeManagerTest {
+
+ /**
+ * This rule adopts the Shell process permissions, needed because MANAGE_TIME_AND_ZONE_DETECTION
+ * and SUGGEST_EXTERNAL_TIME required by {@link TimeManager} are privileged permissions.
+ */
+ @Rule
+ public final AdoptShellPermissionsRule shellPermRule = new AdoptShellPermissionsRule();
+
+ private TimeZoneDetectorShellHelper mTimeZoneDetectorShellHelper;
+ private DeviceConfigShellHelper mDeviceConfigShellHelper;
+ private DeviceConfigShellHelper.PreTestState mDeviceConfigPreTestState;
+
+ private Context mContext;
+ private TimeManager mTimeManager;
+
+ @Before
+ public void before() throws Exception {
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ DeviceShellCommandExecutor shellCommandExecutor = new InstrumentationShellCommandExecutor(
+ instrumentation.getUiAutomation());
+ mTimeZoneDetectorShellHelper = new TimeZoneDetectorShellHelper(shellCommandExecutor);
+ mDeviceConfigShellHelper = new DeviceConfigShellHelper(shellCommandExecutor);
+
+ // This anticipates a future state where a generally applied target preparer may disable
+ // device_config sync for all CTS tests: only suspend syncing if it isn't already suspended,
+ // and only resume it if this test suspended it.
+ mDeviceConfigPreTestState = mDeviceConfigShellHelper.setSyncModeForTest(
+ SYNC_DISABLED_MODE_UNTIL_REBOOT, NAMESPACE_SYSTEM_TIME);
+
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ mTimeManager = mContext.getSystemService(TimeManager.class);
+ assertNotNull(mTimeManager);
+
+ // Avoid running tests when device policy doesn't allow user configuration. If this needs to
+ // pass then tests will become more complicated or separate cases broken out.
+ int configureAutoDetectionEnabledCapability = mTimeManager.getTimeCapabilitiesAndConfig()
+ .getCapabilities().getConfigureAutoDetectionEnabledCapability();
+ boolean userRestricted = configureAutoDetectionEnabledCapability == CAPABILITY_NOT_ALLOWED;
+ assertFalse(userRestricted);
+ }
+
+ @After
+ public void after() throws Exception {
+ mDeviceConfigShellHelper.restoreDeviceConfigStateForTest(mDeviceConfigPreTestState);
+ }
+
+ /**
+ * Tests a server flag that can be used to change the "automatic time zone enabled" value
+ * for devices where the user hasn't yet expressed a preference. The flag is only intended for
+ * use during internal testing and therefore has not been included in CTS; it could be removed
+ * in later releases. This test takes ~35s to run because the asynchronous operations involved
+ * require sleeps to allow them to complete.
+ */
+ @Test
+ public void testTimeZoneEnabledDefaultFlagBehavior() throws Exception {
+ TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
+ mTimeManager.getTimeZoneCapabilitiesAndConfig();
+
+ TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+
+ // Skip this test if the current user is not allowed to alter time detection settings via
+ // the TimeManager APIs.
+ assumeTrue(capabilities.getConfigureAutoDetectionEnabledCapability()
+ == CAPABILITY_POSSESSED);
+
+ // Start with the auto_time_zone_explicit setting empty, but record the value if there is
+ // one so that it can be restored.
+ boolean isAutoDetectionEnabledExplicit =
+ mTimeZoneDetectorShellHelper.isAutoTimeZoneEnabledExplicitly();
+
+ mTimeZoneDetectorShellHelper.clearAutoTimeZoneEnabledExplicitly();
+ sleepForAsyncOperation();
+
+ // Record the current time zone and auto detection setting so that it can be restored by the
+ // test afterwards.
+ boolean initialAutoTzEnabled =
+ capabilitiesAndConfig.getConfiguration().isAutoDetectionEnabled();
+ TimeZoneState initialTimeZoneState = mTimeManager.getTimeZoneState();
+
+ try {
+ // The server flag should be used to control the device's behavior initially because
+ // auto_time_zone_explicit is not set.
+ boolean newAutoTzEnabled = !initialAutoTzEnabled;
+ mDeviceConfigShellHelper.put(NAMESPACE_SYSTEM_TIME,
+ KEY_TIME_ZONE_DETECTOR_AUTO_DETECTION_ENABLED_DEFAULT,
+ Boolean.toString(newAutoTzEnabled));
+ sleepForAsyncOperation();
+ assertEquals(newAutoTzEnabled, mTimeZoneDetectorShellHelper.isAutoDetectionEnabled());
+
+ mDeviceConfigShellHelper.put(NAMESPACE_SYSTEM_TIME,
+ KEY_TIME_ZONE_DETECTOR_AUTO_DETECTION_ENABLED_DEFAULT,
+ Boolean.toString(initialAutoTzEnabled));
+ sleepForAsyncOperation();
+ assertEquals(initialAutoTzEnabled,
+ mTimeZoneDetectorShellHelper.isAutoDetectionEnabled());
+
+ // Now simulate the user toggling the auto tz setting twice, which should cause the
+ // system to recognize the user has expressed an explicit preference.
+ TimeZoneConfiguration config1 = new TimeZoneConfiguration.Builder()
+ .setAutoDetectionEnabled(newAutoTzEnabled)
+ .build();
+ mTimeManager.updateTimeZoneConfiguration(config1);
+ sleepForAsyncOperation();
+ assertEquals(newAutoTzEnabled,
+ mTimeZoneDetectorShellHelper.isAutoDetectionEnabled());
+
+ TimeZoneConfiguration config2 = new TimeZoneConfiguration.Builder()
+ .setAutoDetectionEnabled(initialAutoTzEnabled)
+ .build();
+ mTimeManager.updateTimeZoneConfiguration(config2);
+ sleepForAsyncOperation();
+ assertEquals(initialAutoTzEnabled,
+ mTimeZoneDetectorShellHelper.isAutoDetectionEnabled());
+
+ // Auto tz enabled is now back to initialAutoTzEnabled.
+
+ // Repeat the flag check: Now the server flag should have no effect because they have
+ // expressed a preference.
+ mDeviceConfigShellHelper.put(NAMESPACE_SYSTEM_TIME,
+ KEY_TIME_ZONE_DETECTOR_AUTO_DETECTION_ENABLED_DEFAULT,
+ Boolean.toString(newAutoTzEnabled));
+ sleepForAsyncOperation();
+ assertEquals(initialAutoTzEnabled,
+ mTimeZoneDetectorShellHelper.isAutoDetectionEnabled());
+ } finally {
+ // Restore the device's state (as much as possible).
+ if (isAutoDetectionEnabledExplicit) {
+ mTimeZoneDetectorShellHelper.setAutoTimeZoneEnabledExplicitly();
+ } else {
+ mTimeZoneDetectorShellHelper.clearAutoTimeZoneEnabledExplicitly();
+ }
+
+ // Restore auto tz and the time zone (if the device started in manual).
+ mTimeZoneDetectorShellHelper.setAutoDetectionEnabled(initialAutoTzEnabled);
+ if (!initialAutoTzEnabled) {
+ // If the device started in "manual" we can restore the time zone to its original
+ // state, maybe not confidence exactly.
+ mTimeZoneDetectorShellHelper.setTimeZoneState(
+ initialTimeZoneState.getId(),
+ initialTimeZoneState.getUserShouldConfirmId());
+ }
+ sleepForAsyncOperation();
+ }
+ }
+
+ /**
+ * Sleeps for a length of time sufficient to allow async operations to complete. Many time
+ * manager APIs are or could be asynchronous and deal with time, so there are no practical
+ * alternatives.
+ */
+ private static void sleepForAsyncOperation() throws Exception {
+ Thread.sleep(5_000);
+ }
+}
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index a3eda8d..f45db23 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -39,7 +39,6 @@
import android.widget.TextView;
import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.FlakyTest;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Before;
@@ -55,7 +54,6 @@
* atest FrameworksCoreTests:ImeInsetsSourceConsumerTest
*/
@Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
@RunWith(AndroidJUnit4.class)
public class ImeInsetsSourceConsumerTest {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
index b917ac8..d9b73a8 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
@@ -83,10 +83,7 @@
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
- if (TaskFragmentAnimationController.DEBUG) {
- Log.v(TAG, "onAnimationCancelled: isKeyguardOccluded=" + isKeyguardOccluded);
- }
+ public void onAnimationCancelled() {
mHandler.post(this::cancelAnimation);
}
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index 54978bd..6a79bc1 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -125,6 +125,34 @@
// End ProtoLog
+gensrcs {
+ name: "wm-shell-protos",
+
+ tools: [
+ "aprotoc",
+ "protoc-gen-javastream",
+ "soong_zip",
+ ],
+
+ tool_files: [
+ ":libprotobuf-internal-protos",
+ ],
+
+ cmd: "mkdir -p $(genDir)/$(in) " +
+ "&& $(location aprotoc) " +
+ " --plugin=$(location protoc-gen-javastream) " +
+ " --javastream_out=$(genDir)/$(in) " +
+ " -Iexternal/protobuf/src " +
+ " -I . " +
+ " $(in) " +
+ "&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)",
+
+ srcs: [
+ "proto/**/*.proto",
+ ],
+ output_extension: "srcjar",
+}
+
java_library {
name: "WindowManager-Shell-proto",
@@ -142,6 +170,7 @@
// TODO(b/168581922) protologtool do not support kotlin(*.kt)
":wm_shell-sources-kt",
":wm_shell-aidls",
+ ":wm-shell-protos",
],
resource_dirs: [
"res",
diff --git a/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto b/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto
new file mode 100644
index 0000000..6e01101
--- /dev/null
+++ b/libs/WindowManager/Shell/proto/wm_shell_transition_trace.proto
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package com.android.wm.shell;
+
+option java_multiple_files = true;
+
+/* Represents a file full of transition entries.
+ Encoded, it should start with 0x09 0x57 0x4D 0x53 0x54 0x52 0x41 0x43 0x45 (.WMSTRACE), such
+ that it can be easily identified. */
+message WmShellTransitionTraceProto {
+ /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L
+ (this is needed because enums have to be 32 bits and there's no nice way to put 64bit
+ constants into .proto files. */
+ enum MagicNumber {
+ INVALID = 0;
+ MAGIC_NUMBER_L = 0x54534D57; /* WMST (little-endian ASCII) */
+ MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */
+ }
+
+ // Must be the first field, set to value in MagicNumber
+ required fixed64 magic_number = 1;
+ repeated Transition transitions = 2;
+ repeated HandlerMapping handlerMappings = 3;
+}
+
+message Transition {
+ required int32 id = 1;
+ optional int64 dispatch_time_ns = 2;
+ optional int32 handler = 3;
+ optional int64 merge_time_ns = 4;
+ optional int64 merge_request_time_ns = 5;
+ optional int32 merged_into = 6;
+ optional int64 abort_time_ns = 7;
+}
+
+message HandlerMapping {
+ required int32 id = 1;
+ required string name = 2;
+}
diff --git a/libs/WindowManager/Shell/res/drawable/bubble_manage_btn_bg.xml b/libs/WindowManager/Shell/res/drawable/bubble_manage_btn_bg.xml
index 96d2d7c..d2360e9 100644
--- a/libs/WindowManager/Shell/res/drawable/bubble_manage_btn_bg.xml
+++ b/libs/WindowManager/Shell/res/drawable/bubble_manage_btn_bg.xml
@@ -16,9 +16,10 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
<solid
- android:color="@android:color/system_neutral1_800"
+ android:color="?androidprv:attr/materialColorSurfaceContainerHigh"
/>
<corners android:radius="20dp" />
diff --git a/libs/WindowManager/Shell/res/drawable/bubble_manage_menu_bg.xml b/libs/WindowManager/Shell/res/drawable/bubble_manage_menu_bg.xml
index 4bd2f13..8fd2e68 100644
--- a/libs/WindowManager/Shell/res/drawable/bubble_manage_menu_bg.xml
+++ b/libs/WindowManager/Shell/res/drawable/bubble_manage_menu_bg.xml
@@ -17,7 +17,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
- <solid android:color="?androidprv:attr/colorSurface" />
+ <solid android:color="?androidprv:attr/materialColorSurfaceBright" />
<corners
android:bottomLeftRadius="?android:attr/dialogCornerRadius"
android:topLeftRadius="?android:attr/dialogCornerRadius"
diff --git a/libs/WindowManager/Shell/res/drawable/desktop_mode_resize_veil_background.xml b/libs/WindowManager/Shell/res/drawable/desktop_mode_resize_veil_background.xml
new file mode 100644
index 0000000..1f3e3a4
--- /dev/null
+++ b/libs/WindowManager/Shell/res/drawable/desktop_mode_resize_veil_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<shape android:shape="rectangle"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@android:color/white" />
+</shape>
diff --git a/libs/WindowManager/Shell/res/layout/bubble_flyout.xml b/libs/WindowManager/Shell/res/layout/bubble_flyout.xml
index 7fdf290..65a07a7 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_flyout.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_flyout.xml
@@ -13,7 +13,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<LinearLayout
android:id="@+id/bubble_flyout_text_container"
@@ -48,6 +49,7 @@
android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
android:maxLines="1"
android:ellipsize="end"
+ android:textColor="?androidprv:attr/materialColorOnSurface"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"/>
<TextView
@@ -57,6 +59,7 @@
android:fontFamily="@*android:string/config_bodyFontFamily"
android:maxLines="2"
android:ellipsize="end"
+ android:textColor="?androidprv:attr/materialColorOnSurfaceVariant"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"/>
</LinearLayout>
diff --git a/libs/WindowManager/Shell/res/layout/bubble_manage_button.xml b/libs/WindowManager/Shell/res/layout/bubble_manage_button.xml
index 0cf6d73..f88d63d 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_manage_button.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_manage_button.xml
@@ -16,6 +16,7 @@
-->
<com.android.wm.shell.common.AlphaOptimizedButton
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
style="@android:style/Widget.DeviceDefault.Button.Borderless"
android:id="@+id/manage_button"
android:layout_gravity="start"
@@ -27,6 +28,6 @@
android:focusable="true"
android:text="@string/manage_bubbles_text"
android:textSize="@*android:dimen/text_size_body_2_material"
- android:textColor="@*android:color/system_neutral1_50"
+ android:textColor="?androidprv:attr/materialColorOnSurface"
android:background="@drawable/bubble_manage_btn_bg"
/>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/bubble_manage_menu.xml b/libs/WindowManager/Shell/res/layout/bubble_manage_menu.xml
index 298ad30..10c9562 100644
--- a/libs/WindowManager/Shell/res/layout/bubble_manage_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/bubble_manage_menu.xml
@@ -15,6 +15,7 @@
~ limitations under the License
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bubble_manage_menu_bg"
@@ -41,6 +42,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
+ android:textColor="?androidprv:attr/materialColorOnSurface"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault"
android:text="@string/bubble_dismiss_text" />
@@ -66,6 +68,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
+ android:textColor="?androidprv:attr/materialColorOnSurface"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault"
android:text="@string/bubbles_dont_bubble_conversation" />
@@ -92,6 +95,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
+ android:textColor="?androidprv:attr/materialColorOnSurface"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault" />
</LinearLayout>
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_resize_veil.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_resize_veil.xml
new file mode 100644
index 0000000..a4bbd89
--- /dev/null
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_resize_veil.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/desktop_mode_resize_veil_background">
+
+ <ImageView
+ android:id="@+id/veil_application_icon"
+ android:layout_width="96dp"
+ android:layout_height="96dp"
+ android:layout_gravity="center"
+ android:contentDescription="@string/app_icon_text" />
+</FrameLayout>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
index 5aff415..7f1aac3 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
@@ -73,11 +73,13 @@
android:textAlignment="center"/>
<LinearLayout
+ android:id="@+id/letterbox_restart_dialog_checkbox_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:paddingVertical="14dp"
android:orientation="horizontal"
android:layout_gravity="center_vertical"
- android:layout_marginVertical="32dp">
+ android:layout_marginVertical="18dp">
<CheckBox
android:id="@+id/letterbox_restart_dialog_checkbox"
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index 76eb094..a3916b7 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -125,4 +125,7 @@
<!-- Whether the additional education about reachability is enabled -->
<bool name="config_letterboxIsReachabilityEducationEnabled">false</bool>
+
+ <!-- Whether DragAndDrop capability is enabled -->
+ <bool name="config_enableShellDragDrop">true</bool>
</resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
index 22c9015..edefe9e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
@@ -404,7 +404,7 @@
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
finishAnimation();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
index f0c5d8b2..2d6ec75 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
@@ -323,7 +323,7 @@
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
finishAnimation();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index d3f3958..24fd86b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -297,7 +297,7 @@
public BubbleInfo asBubbleBarBubble() {
return new BubbleInfo(getKey(),
getFlags(),
- getShortcutInfo().getId(),
+ getShortcutId(),
getIcon(),
getUser().getIdentifier(),
getPackageName());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 21f02b1..3eb9fa2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -260,7 +260,7 @@
/** One handed mode controller to register transition listener. */
private Optional<OneHandedController> mOneHandedOptional;
/** Drag and drop controller to register listener for onDragStarted. */
- private DragAndDropController mDragAndDropController;
+ private Optional<DragAndDropController> mDragAndDropController;
/** Used to send bubble events to launcher. */
private Bubbles.BubbleStateListener mBubbleStateListener;
@@ -286,7 +286,7 @@
BubblePositioner positioner,
DisplayController displayController,
Optional<OneHandedController> oneHandedOptional,
- DragAndDropController dragAndDropController,
+ Optional<DragAndDropController> dragAndDropController,
@ShellMainThread ShellExecutor mainExecutor,
@ShellMainThread Handler mainHandler,
@ShellBackgroundThread ShellExecutor bgExecutor,
@@ -469,7 +469,7 @@
});
mOneHandedOptional.ifPresent(this::registerOneHandedState);
- mDragAndDropController.addListener(this::collapseStack);
+ mDragAndDropController.ifPresent(controller -> controller.addListener(this::collapseStack));
// Clear out any persisted bubbles on disk that no longer have a valid user.
List<UserInfo> users = mUserManager.getAliveUsers();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
index f878a46..6a5f785 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
@@ -177,7 +177,7 @@
final TypedArray ta = mContext.obtainStyledAttributes(
new int[] {
- com.android.internal.R.attr.colorSurface,
+ com.android.internal.R.attr.materialColorSurfaceContainer,
android.R.attr.dialogCornerRadius});
mFloatingBackgroundColor = ta.getColor(0, Color.WHITE);
mCornerRadius = ta.getDimensionPixelSize(1, 0);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
index c49451d..df7f5b4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
@@ -19,23 +19,21 @@
import android.app.ActivityTaskManager.INVALID_TASK_ID
import android.content.Context
import android.graphics.Bitmap
+import android.graphics.Color
import android.graphics.Matrix
import android.graphics.Path
import android.graphics.drawable.AdaptiveIconDrawable
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.InsetDrawable
import android.util.PathParser
-import android.util.TypedValue
import android.view.LayoutInflater
import android.widget.FrameLayout
import com.android.launcher3.icons.BubbleIconFactory
import com.android.wm.shell.R
import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView
-class BubbleOverflow(
- private val context: Context,
- private val positioner: BubblePositioner
-) : BubbleViewProvider {
+class BubbleOverflow(private val context: Context, private val positioner: BubblePositioner) :
+ BubbleViewProvider {
private lateinit var bitmap: Bitmap
private lateinit var dotPath: Path
@@ -54,7 +52,7 @@
overflowBtn = null
}
- /** Call before use and again if cleanUpExpandedState was called. */
+ /** Call before use and again if cleanUpExpandedState was called. */
fun initialize(controller: BubbleController) {
createExpandedView()
getExpandedView()?.initialize(controller, controller.stackView, true /* isOverflow */)
@@ -74,10 +72,10 @@
}
fun updateResources() {
- overflowIconInset = context.resources.getDimensionPixelSize(
- R.dimen.bubble_overflow_icon_inset)
- overflowBtn?.layoutParams = FrameLayout.LayoutParams(positioner.bubbleSize,
- positioner.bubbleSize)
+ overflowIconInset =
+ context.resources.getDimensionPixelSize(R.dimen.bubble_overflow_icon_inset)
+ overflowBtn?.layoutParams =
+ FrameLayout.LayoutParams(positioner.bubbleSize, positioner.bubbleSize)
expandedView?.updateDimensions()
}
@@ -85,36 +83,58 @@
val res = context.resources
// Set overflow button accent color, dot color
- val typedValue = TypedValue()
- context.theme.resolveAttribute(com.android.internal.R.attr.colorAccentPrimary,
- typedValue, true)
- val colorAccent = res.getColor(typedValue.resourceId, null)
- dotColor = colorAccent
- val shapeColor = res.getColor(android.R.color.system_accent1_1000)
+ val typedArray =
+ context.obtainStyledAttributes(
+ intArrayOf(
+ com.android.internal.R.attr.materialColorPrimaryFixed,
+ com.android.internal.R.attr.materialColorOnPrimaryFixed
+ )
+ )
+
+ val colorAccent = typedArray.getColor(0, Color.WHITE)
+ val shapeColor = typedArray.getColor(1, Color.BLACK)
+ typedArray.recycle()
+
+ dotColor = colorAccent
overflowBtn?.iconDrawable?.setTint(shapeColor)
- val iconFactory = BubbleIconFactory(context,
- context.getResources().getDimensionPixelSize(R.dimen.bubble_size),
- context.getResources().getDimensionPixelSize(R.dimen.bubble_badge_size),
- context.getResources().getColor(R.color.important_conversation),
- context.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.importance_ring_stroke_width))
+ val iconFactory =
+ BubbleIconFactory(
+ context,
+ res.getDimensionPixelSize(R.dimen.bubble_size),
+ res.getDimensionPixelSize(R.dimen.bubble_badge_size),
+ res.getColor(R.color.important_conversation),
+ res.getDimensionPixelSize(com.android.internal.R.dimen.importance_ring_stroke_width)
+ )
// Update bitmap
val fg = InsetDrawable(overflowBtn?.iconDrawable, overflowIconInset)
- bitmap = iconFactory.createBadgedIconBitmap(
- AdaptiveIconDrawable(ColorDrawable(colorAccent), fg)).icon
+ bitmap =
+ iconFactory
+ .createBadgedIconBitmap(AdaptiveIconDrawable(ColorDrawable(colorAccent), fg))
+ .icon
// Update dot path
- dotPath = PathParser.createPathFromPathData(
- res.getString(com.android.internal.R.string.config_icon_mask))
- val scale = iconFactory.normalizer.getScale(iconView!!.iconDrawable,
- null /* outBounds */, null /* path */, null /* outMaskShape */)
+ dotPath =
+ PathParser.createPathFromPathData(
+ res.getString(com.android.internal.R.string.config_icon_mask)
+ )
+ val scale =
+ iconFactory.normalizer.getScale(
+ iconView!!.iconDrawable,
+ null /* outBounds */,
+ null /* path */,
+ null /* outMaskShape */
+ )
val radius = BadgedImageView.DEFAULT_PATH_SIZE / 2f
val matrix = Matrix()
- matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
- radius /* pivot y */)
+ matrix.setScale(
+ scale /* x scale */,
+ scale /* y scale */,
+ radius /* pivot x */,
+ radius /* pivot y */
+ )
dotPath.transform(matrix)
// Attach BubbleOverflow to BadgedImageView
@@ -132,8 +152,12 @@
}
fun createExpandedView(): BubbleExpandedView? {
- expandedView = inflater.inflate(R.layout.bubble_expanded_view,
- null /* root */, false /* attachToRoot */) as BubbleExpandedView
+ expandedView =
+ inflater.inflate(
+ R.layout.bubble_expanded_view,
+ null /* root */,
+ false /* attachToRoot */
+ ) as BubbleExpandedView
expandedView?.applyThemeAttrs()
updateResources()
return expandedView
@@ -177,11 +201,15 @@
override fun getIconView(): BadgedImageView? {
if (overflowBtn == null) {
- overflowBtn = inflater.inflate(R.layout.bubble_overflow_button,
- null /* root */, false /* attachToRoot */) as BadgedImageView
+ overflowBtn =
+ inflater.inflate(
+ R.layout.bubble_overflow_button,
+ null /* root */,
+ false /* attachToRoot */
+ ) as BadgedImageView
overflowBtn?.initialize(positioner)
- overflowBtn?.contentDescription = context.resources.getString(
- R.string.bubble_overflow_button_content_description)
+ overflowBtn?.contentDescription =
+ context.resources.getString(R.string.bubble_overflow_button_content_description)
val bubbleSize = positioner.bubbleSize
overflowBtn?.layoutParams = FrameLayout.LayoutParams(bubbleSize, bubbleSize)
updateBtnTheme()
@@ -200,4 +228,4 @@
companion object {
const val KEY = "Overflow"
}
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java
index 9aa285f..9655470 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflowContainerView.java
@@ -220,8 +220,8 @@
: res.getColor(R.color.bubbles_light));
final TypedArray typedArray = getContext().obtainStyledAttributes(new int[] {
- android.R.attr.colorBackgroundFloating,
- android.R.attr.textColorSecondary});
+ com.android.internal.R.attr.materialColorSurfaceBright,
+ com.android.internal.R.attr.materialColorOnSurface});
int bgColor = typedArray.getColor(0, isNightMode ? Color.BLACK : Color.WHITE);
int textColor = typedArray.getColor(1, isNightMode ? Color.WHITE : Color.BLACK);
textColor = ContrastColorUtil.ensureTextContrast(textColor, bgColor, isNightMode);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 2afe8ee..b9ff5f0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -282,6 +282,11 @@
/** Whether the expanded view has been hidden, because we are dragging out a bubble. */
private boolean mExpandedViewTemporarilyHidden = false;
+ /**
+ * Whether the last bubble is being removed when expanded, which impacts the collapse animation.
+ */
+ private boolean mRemovingLastBubbleWhileExpanded = false;
+
/** Animator for animating the expanded view's alpha (including the TaskView inside it). */
private final ValueAnimator mExpandedViewAlphaAnimator = ValueAnimator.ofFloat(0f, 1f);
@@ -765,7 +770,7 @@
// Update scrim
if (!mScrimAnimating) {
- showScrim(true);
+ showScrim(true, null /* runnable */);
}
}
}
@@ -880,6 +885,7 @@
final Runnable onBubbleAnimatedOut = () -> {
if (getBubbleCount() == 0) {
+ mExpandedViewTemporarilyHidden = false;
mBubbleController.onAllBubblesAnimatedOut();
}
};
@@ -1773,6 +1779,20 @@
if (DEBUG_BUBBLE_STACK_VIEW) {
Log.d(TAG, "removeBubble: " + bubble);
}
+ if (isExpanded() && getBubbleCount() == 1) {
+ mRemovingLastBubbleWhileExpanded = true;
+ // We're expanded while the last bubble is being removed. Let the scrim animate away
+ // and then remove our views (removing the icon view triggers the removal of the
+ // bubble window so do that at the end of the animation so we see the scrim animate).
+ showScrim(false, () -> {
+ mRemovingLastBubbleWhileExpanded = false;
+ bubble.cleanupExpandedView();
+ mBubbleContainer.removeView(bubble.getIconView());
+ bubble.cleanupViews(); // cleans up the icon view
+ updateExpandedView(); // resets state for no expanded bubble
+ });
+ return;
+ }
// Remove it from the views
for (int i = 0; i < getBubbleCount(); i++) {
View v = mBubbleContainer.getChildAt(i);
@@ -2143,7 +2163,7 @@
mExpandedViewAlphaAnimator.start();
}
- private void showScrim(boolean show) {
+ private void showScrim(boolean show, Runnable after) {
AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
@@ -2153,6 +2173,9 @@
@Override
public void onAnimationEnd(Animator animation) {
mScrimAnimating = false;
+ if (after != null) {
+ after.run();
+ }
}
};
if (show) {
@@ -2179,7 +2202,7 @@
}
beforeExpandedViewAnimation();
- showScrim(true);
+ showScrim(true, null /* runnable */);
updateZOrder();
updateBadges(false /* setBadgeForCollapsedStack */);
mBubbleContainer.setActiveController(mExpandedAnimationController);
@@ -2303,7 +2326,10 @@
mIsExpanded = false;
mIsExpansionAnimating = true;
- showScrim(false);
+ if (!mRemovingLastBubbleWhileExpanded) {
+ // When we remove the last bubble it animates the scrim.
+ showScrim(false, null /* runnable */);
+ }
mBubbleContainer.cancelAllAnimations();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleInfo.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleInfo.java
index b0dea72..d27d05b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleInfo.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/bubbles/BubbleInfo.java
@@ -35,6 +35,7 @@
private String mKey; // Same key as the Notification
private int mFlags; // Flags from BubbleMetadata
+ @Nullable
private String mShortcutId;
private int mUserId;
private String mPackageName;
@@ -46,7 +47,7 @@
@Nullable
private Icon mIcon;
- public BubbleInfo(String key, int flags, String shortcutId, @Nullable Icon icon,
+ public BubbleInfo(String key, int flags, @Nullable String shortcutId, @Nullable Icon icon,
int userId, String packageName) {
mKey = key;
mFlags = flags;
@@ -69,10 +70,12 @@
return mKey;
}
+ @Nullable
public String getShortcutId() {
return mShortcutId;
}
+ @Nullable
public Icon getIcon() {
return mIcon;
}
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 9eba5ec..e7dede7 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
@@ -738,10 +738,6 @@
getRefBounds2(mTempRect);
t.setPosition(leash2, mTempRect.left, mTempRect.top)
.setWindowCrop(leash2, mTempRect.width(), mTempRect.height());
- // Make right or bottom side surface always higher than left or top side to avoid weird
- // animation when dismiss split. e.g. App surface fling above on decor surface.
- t.setLayer(leash1, 1);
- t.setLayer(leash2, 2);
if (mImePositionProcessor.adjustSurfaceLayoutForIme(
t, dividerLeash, leash1, leash2, dimLayer1, dimLayer2)) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogLayout.java
index c53e638..05fd5f1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogLayout.java
@@ -95,6 +95,9 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ final View checkboxContainer = findViewById(
+ R.id.letterbox_restart_dialog_checkbox_container);
+ final CheckBox checkbox = findViewById(R.id.letterbox_restart_dialog_checkbox);
mDialogContainer = findViewById(R.id.letterbox_restart_dialog_container);
mDialogTitle = findViewById(R.id.letterbox_restart_dialog_title);
mBackgroundDim = getBackground().mutate();
@@ -103,5 +106,6 @@
// We add a no-op on-click listener to the dialog container so that clicks on it won't
// propagate to the listener of the layout (which represents the background dim).
mDialogContainer.setOnClickListener(view -> {});
+ checkboxContainer.setOnClickListener(view -> checkbox.performClick());
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
index e9957fd..12d51f5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
@@ -41,11 +41,11 @@
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
-import java.util.Optional;
-
import dagger.Module;
import dagger.Provides;
+import java.util.Optional;
+
/**
* Provides dependencies from {@link com.android.wm.shell}, these dependencies are only
* accessible from components within the WM subcomponent (can be explicitly exposed to the
@@ -81,7 +81,7 @@
DisplayController displayController,
DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController,
- DragAndDropController dragAndDropController,
+ Optional<DragAndDropController> dragAndDropController,
Transitions transitions,
TransactionPool transactionPool,
IconProvider iconProvider,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 9808c59..80e920f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -186,15 +186,15 @@
@WMSingleton
@Provides
- static DragAndDropController provideDragAndDropController(Context context,
+ static Optional<DragAndDropController> provideDragAndDropController(Context context,
ShellInit shellInit,
ShellController shellController,
DisplayController displayController,
UiEventLogger uiEventLogger,
IconProvider iconProvider,
@ShellMainThread ShellExecutor mainExecutor) {
- return new DragAndDropController(context, shellInit, shellController, displayController,
- uiEventLogger, iconProvider, mainExecutor);
+ return Optional.ofNullable(DragAndDropController.create(context, shellInit, shellController,
+ displayController, uiEventLogger, iconProvider, mainExecutor));
}
@WMSingleton
@@ -544,13 +544,14 @@
DisplayController displayController,
@ShellMainThread ShellExecutor mainExecutor,
@ShellMainThread Handler mainHandler,
- @ShellAnimationThread ShellExecutor animExecutor) {
+ @ShellAnimationThread ShellExecutor animExecutor,
+ ShellCommandHandler shellCommandHandler) {
if (!context.getResources().getBoolean(R.bool.config_registerShellTransitionsOnInit)) {
// TODO(b/238217847): Force override shell init if registration is disabled
shellInit = new ShellInit(mainExecutor);
}
return new Transitions(context, shellInit, shellController, organizer, pool,
- displayController, mainExecutor, mainHandler, animExecutor);
+ displayController, mainExecutor, mainHandler, animExecutor, shellCommandHandler);
}
@WMSingleton
@@ -796,7 +797,7 @@
DisplayController displayController,
DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController,
- DragAndDropController dragAndDropController,
+ Optional<DragAndDropController> dragAndDropControllerOptional,
ShellTaskOrganizer shellTaskOrganizer,
Optional<BubbleController> bubblesOptional,
Optional<SplitScreenController> splitScreenOptional,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 2f0f56c..f3130d3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -171,7 +171,7 @@
BubblePositioner positioner,
DisplayController displayController,
@DynamicOverride Optional<OneHandedController> oneHandedOptional,
- DragAndDropController dragAndDropController,
+ Optional<DragAndDropController> dragAndDropController,
@ShellMainThread ShellExecutor mainExecutor,
@ShellMainThread Handler mainHandler,
@ShellBackgroundThread ShellExecutor bgExecutor,
@@ -320,7 +320,7 @@
DisplayController displayController,
DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController,
- DragAndDropController dragAndDropController,
+ Optional<DragAndDropController> dragAndDropController,
Transitions transitions,
TransactionPool transactionPool,
IconProvider iconProvider,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
index 055949f..d1760ed 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
@@ -43,6 +43,12 @@
"persist.wm.debug.desktop_mode_2", false);
/**
+ * Flag to indicate whether task resizing is veiled.
+ */
+ private static final boolean IS_VEILED_RESIZE_ENABLED = SystemProperties.getBoolean(
+ "persist.wm.debug.desktop_veiled_resizing", true);
+
+ /**
* Return {@code true} if desktop mode support is enabled
*/
public static boolean isProto1Enabled() {
@@ -65,6 +71,13 @@
}
/**
+ * Return {@code true} if veiled resizing is active. If false, fluid resizing is used.
+ */
+ public static boolean isVeiledResizeEnabled() {
+ return IS_VEILED_RESIZE_ENABLED;
+ }
+
+ /**
* Check if desktop mode is active
*
* @return {@code true} if active
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index 4cfaae6..091de3a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -94,7 +94,24 @@
void onDragStarted();
}
- public DragAndDropController(Context context,
+ /**
+ * Creates {@link DragAndDropController}. Returns {@code null} if the feature is disabled.
+ */
+ public static DragAndDropController create(Context context,
+ ShellInit shellInit,
+ ShellController shellController,
+ DisplayController displayController,
+ UiEventLogger uiEventLogger,
+ IconProvider iconProvider,
+ ShellExecutor mainExecutor) {
+ if (!context.getResources().getBoolean(R.bool.config_enableShellDragDrop)) {
+ return null;
+ }
+ return new DragAndDropController(context, shellInit, shellController, displayController,
+ uiEventLogger, iconProvider, mainExecutor);
+ }
+
+ DragAndDropController(Context context,
ShellInit shellInit,
ShellController shellController,
DisplayController displayController,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index eb4d2a1..bffc51c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -549,6 +549,14 @@
// are in mOpening.
for (int i = 0; i < closingTasks.size(); ++i) {
final TransitionInfo.Change change = closingTasks.get(i);
+ final int pausingIdx = TaskState.indexOf(mPausingTasks, change);
+ if (pausingIdx >= 0) {
+ mPausingTasks.remove(pausingIdx);
+ didMergeThings = true;
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " closing pausing taskId=%d", change.getTaskInfo().taskId);
+ continue;
+ }
int openingIdx = TaskState.indexOf(mOpeningTasks, change);
if (openingIdx < 0) {
Slog.w(TAG, "Closing a task that wasn't opening, this may be split or"
@@ -601,6 +609,11 @@
didMergeThings = true;
mState = STATE_NEW_TASK;
}
+ if (mPausingTasks.isEmpty()) {
+ // The pausing tasks may be removed by the incoming closing tasks.
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "[%d] RecentsController.merge: empty pausing tasks", mInstanceId);
+ }
if (!hasTaskChange) {
// Activity only transition, so consume the merge as it doesn't affect the rest of
// recents.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 2f25511..af52350 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -165,7 +165,7 @@
private final DisplayController mDisplayController;
private final DisplayImeController mDisplayImeController;
private final DisplayInsetsController mDisplayInsetsController;
- private final DragAndDropController mDragAndDropController;
+ private final Optional<DragAndDropController> mDragAndDropController;
private final Transitions mTransitions;
private final TransactionPool mTransactionPool;
private final IconProvider mIconProvider;
@@ -191,7 +191,7 @@
DisplayController displayController,
DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController,
- DragAndDropController dragAndDropController,
+ Optional<DragAndDropController> dragAndDropController,
Transitions transitions,
TransactionPool transactionPool,
IconProvider iconProvider,
@@ -253,7 +253,7 @@
mDisplayController = displayController;
mDisplayImeController = displayImeController;
mDisplayInsetsController = displayInsetsController;
- mDragAndDropController = dragAndDropController;
+ mDragAndDropController = Optional.of(dragAndDropController);
mTransitions = transitions;
mTransactionPool = transactionPool;
mIconProvider = iconProvider;
@@ -289,7 +289,7 @@
// TODO: Multi-display
mStageCoordinator = createStageCoordinator();
}
- mDragAndDropController.setSplitScreenController(this);
+ mDragAndDropController.ifPresent(controller -> controller.setSplitScreenController(this));
}
protected StageCoordinator createStageCoordinator() {
@@ -460,7 +460,7 @@
}
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
final WindowContainerTransaction evictWct = new WindowContainerTransaction();
mStageCoordinator.prepareEvictInvisibleChildTasks(evictWct);
mSyncQueue.queue(evictWct);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
index 51b8000..a2af93f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
@@ -30,8 +30,6 @@
import static com.android.wm.shell.splitscreen.SplitScreenController.exitReasonToString;
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_DISMISS;
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_DISMISS_SNAP;
-import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE;
-import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -165,7 +163,7 @@
t.setLayer(leash, Integer.MAX_VALUE);
t.show(leash);
}
- boolean isOpening = isOpeningTransition(info);
+ boolean isOpening = TransitionUtil.isOpeningType(info.getType());
if (isOpening && (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT)) {
// fade in
startExampleAnimation(leash, true /* show */);
@@ -295,14 +293,16 @@
@Nullable RemoteTransition remoteTransition,
Transitions.TransitionHandler handler,
@Nullable TransitionConsumedCallback consumedCallback,
- @Nullable TransitionFinishedCallback finishedCallback) {
+ @Nullable TransitionFinishedCallback finishedCallback,
+ int extraTransitType) {
if (mPendingEnter != null) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " splitTransition "
+ " skip to start enter split transition since it already exist. ");
return null;
}
final IBinder transition = mTransitions.startTransition(transitType, wct, handler);
- setEnterTransition(transition, remoteTransition, consumedCallback, finishedCallback);
+ setEnterTransition(transition, remoteTransition, consumedCallback, finishedCallback,
+ extraTransitType);
return transition;
}
@@ -310,9 +310,10 @@
void setEnterTransition(@NonNull IBinder transition,
@Nullable RemoteTransition remoteTransition,
@Nullable TransitionConsumedCallback consumedCallback,
- @Nullable TransitionFinishedCallback finishedCallback) {
+ @Nullable TransitionFinishedCallback finishedCallback,
+ int extraTransitType) {
mPendingEnter = new TransitSession(
- transition, consumedCallback, finishedCallback, remoteTransition);
+ transition, consumedCallback, finishedCallback, remoteTransition, extraTransitType);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " splitTransition "
+ " deduced Enter split screen");
@@ -513,12 +514,6 @@
mTransitions.getAnimExecutor().execute(va::start);
}
- private boolean isOpeningTransition(TransitionInfo info) {
- return TransitionUtil.isOpeningType(info.getType())
- || info.getType() == TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE
- || info.getType() == TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
- }
-
/** Calls when the transition got consumed. */
interface TransitionConsumedCallback {
void onConsumed(boolean aborted);
@@ -539,16 +534,19 @@
/** Whether the transition was canceled. */
boolean mCanceled;
+ /** A note for extra transit type, to help indicate custom transition. */
+ final int mExtraTransitType;
+
TransitSession(IBinder transition,
@Nullable TransitionConsumedCallback consumedCallback,
@Nullable TransitionFinishedCallback finishedCallback) {
- this(transition, consumedCallback, finishedCallback, null /* remoteTransition */);
+ this(transition, consumedCallback, finishedCallback, null /* remoteTransition */, 0);
}
TransitSession(IBinder transition,
@Nullable TransitionConsumedCallback consumedCallback,
@Nullable TransitionFinishedCallback finishedCallback,
- @Nullable RemoteTransition remoteTransition) {
+ @Nullable RemoteTransition remoteTransition, int extraTransitType) {
mTransition = transition;
mConsumedCallback = consumedCallback;
mFinishedCallback = finishedCallback;
@@ -560,6 +558,7 @@
mTransitions.getMainExecutor(), remoteTransition);
mRemoteHandler.setTransition(transition);
}
+ mExtraTransitType = extraTransitType;
}
/** Sets transition consumed callback. */
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 49e8227..0ef26fc 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
@@ -446,26 +446,10 @@
RemoteAnimationTarget[] wallpapers,
RemoteAnimationTarget[] nonApps,
final IRemoteAnimationFinishedCallback finishedCallback) {
- boolean openingToSide = false;
- if (apps != null) {
- for (int i = 0; i < apps.length; ++i) {
- if (apps[i].mode == MODE_OPENING
- && mSideStage.containsTask(apps[i].taskId)) {
- openingToSide = true;
- break;
- }
- }
- } else if (mSideStage.getChildCount() != 0) {
- // There are chances the entering app transition got canceled by performing
- // rotation transition. Checks if there is any child task existed in split
- // screen before fallback to cancel entering flow.
- openingToSide = true;
- }
-
- if (isEnteringSplit && !openingToSide) {
+ if (isEnteringSplit && mSideStage.getChildCount() == 0) {
mMainExecutor.execute(() -> exitSplitScreen(
- mSideStage.getChildCount() == 0 ? mMainStage : mSideStage,
- EXIT_REASON_UNKNOWN));
+ null /* childrenToTop */, EXIT_REASON_UNKNOWN));
+ mSplitUnsupportedToast.show();
}
if (finishedCallback != null) {
@@ -483,7 +467,7 @@
}
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
if (isEnteringSplit) {
mMainExecutor.execute(() -> exitSplitScreen(
mSideStage.getChildCount() == 0 ? mMainStage : mSideStage,
@@ -526,17 +510,17 @@
wct.sendPendingIntent(intent, fillInIntent, options);
// If split screen is not activated, we're expecting to open a pair of apps to split.
- final int transitType = mMainStage.isActive()
+ final int extraTransitType = mMainStage.isActive()
? TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE : TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
prepareEnterSplitScreen(wct, null /* taskInfo */, position);
- mSplitTransitions.startEnterTransition(transitType, wct, null, this,
+ mSplitTransitions.startEnterTransition(TRANSIT_TO_FRONT, wct, null, this,
null /* consumedCallback */,
(finishWct, finishT) -> {
if (!evictWct.isEmpty()) {
finishWct.merge(evictWct, true);
}
- } /* finishedCallback */);
+ } /* finishedCallback */, extraTransitType);
}
/** Launches an activity into split by legacy transition. */
@@ -550,26 +534,10 @@
RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
IRemoteAnimationFinishedCallback finishedCallback,
SurfaceControl.Transaction t) {
- boolean openingToSide = false;
- if (apps != null) {
- for (int i = 0; i < apps.length; ++i) {
- if (apps[i].mode == MODE_OPENING
- && mSideStage.containsTask(apps[i].taskId)) {
- openingToSide = true;
- break;
- }
- }
- } else if (mSideStage.getChildCount() != 0) {
- // There are chances the entering app transition got canceled by performing
- // rotation transition. Checks if there is any child task existed in split
- // screen before fallback to cancel entering flow.
- openingToSide = true;
- }
-
- if (isEnteringSplit && !openingToSide && apps != null) {
+ if (isEnteringSplit && mSideStage.getChildCount() == 0) {
mMainExecutor.execute(() -> exitSplitScreen(
- mSideStage.getChildCount() == 0 ? mMainStage : mSideStage,
- EXIT_REASON_UNKNOWN));
+ null /* childrenToTop */, EXIT_REASON_UNKNOWN));
+ mSplitUnsupportedToast.show();
}
if (apps != null) {
@@ -709,7 +677,8 @@
wct.startTask(mainTaskId, mainOptions);
mSplitTransitions.startEnterTransition(
- TRANSIT_SPLIT_SCREEN_PAIR_OPEN, wct, remoteTransition, this, null, null);
+ TRANSIT_TO_FRONT, wct, remoteTransition, this, null, null,
+ TRANSIT_SPLIT_SCREEN_PAIR_OPEN);
setEnterInstanceId(instanceId);
}
@@ -760,7 +729,8 @@
}
mSplitTransitions.startEnterTransition(
- TRANSIT_SPLIT_SCREEN_PAIR_OPEN, wct, remoteTransition, this, null, null);
+ TRANSIT_TO_FRONT, wct, remoteTransition, this, null, null,
+ TRANSIT_SPLIT_SCREEN_PAIR_OPEN);
setEnterInstanceId(instanceId);
}
@@ -869,7 +839,7 @@
onRemoteAnimationFinished(apps);
t.apply();
try {
- adapter.getRunner().onAnimationCancelled(mKeyguardShowing);
+ adapter.getRunner().onAnimationCancelled();
} catch (RemoteException e) {
Slog.e(TAG, "Error starting remote animation", e);
}
@@ -1013,11 +983,11 @@
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
onRemoteAnimationFinishedOrCancelled(evictWct);
setDividerVisibility(true, null);
try {
- adapter.getRunner().onAnimationCancelled(isKeyguardOccluded);
+ adapter.getRunner().onAnimationCancelled();
} catch (RemoteException e) {
Slog.e(TAG, "Error starting remote animation", e);
}
@@ -1038,7 +1008,7 @@
onRemoteAnimationFinished(apps);
t.apply();
try {
- adapter.getRunner().onAnimationCancelled(mKeyguardShowing);
+ adapter.getRunner().onAnimationCancelled();
} catch (RemoteException e) {
Slog.e(TAG, "Error starting remote animation", e);
}
@@ -1088,7 +1058,7 @@
private void onRemoteAnimationFinishedOrCancelled(WindowContainerTransaction evictWct) {
mIsDividerRemoteAnimating = false;
mShouldUpdateRecents = true;
- mSplitRequest = null;
+ clearRequestIfPresented();
// If any stage has no child after animation finished, it means that split will display
// nothing, such status will happen if task and intent is same app but not support
// multi-instance, we should exit split and expand that app as full screen.
@@ -1108,7 +1078,7 @@
private void onRemoteAnimationFinished(RemoteAnimationTarget[] apps) {
mIsDividerRemoteAnimating = false;
mShouldUpdateRecents = true;
- mSplitRequest = null;
+ clearRequestIfPresented();
// If any stage has no child after finished animation, that side of the split will display
// nothing. This might happen if starting the same app on the both sides while not
// supporting multi-instance. Exit the split screen and expand that app to full screen.
@@ -1381,6 +1351,7 @@
});
mShouldUpdateRecents = false;
mIsDividerRemoteAnimating = false;
+ mSplitRequest = null;
mSplitLayout.getInvisibleBounds(mTempRect1);
if (childrenToTop == null || childrenToTop.getTopVisibleChildTaskId() == INVALID_TASK_ID) {
@@ -1473,6 +1444,13 @@
}
}
+ private void clearRequestIfPresented() {
+ if (mSideStageListener.mVisible && mSideStageListener.mHasChildren
+ && mMainStageListener.mVisible && mSideStageListener.mHasChildren) {
+ mSplitRequest = null;
+ }
+ }
+
/**
* Returns whether the split pair in the recent tasks list should be broken.
*/
@@ -1851,6 +1829,7 @@
true /* setReparentLeafTaskIfRelaunch */);
setRootForceTranslucent(true, wct);
} else {
+ clearRequestIfPresented();
wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
false /* setReparentLeafTaskIfRelaunch */);
setRootForceTranslucent(false, wct);
@@ -2010,7 +1989,7 @@
}
if (mMainStageListener.mHasChildren && mSideStageListener.mHasChildren) {
mShouldUpdateRecents = true;
- mSplitRequest = null;
+ clearRequestIfPresented();
updateRecentTasksSplitPair();
if (!mLogger.hasStartedSession()) {
@@ -2334,7 +2313,8 @@
out = new WindowContainerTransaction();
prepareEnterSplitScreen(out);
mSplitTransitions.setEnterTransition(transition, request.getRemoteTransition(),
- null /* consumedCallback */, null /* finishedCallback */);
+ null /* consumedCallback */, null /* finishedCallback */,
+ 0 /* extraTransitType */);
}
}
return out;
@@ -2573,7 +2553,8 @@
}
}
- if (info.getType() == TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE) {
+ if (mSplitTransitions.mPendingEnter.mExtraTransitType
+ == TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE) {
if (mainChild == null && sideChild == null) {
Log.w(TAG, "Launched a task in split, but didn't receive any task in transition.");
mSplitTransitions.mPendingEnter.cancel(null /* finishedCb */);
@@ -2716,6 +2697,7 @@
}
});
mShouldUpdateRecents = false;
+ mSplitRequest = null;
// Update local states.
setSplitsVisible(false);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index ead0bcd..a841b7f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -220,20 +220,12 @@
mCallbacks.onNoLongerSupportMultiWindow();
return;
}
- if (taskInfo.topActivity == null && mChildrenTaskInfo.contains(taskInfo.taskId)
- && mChildrenTaskInfo.get(taskInfo.taskId).topActivity != null) {
- // If top activity become null, it means the task is about to vanish, we use this
- // signal to remove it from children list earlier for smooth dismiss transition.
- mChildrenTaskInfo.remove(taskInfo.taskId);
- mChildrenLeashes.remove(taskInfo.taskId);
- } else {
- mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
- }
+ mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
mCallbacks.onChildTaskStatusChanged(taskInfo.taskId, true /* present */,
taskInfo.isVisible);
- if (!ENABLE_SHELL_TRANSITIONS && mChildrenLeashes.contains(taskInfo.taskId)) {
- updateChildTaskSurface(taskInfo, mChildrenLeashes.get(taskInfo.taskId),
- false /* firstAppeared */);
+ if (!ENABLE_SHELL_TRANSITIONS) {
+ updateChildTaskSurface(
+ taskInfo, mChildrenLeashes.get(taskInfo.taskId), false /* firstAppeared */);
}
} else {
throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
@@ -267,6 +259,9 @@
return;
}
sendStatusChanged();
+ } else {
+ throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
+ + "\n mRootTaskInfo: " + mRootTaskInfo);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
index 46d2a5a..27d520d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
@@ -72,7 +72,7 @@
DisplayController displayController,
DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController,
- DragAndDropController dragAndDropController,
+ Optional<DragAndDropController> dragAndDropController,
Transitions transitions,
TransactionPool transactionPool,
IconProvider iconProvider,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/LegacyTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/LegacyTransitions.java
index 61e92f3..61e11e8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/LegacyTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/LegacyTransitions.java
@@ -107,7 +107,7 @@
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException {
+ public void onAnimationCancelled() throws RemoteException {
mCancelled = true;
mApps = mWallpapers = mNonApps = null;
checkApply();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
index 5b7231c..ef2a511 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
@@ -94,9 +94,11 @@
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
- if (!Transitions.SHELL_TRANSITIONS_ROTATION && TransitionUtil.hasDisplayChange(info)) {
+ if (!Transitions.SHELL_TRANSITIONS_ROTATION && TransitionUtil.hasDisplayChange(info)
+ && !TransitionUtil.alwaysReportToKeyguard(info)) {
// Note that if the remote doesn't have permission ACCESS_SURFACE_FLINGER, some
// operations of the start transaction may be ignored.
+ mRequestedRemotes.remove(transition);
return false;
}
RemoteTransition pendingRemote = mRequestedRemotes.get(transition);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java
new file mode 100644
index 0000000..9d7c39f
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Tracer.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.transition;
+
+import static android.os.Build.IS_USER;
+
+import static com.android.wm.shell.WmShellTransitionTraceProto.MAGIC_NUMBER;
+import static com.android.wm.shell.WmShellTransitionTraceProto.MAGIC_NUMBER_H;
+import static com.android.wm.shell.WmShellTransitionTraceProto.MAGIC_NUMBER_L;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.SystemClock;
+import android.os.Trace;
+import android.util.Log;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.util.TraceBuffer;
+import com.android.wm.shell.sysui.ShellCommandHandler;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Helper class to collect and dump transition traces.
+ */
+public class Tracer implements ShellCommandHandler.ShellCommandActionHandler {
+ private static final int ALWAYS_ON_TRACING_CAPACITY = 15 * 1024; // 15 KB
+ private static final int ACTIVE_TRACING_BUFFER_CAPACITY = 5000 * 1024; // 5 MB
+
+ private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
+
+ static final String WINSCOPE_EXT = ".winscope";
+ private static final String TRACE_FILE =
+ "/data/misc/wmtrace/shell_transition_trace" + WINSCOPE_EXT;
+
+ private final Object mEnabledLock = new Object();
+ private boolean mActiveTracingEnabled = false;
+
+ private final TraceBuffer mTraceBuffer = new TraceBuffer(ALWAYS_ON_TRACING_CAPACITY,
+ (proto) -> handleOnEntryRemovedFromTrace(proto));
+ private final Map<Object, Runnable> mRemovedFromTraceCallbacks = new HashMap<>();
+
+ private final Map<Transitions.TransitionHandler, Integer> mHandlerIds = new HashMap<>();
+ private final Map<Transitions.TransitionHandler, Integer> mHandlerUseCountInTrace =
+ new HashMap<>();
+
+ /**
+ * Adds an entry in the trace to log that a transition has been dispatched to a handler.
+ *
+ * @param transitionId The id of the transition being dispatched.
+ * @param handler The handler the transition is being dispatched to.
+ */
+ public void logDispatched(int transitionId, Transitions.TransitionHandler handler) {
+ final int handlerId;
+ if (mHandlerIds.containsKey(handler)) {
+ handlerId = mHandlerIds.get(handler);
+ } else {
+ handlerId = mHandlerIds.size();
+ mHandlerIds.put(handler, handlerId);
+ }
+
+ ProtoOutputStream outputStream = new ProtoOutputStream();
+ final long protoToken =
+ outputStream.start(com.android.wm.shell.WmShellTransitionTraceProto.TRANSITIONS);
+
+ outputStream.write(com.android.wm.shell.Transition.ID, transitionId);
+ outputStream.write(com.android.wm.shell.Transition.DISPATCH_TIME_NS,
+ SystemClock.elapsedRealtimeNanos());
+ outputStream.write(com.android.wm.shell.Transition.HANDLER, handlerId);
+
+ outputStream.end(protoToken);
+
+ final int useCountAfterAdd = mHandlerUseCountInTrace.getOrDefault(handler, 0) + 1;
+ mHandlerUseCountInTrace.put(handler, useCountAfterAdd);
+
+ mRemovedFromTraceCallbacks.put(outputStream, () -> {
+ final int useCountAfterRemove = mHandlerUseCountInTrace.get(handler) - 1;
+ mHandlerUseCountInTrace.put(handler, useCountAfterRemove);
+ });
+
+ mTraceBuffer.add(outputStream);
+ }
+
+ /**
+ * Adds an entry in the trace to log that a request to merge a transition was made.
+ *
+ * @param mergeRequestedTransitionId The id of the transition we are requesting to be merged.
+ * @param playingTransitionId The id of the transition we was to merge the transition into.
+ */
+ public void logMergeRequested(int mergeRequestedTransitionId, int playingTransitionId) {
+ ProtoOutputStream outputStream = new ProtoOutputStream();
+ final long protoToken =
+ outputStream.start(com.android.wm.shell.WmShellTransitionTraceProto.TRANSITIONS);
+
+ outputStream.write(com.android.wm.shell.Transition.ID, mergeRequestedTransitionId);
+ outputStream.write(com.android.wm.shell.Transition.MERGE_REQUEST_TIME_NS,
+ SystemClock.elapsedRealtimeNanos());
+ outputStream.write(com.android.wm.shell.Transition.MERGED_INTO, playingTransitionId);
+
+ outputStream.end(protoToken);
+
+ mTraceBuffer.add(outputStream);
+ }
+
+ /**
+ * Adds an entry in the trace to log that a transition was merged by the handler.
+ *
+ * @param mergedTransitionId The id of the transition that was merged.
+ * @param playingTransitionId The id of the transition the transition was merged into.
+ */
+ public void logMerged(int mergedTransitionId, int playingTransitionId) {
+ ProtoOutputStream outputStream = new ProtoOutputStream();
+ final long protoToken =
+ outputStream.start(com.android.wm.shell.WmShellTransitionTraceProto.TRANSITIONS);
+
+ outputStream.write(com.android.wm.shell.Transition.ID, mergedTransitionId);
+ outputStream.write(
+ com.android.wm.shell.Transition.MERGE_TIME_NS, SystemClock.elapsedRealtimeNanos());
+ outputStream.write(com.android.wm.shell.Transition.MERGED_INTO, playingTransitionId);
+
+ outputStream.end(protoToken);
+
+ mTraceBuffer.add(outputStream);
+ }
+
+ /**
+ * Adds an entry in the trace to log that a transition was aborted.
+ *
+ * @param transitionId The id of the transition that was aborted.
+ */
+ public void logAborted(int transitionId) {
+ ProtoOutputStream outputStream = new ProtoOutputStream();
+ final long protoToken =
+ outputStream.start(com.android.wm.shell.WmShellTransitionTraceProto.TRANSITIONS);
+
+ outputStream.write(com.android.wm.shell.Transition.ID, transitionId);
+ outputStream.write(
+ com.android.wm.shell.Transition.ABORT_TIME_NS, SystemClock.elapsedRealtimeNanos());
+
+ outputStream.end(protoToken);
+
+ mTraceBuffer.add(outputStream);
+ }
+
+ /**
+ * Starts collecting transitions for the trace.
+ * If called while a trace is already running, this will reset the trace.
+ */
+ public void startTrace(@Nullable PrintWriter pw) {
+ if (IS_USER) {
+ LogAndPrintln.e(pw, "Tracing is not supported on user builds.");
+ return;
+ }
+ Trace.beginSection("Tracer#startTrace");
+ LogAndPrintln.i(pw, "Starting shell transition trace.");
+ synchronized (mEnabledLock) {
+ mActiveTracingEnabled = true;
+ mTraceBuffer.resetBuffer();
+ mTraceBuffer.setCapacity(ACTIVE_TRACING_BUFFER_CAPACITY);
+ }
+ Trace.endSection();
+ }
+
+ /**
+ * Stops collecting the transition trace and dump to trace to file.
+ *
+ * Dumps the trace to @link{TRACE_FILE}.
+ */
+ public void stopTrace(@Nullable PrintWriter pw) {
+ stopTrace(pw, new File(TRACE_FILE));
+ }
+
+ /**
+ * Stops collecting the transition trace and dump to trace to file.
+ * @param outputFile The file to dump the transition trace to.
+ */
+ public void stopTrace(@Nullable PrintWriter pw, File outputFile) {
+ if (IS_USER) {
+ LogAndPrintln.e(pw, "Tracing is not supported on user builds.");
+ return;
+ }
+ Trace.beginSection("Tracer#stopTrace");
+ LogAndPrintln.i(pw, "Stopping shell transition trace.");
+ synchronized (mEnabledLock) {
+ mActiveTracingEnabled = false;
+ writeTraceToFileLocked(pw, outputFile);
+ mTraceBuffer.resetBuffer();
+ mTraceBuffer.setCapacity(ALWAYS_ON_TRACING_CAPACITY);
+ }
+ Trace.endSection();
+ }
+
+ /**
+ * Being called while taking a bugreport so that tracing files can be included in the bugreport.
+ *
+ * @param pw Print writer
+ */
+ public void saveForBugreport(@Nullable PrintWriter pw) {
+ if (IS_USER) {
+ LogAndPrintln.e(pw, "Tracing is not supported on user builds.");
+ return;
+ }
+ Trace.beginSection("TransitionTracer#saveForBugreport");
+ synchronized (mEnabledLock) {
+ final File outputFile = new File(TRACE_FILE);
+ writeTraceToFileLocked(pw, outputFile);
+ }
+ Trace.endSection();
+ }
+
+ private void writeTraceToFileLocked(@Nullable PrintWriter pw, File file) {
+ Trace.beginSection("TransitionTracer#writeTraceToFileLocked");
+ try {
+ ProtoOutputStream proto = new ProtoOutputStream();
+ proto.write(MAGIC_NUMBER, MAGIC_NUMBER_VALUE);
+ writeHandlerMappingToProto(proto);
+ int pid = android.os.Process.myPid();
+ LogAndPrintln.i(pw, "Writing file to " + file.getAbsolutePath()
+ + " from process " + pid);
+ mTraceBuffer.writeTraceToFile(file, proto);
+ } catch (IOException e) {
+ LogAndPrintln.e(pw, "Unable to write buffer to file", e);
+ }
+ Trace.endSection();
+ }
+
+ private void writeHandlerMappingToProto(ProtoOutputStream outputStream) {
+ for (Transitions.TransitionHandler handler : mHandlerUseCountInTrace.keySet()) {
+ final int count = mHandlerUseCountInTrace.get(handler);
+ if (count > 0) {
+ final long protoToken = outputStream.start(
+ com.android.wm.shell.WmShellTransitionTraceProto.HANDLER_MAPPINGS);
+ outputStream.write(com.android.wm.shell.HandlerMapping.ID,
+ mHandlerIds.get(handler));
+ outputStream.write(com.android.wm.shell.HandlerMapping.NAME,
+ handler.getClass().getName());
+ outputStream.end(protoToken);
+ }
+ }
+ }
+
+ private void handleOnEntryRemovedFromTrace(Object proto) {
+ if (mRemovedFromTraceCallbacks.containsKey(proto)) {
+ mRemovedFromTraceCallbacks.get(proto).run();
+ mRemovedFromTraceCallbacks.remove(proto);
+ }
+ }
+
+ @Override
+ public boolean onShellCommand(String[] args, PrintWriter pw) {
+ switch (args[0]) {
+ case "start": {
+ startTrace(pw);
+ return true;
+ }
+ case "stop": {
+ stopTrace(pw);
+ return true;
+ }
+ case "save-for-bugreport": {
+ saveForBugreport(pw);
+ return true;
+ }
+ default: {
+ pw.println("Invalid command: " + args[0]);
+ printShellCommandHelp(pw, "");
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public void printShellCommandHelp(PrintWriter pw, String prefix) {
+ pw.println(prefix + "start");
+ pw.println(prefix + " Start tracing the transitions.");
+ pw.println(prefix + "stop");
+ pw.println(prefix + " Stop tracing the transitions.");
+ pw.println(prefix + "save-for-bugreport");
+ pw.println(prefix + " Flush in memory transition trace to file.");
+ }
+
+ private static class LogAndPrintln {
+ private static final String LOG_TAG = "ShellTransitionTracer";
+
+ private static void i(@Nullable PrintWriter pw, String msg) {
+ Log.i(LOG_TAG, msg);
+ if (pw != null) {
+ pw.println(msg);
+ pw.flush();
+ }
+ }
+
+ private static void e(@Nullable PrintWriter pw, String msg) {
+ Log.e(LOG_TAG, msg);
+ if (pw != null) {
+ pw.println("ERROR: " + msg);
+ pw.flush();
+ }
+ }
+
+ private static void e(@Nullable PrintWriter pw, String msg, @NonNull Exception e) {
+ Log.e(LOG_TAG, msg, e);
+ if (pw != null) {
+ pw.println("ERROR: " + msg + " ::\n " + e);
+ pw.flush();
+ }
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 5c8791e..f79f1f7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -74,10 +74,12 @@
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
+import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.util.TransitionUtil;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -106,7 +108,8 @@
* track, it will be marked as SYNC. This means that all currently active tracks must be flushed
* before the SYNC transition can play.
*/
-public class Transitions implements RemoteCallable<Transitions> {
+public class Transitions implements RemoteCallable<Transitions>,
+ ShellCommandHandler.ShellCommandActionHandler {
static final String TAG = "ShellTransitions";
/** Set to {@code true} to enable shell transitions. */
@@ -165,12 +168,15 @@
private final ShellController mShellController;
private final ShellTransitionImpl mImpl = new ShellTransitionImpl();
private final SleepHandler mSleepHandler = new SleepHandler();
-
+ private final Tracer mTracer = new Tracer();
private boolean mIsRegistered = false;
/** List of possible handlers. Ordered by specificity (eg. tapped back to front). */
private final ArrayList<TransitionHandler> mHandlers = new ArrayList<>();
+ @Nullable
+ private final ShellCommandHandler mShellCommandHandler;
+
private final ArrayList<TransitionObserver> mObservers = new ArrayList<>();
/** List of {@link Runnable} instances to run when the last active transition has finished. */
@@ -246,8 +252,23 @@
@NonNull WindowOrganizer organizer,
@NonNull TransactionPool pool,
@NonNull DisplayController displayController,
- @NonNull ShellExecutor mainExecutor, @NonNull Handler mainHandler,
+ @NonNull ShellExecutor mainExecutor,
+ @NonNull Handler mainHandler,
@NonNull ShellExecutor animExecutor) {
+ this(context, shellInit, shellController, organizer, pool, displayController, mainExecutor,
+ mainHandler, animExecutor, null);
+ }
+
+ public Transitions(@NonNull Context context,
+ @NonNull ShellInit shellInit,
+ @NonNull ShellController shellController,
+ @NonNull WindowOrganizer organizer,
+ @NonNull TransactionPool pool,
+ @NonNull DisplayController displayController,
+ @NonNull ShellExecutor mainExecutor,
+ @NonNull Handler mainHandler,
+ @NonNull ShellExecutor animExecutor,
+ @Nullable ShellCommandHandler shellCommandHandler) {
mOrganizer = organizer;
mContext = context;
mMainExecutor = mainExecutor;
@@ -263,6 +284,7 @@
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "addHandler: Default");
// Next lowest priority is remote transitions.
mHandlers.add(mRemoteTransitionHandler);
+ mShellCommandHandler = shellCommandHandler;
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "addHandler: Remote");
shellInit.addInitCallback(this::onInit, this);
}
@@ -294,6 +316,10 @@
// Pre-load the instance.
TransitionMetrics.getInstance();
}
+
+ if (mShellCommandHandler != null) {
+ mShellCommandHandler.addCommandCallback("transitions", this, this);
+ }
}
public boolean isRegistered() {
@@ -650,7 +676,7 @@
active.mToken, info, active.mStartT, active.mFinishT);
}
- if (info.getRootCount() == 0 && !alwaysReportToKeyguard(info)) {
+ if (info.getRootCount() == 0 && !TransitionUtil.alwaysReportToKeyguard(info)) {
// No root-leashes implies that the transition is empty/no-op, so just do
// housekeeping and return.
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "No transition roots in %s so"
@@ -699,23 +725,6 @@
return true;
}
- /**
- * Some transitions we always need to report to keyguard even if they are empty.
- * TODO (b/274954192): Remove this once keyguard dispatching moves to Shell.
- */
- private static boolean alwaysReportToKeyguard(TransitionInfo info) {
- // occlusion status of activities can change while screen is off so there will be no
- // visibility change but we still need keyguardservice to be notified.
- if (info.getType() == TRANSIT_KEYGUARD_UNOCCLUDE) return true;
-
- // It's possible for some activities to stop with bad timing (esp. since we can't yet
- // queue activity transitions initiated by apps) that results in an empty transition for
- // keyguard going-away. In general, we should should always report Keyguard-going-away.
- if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) return true;
-
- return false;
- }
-
private boolean areTracksIdle() {
for (int i = 0; i < mTracks.size(); ++i) {
if (!mTracks.get(i).isIdle()) return false;
@@ -783,6 +792,7 @@
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition %s ready while"
+ " %s is still animating. Notify the animating transition"
+ " in case they can be merged", ready, playing);
+ mTracer.logMergeRequested(ready.mInfo.getDebugId(), playing.mInfo.getDebugId());
playing.mHandler.mergeAnimation(ready.mToken, ready.mInfo, ready.mStartT,
playing.mToken, (wct, cb) -> onMerged(playing, ready));
}
@@ -816,6 +826,7 @@
for (int i = 0; i < mObservers.size(); ++i) {
mObservers.get(i).onTransitionMerged(merged.mToken, playing.mToken);
}
+ mTracer.logMerged(merged.mInfo.getDebugId(), playing.mInfo.getDebugId());
// See if we should merge another transition.
processReadyQueue(track);
}
@@ -842,6 +853,8 @@
// Otherwise give every other handler a chance
active.mHandler = dispatchTransition(active.mToken, active.mInfo, active.mStartT,
active.mFinishT, (wct, cb) -> onFinish(active, wct, cb), active.mHandler);
+
+ mTracer.logDispatched(active.mInfo.getDebugId(), active.mHandler);
}
/**
@@ -893,6 +906,8 @@
transition.mFinishT.apply();
transition.mAborted = true;
+ mTracer.logAborted(transition.mInfo.getDebugId());
+
if (transition.mHandler != null) {
// Notifies to clean-up the aborted transition.
transition.mHandler.onTransitionConsumed(
@@ -1367,4 +1382,26 @@
mMainExecutor.execute(() -> dispatchAnimScaleSetting(mTransitionAnimationScaleSetting));
}
}
+
+
+ @Override
+ public boolean onShellCommand(String[] args, PrintWriter pw) {
+ switch (args[0]) {
+ case "tracing": {
+ mTracer.onShellCommand(Arrays.copyOfRange(args, 1, args.length), pw);
+ return true;
+ }
+ default: {
+ pw.println("Invalid command: " + args[0]);
+ printShellCommandHelp(pw, "");
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public void printShellCommandHelp(PrintWriter pw, String prefix) {
+ pw.println(prefix + "tracing");
+ mTracer.printShellCommandHelp(pw, prefix + " ");
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
index ce10291..c5cd2d9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
@@ -24,7 +24,9 @@
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -77,6 +79,23 @@
return false;
}
+ /**
+ * Some transitions we always need to report to keyguard even if they are empty.
+ * TODO (b/274954192): Remove this once keyguard dispatching moves to Shell.
+ */
+ public static boolean alwaysReportToKeyguard(TransitionInfo info) {
+ // occlusion status of activities can change while screen is off so there will be no
+ // visibility change but we still need keyguardservice to be notified.
+ if (info.getType() == TRANSIT_KEYGUARD_UNOCCLUDE) return true;
+
+ // It's possible for some activities to stop with bad timing (esp. since we can't yet
+ // queue activity transitions initiated by apps) that results in an empty transition for
+ // keyguard going-away. In general, we should should always report Keyguard-going-away.
+ if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) return true;
+
+ return false;
+ }
+
/** Returns `true` if `change` is a wallpaper. */
public static boolean isWallpaper(TransitionInfo.Change change) {
return (change.getTaskInfo() == null)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index e8a6a15..212ad9e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -185,8 +185,8 @@
mSyncQueue);
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
- final TaskPositioner taskPositioner =
- new TaskPositioner(mTaskOrganizer, windowDecoration, mDisplayController);
+ final FluidResizeTaskPositioner taskPositioner =
+ new FluidResizeTaskPositioner(mTaskOrganizer, windowDecoration, mDisplayController);
final CaptionTouchEventListener touchEventListener =
new CaptionTouchEventListener(taskInfo, taskPositioner);
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 8fb56fc..4ef3350 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -101,7 +101,7 @@
private final SparseArray<DesktopModeWindowDecoration> mWindowDecorByTaskId =
new SparseArray<>();
- private final DragListenerImpl mDragStartListener = new DragListenerImpl();
+ private final DragStartListenerImpl mDragStartListener = new DragStartListenerImpl();
private final InputMonitorFactory mInputMonitorFactory;
private TaskOperations mTaskOperations;
private final Supplier<SurfaceControl.Transaction> mTransactionFactory;
@@ -777,21 +777,32 @@
mSyncQueue);
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
- final TaskPositioner taskPositioner =
- new TaskPositioner(mTaskOrganizer, windowDecoration, mDisplayController,
- mDragStartListener);
+ final DragPositioningCallback dragPositioningCallback;
+ if (!DesktopModeStatus.isVeiledResizeEnabled()) {
+ dragPositioningCallback =
+ new FluidResizeTaskPositioner(mTaskOrganizer, windowDecoration,
+ mDisplayController, mDragStartListener);
+ } else {
+ windowDecoration.createResizeVeil();
+ dragPositioningCallback =
+ new VeiledResizeTaskPositioner(mTaskOrganizer, windowDecoration,
+ mDisplayController, mDragStartListener);
+ }
final DesktopModeTouchEventListener touchEventListener =
- new DesktopModeTouchEventListener(taskInfo, taskPositioner);
+ new DesktopModeTouchEventListener(taskInfo, dragPositioningCallback);
+
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
windowDecoration.setCornersListener(mCornersListener);
- windowDecoration.setDragPositioningCallback(taskPositioner);
+ windowDecoration.setDragPositioningCallback(dragPositioningCallback);
windowDecoration.setDragDetector(touchEventListener.mDragDetector);
windowDecoration.relayout(taskInfo, startT, finishT,
false /* applyStartTransactionOnDraw */);
incrementEventReceiverTasks(taskInfo.displayId);
}
- private class DragListenerImpl implements TaskPositioner.DragStartListener {
+
+ private class DragStartListenerImpl
+ implements DragPositioningCallbackUtility.DragStartListener {
@Override
public void onDragStart(int taskId) {
mWindowDecorByTaskId.get(taskId).closeHandleMenu();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index f9fdd83..b1c3791 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -23,8 +23,10 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
+import android.content.res.TypedArray;
import android.graphics.Point;
import android.graphics.PointF;
+import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.os.Handler;
@@ -72,31 +74,15 @@
new WindowDecoration.RelayoutResult<>();
private final Point mPositionInParent = new Point();
- private final PointF mHandleMenuAppInfoPillPosition = new PointF();
- private final PointF mHandleMenuWindowingPillPosition = new PointF();
- private final PointF mHandleMenuMoreActionsPillPosition = new PointF();
-
- // Collection of additional windows that comprise the handle menu.
- private AdditionalWindow mHandleMenuAppInfoPill;
- private AdditionalWindow mHandleMenuWindowingPill;
- private AdditionalWindow mHandleMenuMoreActionsPill;
private HandleMenu mHandleMenu;
+ private ResizeVeil mResizeVeil;
+
private Drawable mAppIcon;
private CharSequence mAppName;
private TaskCornersListener mCornersListener;
- private int mMenuWidth;
- private int mMarginMenuTop;
- private int mMarginMenuStart;
- private int mMarginMenuSpacing;
- private int mAppInfoPillHeight;
- private int mWindowingPillHeight;
- private int mMoreActionsPillHeight;
- private int mShadowRadius;
- private int mCornerRadius;
-
DesktopModeWindowDecoration(
Context context,
DisplayController displayController,
@@ -182,6 +168,11 @@
mRelayoutParams.mShadowRadiusId = shadowRadiusID;
mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
+ final TypedArray ta = mContext.obtainStyledAttributes(
+ new int[]{android.R.attr.dialogCornerRadius});
+ mRelayoutParams.mCornerRadius = ta.getDimensionPixelSize(0, 0);
+ ta.recycle();
+
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
// After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
@@ -280,6 +271,42 @@
}
/**
+ * Create the resize veil for this task. Note the veil's visibility is View.GONE by default
+ * until a resize event calls showResizeVeil below.
+ */
+ void createResizeVeil() {
+ mResizeVeil = new ResizeVeil(mContext, mAppIcon, mTaskInfo,
+ mSurfaceControlBuilderSupplier, mDisplay, mSurfaceControlTransactionSupplier);
+ }
+
+ /**
+ * Fade in the resize veil
+ */
+ void showResizeVeil() {
+ mResizeVeil.showVeil(mTaskSurface);
+ }
+
+ /**
+ * Set new bounds for the resize veil
+ */
+ void updateResizeVeil(Rect newBounds) {
+ mResizeVeil.relayout(newBounds);
+ }
+
+ /**
+ * Fade the resize veil out.
+ */
+ void hideResizeVeil() {
+ mResizeVeil.hideVeil();
+ }
+
+ private void disposeResizeVeil() {
+ if (mResizeVeil == null) return;
+ mResizeVeil.dispose();
+ mResizeVeil = null;
+ }
+
+ /**
* Create and display handle menu window
*/
void createHandleMenu() {
@@ -406,6 +433,7 @@
closeDragResizeListener();
closeHandleMenu();
mCornersListener.onTaskCornersRemoved(mTaskInfo.taskId);
+ disposeResizeVeil();
super.close();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java
index 0191c60..4e98f0c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallback.java
@@ -16,19 +16,29 @@
package com.android.wm.shell.windowdecor;
+import android.annotation.IntDef;
+
/**
* Callback called when receiving drag-resize or drag-move related input events.
*/
public interface DragPositioningCallback {
+ @IntDef({CTRL_TYPE_UNDEFINED, CTRL_TYPE_LEFT, CTRL_TYPE_RIGHT, CTRL_TYPE_TOP, CTRL_TYPE_BOTTOM})
+ @interface CtrlType {}
+
+ int CTRL_TYPE_UNDEFINED = 0;
+ int CTRL_TYPE_LEFT = 1;
+ int CTRL_TYPE_RIGHT = 2;
+ int CTRL_TYPE_TOP = 4;
+ int CTRL_TYPE_BOTTOM = 8;
/**
* Called when a drag-resize or drag-move starts.
*
- * @param ctrlType {@link TaskPositioner.CtrlType} indicating the direction of resizing, use
+ * @param ctrlType {@link CtrlType} indicating the direction of resizing, use
* {@code 0} to indicate it's a move
* @param x x coordinate in window decoration coordinate system where the drag starts
* @param y y coordinate in window decoration coordinate system where the drag starts
*/
- void onDragPositioningStart(@TaskPositioner.CtrlType int ctrlType, float x, float y);
+ void onDragPositioningStart(@CtrlType int ctrlType, float x, float y);
/**
* Called when the pointer moves during a drag-resize or drag-move.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
new file mode 100644
index 0000000..ae93a43
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragPositioningCallbackUtility.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.windowdecor;
+
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_LEFT;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_UNDEFINED;
+
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.util.DisplayMetrics;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
+
+/**
+ * Utility class that contains logic common to classes implementing {@link DragPositioningCallback}
+ * Specifically, this class contains logic for determining changed bounds from a drag input
+ * and applying that change to the task bounds when applicable.
+ */
+public class DragPositioningCallbackUtility {
+
+ /**
+ * Determine the delta between input's current point and the input start point.
+ * @param inputX current input x coordinate
+ * @param inputY current input y coordinate
+ * @param repositionStartPoint initial input coordinate
+ * @return delta between these two points
+ */
+ static PointF calculateDelta(float inputX, float inputY, PointF repositionStartPoint) {
+ final float deltaX = inputX - repositionStartPoint.x;
+ final float deltaY = inputY - repositionStartPoint.y;
+ return new PointF(deltaX, deltaY);
+ }
+
+ /**
+ * Based on type of drag and delta provided, calculate the new bounds to display for this task.
+ * @param ctrlType type of drag being performed
+ * @param hasMoved whether the current drag has moved on a prior input event
+ * @param repositionTaskBounds the bounds the task is being repositioned to
+ * @param taskBoundsAtDragStart the bounds of the task on the first drag input event
+ * @param stableBounds bounds that represent the resize limit of this task
+ * @param delta difference between start input and current input in x/y coordinates
+ * @param displayController task's display controller
+ * @param windowDecoration window decoration of the task being dragged
+ * @return whether this method changed repositionTaskBounds
+ */
+ static boolean changeBounds(int ctrlType, boolean hasMoved,
+ Rect repositionTaskBounds, Rect taskBoundsAtDragStart, Rect stableBounds,
+ PointF delta, DisplayController displayController, WindowDecoration windowDecoration) {
+ // |mRepositionTaskBounds| is the bounds last reported if |mHasMoved| is true. If it's not
+ // true, we can compare it against |mTaskBoundsAtDragStart|.
+ final int oldLeft = hasMoved ? repositionTaskBounds.left : taskBoundsAtDragStart.left;
+ final int oldTop = hasMoved ? repositionTaskBounds.top : taskBoundsAtDragStart.top;
+ final int oldRight = hasMoved ? repositionTaskBounds.right : taskBoundsAtDragStart.right;
+ final int oldBottom =
+ hasMoved ? repositionTaskBounds.bottom : taskBoundsAtDragStart.bottom;
+
+
+ repositionTaskBounds.set(taskBoundsAtDragStart);
+
+ // Make sure the new resizing destination in any direction falls within the stable bounds.
+ // If not, set the bounds back to the old location that was valid to avoid conflicts with
+ // some regions such as the gesture area.
+ displayController.getDisplayLayout(windowDecoration.mDisplay.getDisplayId())
+ .getStableBounds(stableBounds);
+ if ((ctrlType & CTRL_TYPE_LEFT) != 0) {
+ final int candidateLeft = repositionTaskBounds.left + (int) delta.x;
+ repositionTaskBounds.left = (candidateLeft > stableBounds.left)
+ ? candidateLeft : oldLeft;
+ }
+ if ((ctrlType & CTRL_TYPE_RIGHT) != 0) {
+ final int candidateRight = repositionTaskBounds.right + (int) delta.x;
+ repositionTaskBounds.right = (candidateRight < stableBounds.right)
+ ? candidateRight : oldRight;
+ }
+ if ((ctrlType & CTRL_TYPE_TOP) != 0) {
+ final int candidateTop = repositionTaskBounds.top + (int) delta.y;
+ repositionTaskBounds.top = (candidateTop > stableBounds.top)
+ ? candidateTop : oldTop;
+ }
+ if ((ctrlType & CTRL_TYPE_BOTTOM) != 0) {
+ final int candidateBottom = repositionTaskBounds.bottom + (int) delta.y;
+ repositionTaskBounds.bottom = (candidateBottom < stableBounds.bottom)
+ ? candidateBottom : oldBottom;
+ }
+ if (ctrlType == CTRL_TYPE_UNDEFINED) {
+ repositionTaskBounds.offset((int) delta.x, (int) delta.y);
+ }
+
+ // If width or height are negative or less than the minimum width or height, revert the
+ // respective bounds to use previous bound dimensions.
+ if (repositionTaskBounds.width() < getMinWidth(displayController, windowDecoration)) {
+ repositionTaskBounds.right = oldRight;
+ repositionTaskBounds.left = oldLeft;
+ }
+ if (repositionTaskBounds.height() < getMinHeight(displayController, windowDecoration)) {
+ repositionTaskBounds.top = oldTop;
+ repositionTaskBounds.bottom = oldBottom;
+ }
+ // If there are no changes to the bounds after checking new bounds against minimum width
+ // and height, do not set bounds and return false
+ if (oldLeft == repositionTaskBounds.left && oldTop == repositionTaskBounds.top
+ && oldRight == repositionTaskBounds.right
+ && oldBottom == repositionTaskBounds.bottom) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Apply a bounds change to a task.
+ * @param wct provided {@link WindowContainerTransaction} that may contain other changes
+ * @param windowDecoration decor of task we are changing bounds for
+ * @param taskBounds new bounds of this task
+ * @param taskOrganizer applies the provided WindowContainerTransaction
+ */
+ static void applyTaskBoundsChange(WindowContainerTransaction wct,
+ WindowDecoration windowDecoration, Rect taskBounds, ShellTaskOrganizer taskOrganizer) {
+ wct.setBounds(windowDecoration.mTaskInfo.token, taskBounds);
+ taskOrganizer.applyTransaction(wct);
+ }
+
+ private static float getMinWidth(DisplayController displayController,
+ WindowDecoration windowDecoration) {
+ return windowDecoration.mTaskInfo.minWidth < 0 ? getDefaultMinSize(displayController,
+ windowDecoration)
+ : windowDecoration.mTaskInfo.minWidth;
+ }
+
+ private static float getMinHeight(DisplayController displayController,
+ WindowDecoration windowDecoration) {
+ return windowDecoration.mTaskInfo.minHeight < 0 ? getDefaultMinSize(displayController,
+ windowDecoration)
+ : windowDecoration.mTaskInfo.minHeight;
+ }
+
+ private static float getDefaultMinSize(DisplayController displayController,
+ WindowDecoration windowDecoration) {
+ float density = displayController.getDisplayLayout(windowDecoration.mTaskInfo.displayId)
+ .densityDpi() * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+ return windowDecoration.mTaskInfo.defaultMinSize * density;
+ }
+
+ interface DragStartListener {
+ /**
+ * Inform the implementing class that a drag resize has started
+ * @param taskId id of this positioner's {@link WindowDecoration}
+ */
+ void onDragStart(int taskId);
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
index 34c8c08..287d861 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
@@ -21,6 +21,11 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_LEFT;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT;
+import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP;
+
import android.content.Context;
import android.graphics.Rect;
import android.graphics.Region;
@@ -367,7 +372,7 @@
return calculateResizeHandlesCtrlType(x, y) != 0;
}
- @TaskPositioner.CtrlType
+ @DragPositioningCallback.CtrlType
private int calculateCtrlType(boolean isTouch, float x, float y) {
if (isTouch) {
return calculateCornersCtrlType(x, y);
@@ -375,62 +380,62 @@
return calculateResizeHandlesCtrlType(x, y);
}
- @TaskPositioner.CtrlType
+ @DragPositioningCallback.CtrlType
private int calculateResizeHandlesCtrlType(float x, float y) {
int ctrlType = 0;
if (x < 0) {
- ctrlType |= TaskPositioner.CTRL_TYPE_LEFT;
+ ctrlType |= CTRL_TYPE_LEFT;
}
if (x > mTaskWidth) {
- ctrlType |= TaskPositioner.CTRL_TYPE_RIGHT;
+ ctrlType |= CTRL_TYPE_RIGHT;
}
if (y < 0) {
- ctrlType |= TaskPositioner.CTRL_TYPE_TOP;
+ ctrlType |= CTRL_TYPE_TOP;
}
if (y > mTaskHeight) {
- ctrlType |= TaskPositioner.CTRL_TYPE_BOTTOM;
+ ctrlType |= CTRL_TYPE_BOTTOM;
}
return ctrlType;
}
- @TaskPositioner.CtrlType
+ @DragPositioningCallback.CtrlType
private int calculateCornersCtrlType(float x, float y) {
int xi = (int) x;
int yi = (int) y;
if (mLeftTopCornerBounds.contains(xi, yi)) {
- return TaskPositioner.CTRL_TYPE_LEFT | TaskPositioner.CTRL_TYPE_TOP;
+ return CTRL_TYPE_LEFT | CTRL_TYPE_TOP;
}
if (mLeftBottomCornerBounds.contains(xi, yi)) {
- return TaskPositioner.CTRL_TYPE_LEFT | TaskPositioner.CTRL_TYPE_BOTTOM;
+ return CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM;
}
if (mRightTopCornerBounds.contains(xi, yi)) {
- return TaskPositioner.CTRL_TYPE_RIGHT | TaskPositioner.CTRL_TYPE_TOP;
+ return CTRL_TYPE_RIGHT | CTRL_TYPE_TOP;
}
if (mRightBottomCornerBounds.contains(xi, yi)) {
- return TaskPositioner.CTRL_TYPE_RIGHT | TaskPositioner.CTRL_TYPE_BOTTOM;
+ return CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM;
}
return 0;
}
private void updateCursorType(float x, float y) {
- @TaskPositioner.CtrlType int ctrlType = calculateResizeHandlesCtrlType(x, y);
+ @DragPositioningCallback.CtrlType int ctrlType = calculateResizeHandlesCtrlType(x, y);
int cursorType = PointerIcon.TYPE_DEFAULT;
switch (ctrlType) {
- case TaskPositioner.CTRL_TYPE_LEFT:
- case TaskPositioner.CTRL_TYPE_RIGHT:
+ case CTRL_TYPE_LEFT:
+ case CTRL_TYPE_RIGHT:
cursorType = PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
break;
- case TaskPositioner.CTRL_TYPE_TOP:
- case TaskPositioner.CTRL_TYPE_BOTTOM:
+ case CTRL_TYPE_TOP:
+ case CTRL_TYPE_BOTTOM:
cursorType = PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
break;
- case TaskPositioner.CTRL_TYPE_LEFT | TaskPositioner.CTRL_TYPE_TOP:
- case TaskPositioner.CTRL_TYPE_RIGHT | TaskPositioner.CTRL_TYPE_BOTTOM:
+ case CTRL_TYPE_LEFT | CTRL_TYPE_TOP:
+ case CTRL_TYPE_RIGHT | CTRL_TYPE_BOTTOM:
cursorType = PointerIcon.TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW;
break;
- case TaskPositioner.CTRL_TYPE_LEFT | TaskPositioner.CTRL_TYPE_BOTTOM:
- case TaskPositioner.CTRL_TYPE_RIGHT | TaskPositioner.CTRL_TYPE_TOP:
+ case CTRL_TYPE_LEFT | CTRL_TYPE_BOTTOM:
+ case CTRL_TYPE_RIGHT | CTRL_TYPE_TOP:
cursorType = PointerIcon.TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW;
break;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
new file mode 100644
index 0000000..b366c80
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositioner.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.windowdecor;
+
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
+
+/**
+ * A task positioner that resizes/relocates task contents as it is dragged.
+ * Utilizes {@link DragPositioningCallbackUtility} to determine new task bounds.
+ */
+class FluidResizeTaskPositioner implements DragPositioningCallback {
+ private final ShellTaskOrganizer mTaskOrganizer;
+ private final WindowDecoration mWindowDecoration;
+ private DisplayController mDisplayController;
+ private DragPositioningCallbackUtility.DragStartListener mDragStartListener;
+ private final Rect mStableBounds = new Rect();
+ private final Rect mTaskBoundsAtDragStart = new Rect();
+ private final PointF mRepositionStartPoint = new PointF();
+ private final Rect mRepositionTaskBounds = new Rect();
+ private int mCtrlType;
+ private boolean mHasMoved;
+
+ FluidResizeTaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
+ DisplayController displayController) {
+ this(taskOrganizer, windowDecoration, displayController, dragStartListener -> {});
+ }
+
+ FluidResizeTaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
+ DisplayController displayController,
+ DragPositioningCallbackUtility.DragStartListener dragStartListener) {
+ mTaskOrganizer = taskOrganizer;
+ mWindowDecoration = windowDecoration;
+ mDisplayController = displayController;
+ mDragStartListener = dragStartListener;
+ }
+
+ @Override
+ public void onDragPositioningStart(int ctrlType, float x, float y) {
+ mCtrlType = ctrlType;
+ mTaskBoundsAtDragStart.set(
+ mWindowDecoration.mTaskInfo.configuration.windowConfiguration.getBounds());
+ mRepositionStartPoint.set(x, y);
+ mDragStartListener.onDragStart(mWindowDecoration.mTaskInfo.taskId);
+ }
+
+ @Override
+ public void onDragPositioningMove(float x, float y) {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ PointF delta = DragPositioningCallbackUtility.calculateDelta(x, y, mRepositionStartPoint);
+ if (DragPositioningCallbackUtility.changeBounds(mCtrlType, mHasMoved,
+ mRepositionTaskBounds, mTaskBoundsAtDragStart, mStableBounds, delta,
+ mDisplayController, mWindowDecoration)) {
+ // The task is being resized, send the |dragResizing| hint to core with the first
+ // bounds-change wct.
+ if (!mHasMoved && mCtrlType != CTRL_TYPE_UNDEFINED) {
+ // This is the first bounds change since drag resize operation started.
+ wct.setDragResizing(mWindowDecoration.mTaskInfo.token, true /* dragResizing */);
+ }
+ DragPositioningCallbackUtility.applyTaskBoundsChange(wct, mWindowDecoration,
+ mRepositionTaskBounds, mTaskOrganizer);
+ mHasMoved = true;
+ }
+ }
+
+ @Override
+ public void onDragPositioningEnd(float x, float y) {
+ // |mHasMoved| being false means there is no real change to the task bounds in WM core, so
+ // we don't need a WCT to finish it.
+ if (mHasMoved) {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.setDragResizing(mWindowDecoration.mTaskInfo.token, false /* dragResizing */);
+ PointF delta = DragPositioningCallbackUtility.calculateDelta(x, y,
+ mRepositionStartPoint);
+ if (DragPositioningCallbackUtility.changeBounds(mCtrlType, mHasMoved,
+ mRepositionTaskBounds, mTaskBoundsAtDragStart, mStableBounds, delta,
+ mDisplayController, mWindowDecoration)) {
+ wct.setBounds(mWindowDecoration.mTaskInfo.token, mRepositionTaskBounds);
+ }
+ mTaskOrganizer.applyTransaction(wct);
+ }
+
+ mTaskBoundsAtDragStart.setEmpty();
+ mRepositionStartPoint.set(0, 0);
+ mCtrlType = CTRL_TYPE_UNDEFINED;
+ mHasMoved = false;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
new file mode 100644
index 0000000..fa2d7a8
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.windowdecor;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.Display;
+import android.view.LayoutInflater;
+import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowlessWindowManager;
+import android.widget.ImageView;
+import android.window.TaskConstants;
+
+import com.android.wm.shell.R;
+
+import java.util.function.Supplier;
+
+/**
+ * Creates and updates a veil that covers task contents on resize.
+ */
+public class ResizeVeil {
+ private static final int RESIZE_ALPHA_DURATION = 200;
+ private final Context mContext;
+ private final Supplier<SurfaceControl.Builder> mSurfaceControlBuilderSupplier;
+ private final Supplier<SurfaceControl.Transaction> mSurfaceControlTransactionSupplier;
+ private final Drawable mAppIcon;
+ private SurfaceControl mParentSurface;
+ private SurfaceControl mVeilSurface;
+ private final RunningTaskInfo mTaskInfo;
+ private SurfaceControlViewHost mViewHost;
+ private final Display mDisplay;
+
+ public ResizeVeil(Context context, Drawable appIcon, RunningTaskInfo taskInfo,
+ Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier, Display display,
+ Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier) {
+ mContext = context;
+ mAppIcon = appIcon;
+ mSurfaceControlBuilderSupplier = surfaceControlBuilderSupplier;
+ mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier;
+ mTaskInfo = taskInfo;
+ mDisplay = display;
+ setupResizeVeil();
+ }
+
+ /**
+ * Create the veil in its default invisible state.
+ */
+ private void setupResizeVeil() {
+ SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
+ final SurfaceControl.Builder builder = mSurfaceControlBuilderSupplier.get();
+ mVeilSurface = builder
+ .setName("Resize veil of Task= " + mTaskInfo.taskId)
+ .setContainerLayer()
+ .build();
+ View v = LayoutInflater.from(mContext)
+ .inflate(R.layout.desktop_mode_resize_veil, null);
+
+ t.setPosition(mVeilSurface, 0, 0)
+ .setLayer(mVeilSurface, TaskConstants.TASK_CHILD_LAYER_RESIZE_VEIL)
+ .apply();
+ Rect taskBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
+ final WindowManager.LayoutParams lp =
+ new WindowManager.LayoutParams(taskBounds.width(),
+ taskBounds.height(),
+ WindowManager.LayoutParams.TYPE_APPLICATION,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ PixelFormat.TRANSPARENT);
+ lp.setTitle("Resize veil of Task=" + mTaskInfo.taskId);
+ lp.setTrustedOverlay();
+ WindowlessWindowManager windowManager = new WindowlessWindowManager(mTaskInfo.configuration,
+ mVeilSurface, null /* hostInputToken */);
+ mViewHost = new SurfaceControlViewHost(mContext, mDisplay, windowManager, "ResizeVeil");
+ mViewHost.setView(v, lp);
+
+ final ImageView appIcon = mViewHost.getView().findViewById(R.id.veil_application_icon);
+ appIcon.setImageDrawable(mAppIcon);
+ }
+
+ /**
+ * Animate veil's alpha to 1, fading it in.
+ */
+ public void showVeil(SurfaceControl parentSurface) {
+ // Parent surface can change, ensure it is up to date.
+ SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
+ if (!parentSurface.equals(mParentSurface)) {
+ t.reparent(mVeilSurface, parentSurface);
+ mParentSurface = parentSurface;
+ }
+ t.show(mVeilSurface)
+ .apply();
+ final ValueAnimator animator = new ValueAnimator();
+ animator.setFloatValues(0f, 1f);
+ animator.setDuration(RESIZE_ALPHA_DURATION);
+ animator.addUpdateListener(animation -> {
+ t.setAlpha(mVeilSurface, animator.getAnimatedFraction());
+ t.apply();
+ });
+ animator.start();
+ }
+
+ /**
+ * Update veil bounds to match bounds changes.
+ * @param newBounds bounds to update veil to.
+ */
+ public void relayout(Rect newBounds) {
+ SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
+ mViewHost.relayout(newBounds.width(), newBounds.height());
+ t.setWindowCrop(mVeilSurface, newBounds.width(), newBounds.height());
+ t.setPosition(mParentSurface, newBounds.left, newBounds.top);
+ t.setWindowCrop(mParentSurface, newBounds.width(), newBounds.height());
+ mViewHost.getView().getViewRootImpl().applyTransactionOnDraw(t);
+ }
+
+ /**
+ * Animate veil's alpha to 0, fading it out.
+ */
+ public void hideVeil() {
+ final View resizeVeilView = mViewHost.getView();
+ final ValueAnimator animator = new ValueAnimator();
+ animator.setFloatValues(1, 0);
+ animator.setDuration(RESIZE_ALPHA_DURATION);
+ animator.addUpdateListener(animation -> {
+ SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
+ t.setAlpha(mVeilSurface, 1 - animator.getAnimatedFraction());
+ t.apply();
+ });
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
+ t.hide(mVeilSurface);
+ t.apply();
+ }
+ });
+ animator.start();
+ }
+
+ /**
+ * Dispose of veil when it is no longer needed, likely on close of its container decor.
+ */
+ void dispose() {
+ if (mViewHost != null) {
+ mViewHost.release();
+ mViewHost = null;
+ }
+ if (mVeilSurface != null) {
+ final SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get();
+ t.remove(mVeilSurface);
+ mVeilSurface = null;
+ t.apply();
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
deleted file mode 100644
index 0bce3ac..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskPositioner.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.windowdecor;
-
-import android.annotation.IntDef;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.util.DisplayMetrics;
-import android.window.WindowContainerTransaction;
-
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.DisplayController;
-
-class TaskPositioner implements DragPositioningCallback {
-
- @IntDef({CTRL_TYPE_UNDEFINED, CTRL_TYPE_LEFT, CTRL_TYPE_RIGHT, CTRL_TYPE_TOP, CTRL_TYPE_BOTTOM})
- @interface CtrlType {}
-
- static final int CTRL_TYPE_UNDEFINED = 0;
- static final int CTRL_TYPE_LEFT = 1;
- static final int CTRL_TYPE_RIGHT = 2;
- static final int CTRL_TYPE_TOP = 4;
- static final int CTRL_TYPE_BOTTOM = 8;
-
- private final ShellTaskOrganizer mTaskOrganizer;
- private final DisplayController mDisplayController;
- private final WindowDecoration mWindowDecoration;
-
- private final Rect mTempBounds = new Rect();
- private final Rect mTaskBoundsAtDragStart = new Rect();
- private final PointF mRepositionStartPoint = new PointF();
- private final Rect mRepositionTaskBounds = new Rect();
- private boolean mHasMoved = false;
-
- private int mCtrlType;
- private DragStartListener mDragStartListener;
-
- TaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
- DisplayController displayController) {
- this(taskOrganizer, windowDecoration, displayController, dragStartListener -> {});
- }
-
- TaskPositioner(ShellTaskOrganizer taskOrganizer, WindowDecoration windowDecoration,
- DisplayController displayController, DragStartListener dragStartListener) {
- mTaskOrganizer = taskOrganizer;
- mWindowDecoration = windowDecoration;
- mDisplayController = displayController;
- mDragStartListener = dragStartListener;
- }
-
- @Override
- public void onDragPositioningStart(int ctrlType, float x, float y) {
- mHasMoved = false;
-
- mDragStartListener.onDragStart(mWindowDecoration.mTaskInfo.taskId);
- mCtrlType = ctrlType;
-
- mTaskBoundsAtDragStart.set(
- mWindowDecoration.mTaskInfo.configuration.windowConfiguration.getBounds());
- mRepositionStartPoint.set(x, y);
- }
-
- @Override
- public void onDragPositioningMove(float x, float y) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- if (changeBounds(wct, x, y)) {
- // The task is being resized, send the |dragResizing| hint to core with the first
- // bounds-change wct.
- if (!mHasMoved && mCtrlType != CTRL_TYPE_UNDEFINED) {
- // This is the first bounds change since drag resize operation started.
- wct.setDragResizing(mWindowDecoration.mTaskInfo.token, true /* dragResizing */);
- }
- mTaskOrganizer.applyTransaction(wct);
- mHasMoved = true;
- }
- }
-
- @Override
- public void onDragPositioningEnd(float x, float y) {
- // |mHasMoved| being false means there is no real change to the task bounds in WM core, so
- // we don't need a WCT to finish it.
- if (mHasMoved) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- wct.setDragResizing(mWindowDecoration.mTaskInfo.token, false /* dragResizing */);
- changeBounds(wct, x, y);
- mTaskOrganizer.applyTransaction(wct);
- }
-
- mCtrlType = CTRL_TYPE_UNDEFINED;
- mTaskBoundsAtDragStart.setEmpty();
- mRepositionStartPoint.set(0, 0);
- mHasMoved = false;
- }
-
- private boolean changeBounds(WindowContainerTransaction wct, float x, float y) {
- // |mRepositionTaskBounds| is the bounds last reported if |mHasMoved| is true. If it's not
- // true, we can compare it against |mTaskBoundsAtDragStart|.
- final int oldLeft = mHasMoved ? mRepositionTaskBounds.left : mTaskBoundsAtDragStart.left;
- final int oldTop = mHasMoved ? mRepositionTaskBounds.top : mTaskBoundsAtDragStart.top;
- final int oldRight = mHasMoved ? mRepositionTaskBounds.right : mTaskBoundsAtDragStart.right;
- final int oldBottom =
- mHasMoved ? mRepositionTaskBounds.bottom : mTaskBoundsAtDragStart.bottom;
-
- final float deltaX = x - mRepositionStartPoint.x;
- final float deltaY = y - mRepositionStartPoint.y;
- mRepositionTaskBounds.set(mTaskBoundsAtDragStart);
-
- final Rect stableBounds = mTempBounds;
- // Make sure the new resizing destination in any direction falls within the stable bounds.
- // If not, set the bounds back to the old location that was valid to avoid conflicts with
- // some regions such as the gesture area.
- mDisplayController.getDisplayLayout(mWindowDecoration.mDisplay.getDisplayId())
- .getStableBounds(stableBounds);
- if ((mCtrlType & CTRL_TYPE_LEFT) != 0) {
- final int candidateLeft = mRepositionTaskBounds.left + (int) deltaX;
- mRepositionTaskBounds.left = (candidateLeft > stableBounds.left)
- ? candidateLeft : oldLeft;
- }
- if ((mCtrlType & CTRL_TYPE_RIGHT) != 0) {
- final int candidateRight = mRepositionTaskBounds.right + (int) deltaX;
- mRepositionTaskBounds.right = (candidateRight < stableBounds.right)
- ? candidateRight : oldRight;
- }
- if ((mCtrlType & CTRL_TYPE_TOP) != 0) {
- final int candidateTop = mRepositionTaskBounds.top + (int) deltaY;
- mRepositionTaskBounds.top = (candidateTop > stableBounds.top)
- ? candidateTop : oldTop;
- }
- if ((mCtrlType & CTRL_TYPE_BOTTOM) != 0) {
- final int candidateBottom = mRepositionTaskBounds.bottom + (int) deltaY;
- mRepositionTaskBounds.bottom = (candidateBottom < stableBounds.bottom)
- ? candidateBottom : oldBottom;
- }
- if (mCtrlType == CTRL_TYPE_UNDEFINED) {
- mRepositionTaskBounds.offset((int) deltaX, (int) deltaY);
- }
-
- // If width or height are negative or less than the minimum width or height, revert the
- // respective bounds to use previous bound dimensions.
- if (mRepositionTaskBounds.width() < getMinWidth()) {
- mRepositionTaskBounds.right = oldRight;
- mRepositionTaskBounds.left = oldLeft;
- }
- if (mRepositionTaskBounds.height() < getMinHeight()) {
- mRepositionTaskBounds.top = oldTop;
- mRepositionTaskBounds.bottom = oldBottom;
- }
- // If there are no changes to the bounds after checking new bounds against minimum width
- // and height, do not set bounds and return false
- if (oldLeft == mRepositionTaskBounds.left && oldTop == mRepositionTaskBounds.top
- && oldRight == mRepositionTaskBounds.right
- && oldBottom == mRepositionTaskBounds.bottom) {
- return false;
- }
-
- wct.setBounds(mWindowDecoration.mTaskInfo.token, mRepositionTaskBounds);
- return true;
- }
-
- private float getMinWidth() {
- return mWindowDecoration.mTaskInfo.minWidth < 0 ? getDefaultMinSize()
- : mWindowDecoration.mTaskInfo.minWidth;
- }
-
- private float getMinHeight() {
- return mWindowDecoration.mTaskInfo.minHeight < 0 ? getDefaultMinSize()
- : mWindowDecoration.mTaskInfo.minHeight;
- }
-
- private float getDefaultMinSize() {
- float density = mDisplayController.getDisplayLayout(mWindowDecoration.mTaskInfo.displayId)
- .densityDpi() * DisplayMetrics.DENSITY_DEFAULT_SCALE;
- return mWindowDecoration.mTaskInfo.defaultMinSize * density;
- }
-
- interface DragStartListener {
- /**
- * Inform the implementing class that a drag resize has started
- * @param taskId id of this positioner's {@link WindowDecoration}
- */
- void onDragStart(int taskId);
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
new file mode 100644
index 0000000..ef8332f
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositioner.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.windowdecor;
+
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
+
+/**
+ * A task positioner that also takes into account resizing a
+ * {@link com.android.wm.shell.windowdecor.ResizeVeil}.
+ * If the drag is resizing the task, we resize the veil instead.
+ * If the drag is repositioning, we update in the typical manner.
+ */
+public class VeiledResizeTaskPositioner implements DragPositioningCallback {
+
+ private DesktopModeWindowDecoration mDesktopWindowDecoration;
+ private ShellTaskOrganizer mTaskOrganizer;
+ private DisplayController mDisplayController;
+ private DragPositioningCallbackUtility.DragStartListener mDragStartListener;
+ private final Rect mStableBounds = new Rect();
+ private final Rect mTaskBoundsAtDragStart = new Rect();
+ private final PointF mRepositionStartPoint = new PointF();
+ private final Rect mRepositionTaskBounds = new Rect();
+ private int mCtrlType;
+ private boolean mHasMoved;
+
+
+ public VeiledResizeTaskPositioner(ShellTaskOrganizer taskOrganizer,
+ DesktopModeWindowDecoration windowDecoration, DisplayController displayController,
+ DragPositioningCallbackUtility.DragStartListener dragStartListener) {
+ mTaskOrganizer = taskOrganizer;
+ mDesktopWindowDecoration = windowDecoration;
+ mDisplayController = displayController;
+ mDragStartListener = dragStartListener;
+ }
+
+ @Override
+ public void onDragPositioningStart(int ctrlType, float x, float y) {
+ mCtrlType = ctrlType;
+ mTaskBoundsAtDragStart.set(
+ mDesktopWindowDecoration.mTaskInfo.configuration.windowConfiguration.getBounds());
+ mRepositionStartPoint.set(x, y);
+ if (mCtrlType != CTRL_TYPE_UNDEFINED) {
+ mDesktopWindowDecoration.showResizeVeil();
+ }
+ mHasMoved = false;
+ mDragStartListener.onDragStart(mDesktopWindowDecoration.mTaskInfo.taskId);
+ }
+
+ @Override
+ public void onDragPositioningMove(float x, float y) {
+ PointF delta = DragPositioningCallbackUtility.calculateDelta(x, y, mRepositionStartPoint);
+ if (DragPositioningCallbackUtility.changeBounds(mCtrlType, mHasMoved,
+ mRepositionTaskBounds, mTaskBoundsAtDragStart, mStableBounds, delta,
+ mDisplayController, mDesktopWindowDecoration)) {
+ if (mCtrlType != CTRL_TYPE_UNDEFINED) {
+ mDesktopWindowDecoration.updateResizeVeil(mRepositionTaskBounds);
+ } else {
+ DragPositioningCallbackUtility.applyTaskBoundsChange(
+ new WindowContainerTransaction(), mDesktopWindowDecoration,
+ mRepositionTaskBounds, mTaskOrganizer);
+ }
+ mHasMoved = true;
+ }
+ }
+
+ @Override
+ public void onDragPositioningEnd(float x, float y) {
+ PointF delta = DragPositioningCallbackUtility.calculateDelta(x, y,
+ mRepositionStartPoint);
+ if (mHasMoved && DragPositioningCallbackUtility.changeBounds(mCtrlType, mHasMoved,
+ mRepositionTaskBounds, mTaskBoundsAtDragStart, mStableBounds, delta,
+ mDisplayController, mDesktopWindowDecoration)) {
+ DragPositioningCallbackUtility.applyTaskBoundsChange(
+ new WindowContainerTransaction(), mDesktopWindowDecoration,
+ mRepositionTaskBounds, mTaskOrganizer);
+ }
+ // TODO: (b/279062291) Synchronize the start of hide to the end of the draw triggered above.
+ if (mCtrlType != CTRL_TYPE_UNDEFINED) {
+ mDesktopWindowDecoration.updateResizeVeil(mRepositionTaskBounds);
+ mDesktopWindowDecoration.hideResizeVeil();
+ }
+ mCtrlType = CTRL_TYPE_UNDEFINED;
+ mTaskBoundsAtDragStart.setEmpty();
+ mRepositionStartPoint.set(0, 0);
+ mHasMoved = false;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index e772fc2..ac5ff20 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -16,6 +16,8 @@
package com.android.wm.shell.windowdecor;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.res.Configuration;
@@ -256,13 +258,17 @@
mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f;
mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f;
mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
- Point taskPosition = mTaskInfo.positionInParent;
+ final Point taskPosition = mTaskInfo.positionInParent;
startT.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight)
.setShadowRadius(mTaskSurface, shadowRadius)
.setColor(mTaskSurface, mTmpColor)
.show(mTaskSurface);
finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight);
+ if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+ startT.setCornerRadius(mTaskSurface, params.mCornerRadius);
+ finishT.setCornerRadius(mTaskSurface, params.mCornerRadius);
+ }
if (mCaptionWindowManager == null) {
// Put caption under a container surface because ViewRootImpl sets the destination frame
@@ -414,6 +420,8 @@
int mCaptionWidthId;
int mShadowRadiusId;
+ int mCornerRadius;
+
int mCaptionX;
int mCaptionY;
@@ -425,6 +433,8 @@
mCaptionWidthId = Resources.ID_NULL;
mShadowRadiusId = Resources.ID_NULL;
+ mCornerRadius = 0;
+
mCaptionX = 0;
mCaptionY = 0;
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
index c5ee7b7..86edc25 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
@@ -18,7 +18,7 @@
import android.app.Instrumentation
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerBuilderProvider
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index 45024f3..798cc95 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -20,9 +20,9 @@
import android.tools.common.Rotation
import android.tools.common.datatypes.Region
-import android.tools.common.datatypes.component.IComponentMatcher
import android.tools.common.flicker.subject.layers.LayerTraceEntrySubject
import android.tools.common.flicker.subject.layers.LayersTraceSubject
+import android.tools.common.traces.component.IComponentMatcher
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.helpers.WindowUtils
@@ -218,11 +218,11 @@
assertLayers {
if (landscapePosLeft) {
splitAppLayerBoundsSnapToDivider(
- component,
- landscapePosLeft,
- portraitPosTop,
- scenario.endRotation
- )
+ component,
+ landscapePosLeft,
+ portraitPosTop,
+ scenario.endRotation
+ )
} else {
splitAppLayerBoundsSnapToDivider(
component,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
index 983640a..3bc1e2a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
@@ -18,7 +18,7 @@
package com.android.wm.shell.flicker
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui"
const val LAUNCHER_UI_PACKAGE_NAME = "com.google.android.apps.nexuslauncher"
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
index d01a0ee..11c5951 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
@@ -20,11 +20,11 @@
import android.system.helpers.CommandsHelper
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
-import com.android.wm.shell.flicker.BaseTest
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.LetterboxAppHelper
import android.tools.device.flicker.legacy.FlickerTestFactory
import android.tools.device.flicker.legacy.IFlickerTestData
+import com.android.server.wm.flicker.helpers.LetterboxAppHelper
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.wm.shell.flicker.BaseTest
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.appWindowIsVisibleAtStart
import org.junit.Assume
@@ -104,8 +104,8 @@
/**
* Creates the test configurations.
*
- * See [FlickerTestFactory.rotationTests] for configuring screen orientation and
- * navigation modes.
+ * See [FlickerTestFactory.rotationTests] for configuring screen orientation and navigation
+ * modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
index c57100e..f212a4e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
@@ -17,11 +17,11 @@
package com.android.wm.shell.flicker.appcompat
import android.platform.test.annotations.Postsubmit
-import androidx.test.filters.RequiresDevice
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import androidx.test.filters.RequiresDevice
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -35,13 +35,13 @@
* ```
* Rotate non resizable portrait only app to opposite orientation to trigger size compat mode
* ```
+ *
* Notes:
* ```
* Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [BaseTest]
* ```
*/
-
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -86,4 +86,4 @@
.isInvisible(ComponentNameMatcher.ROTATION)
}
}
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt
index f111a8d..8e75439 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt
@@ -17,11 +17,11 @@
package com.android.wm.shell.flicker.appcompat
import android.platform.test.annotations.Postsubmit
-import androidx.test.filters.RequiresDevice
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.helpers.WindowUtils
+import androidx.test.filters.RequiresDevice
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -36,13 +36,13 @@
* Rotate app to opposite orientation to trigger size compat mode
* Press restart button and wait for letterboxed app to resize
* ```
+ *
* Notes:
* ```
* Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [BaseTest]
* ```
*/
-
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -56,9 +56,7 @@
teardown { letterboxApp.exit(wmHelper) }
}
- @Postsubmit
- @Test
- fun appVisibleAtStartAndEnd() = assertLetterboxAppVisibleAtStartAndEnd()
+ @Postsubmit @Test fun appVisibleAtStartAndEnd() = assertLetterboxAppVisibleAtStartAndEnd()
@Postsubmit
@Test
@@ -83,4 +81,4 @@
val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.endRotation)
flicker.assertLayersEnd { visibleRegion(letterboxApp).coversAtMost(displayBounds) }
}
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
index 18a3aa7..889e177 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
@@ -149,9 +149,7 @@
@Ignore("Not applicable to this CUJ. Taskbar is not shown on lock screen")
override fun taskBarWindowIsAlwaysVisible() {}
- /**
- * Checks that the [ComponentNameMatcher.TASK_BAR] is visible at the end of the transition
- */
+ /** Checks that the [ComponentNameMatcher.TASK_BAR] is visible at the end of the transition */
@Postsubmit
@Test
fun taskBarLayerIsVisibleAtEnd() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
index 59918fb..e6544c9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
@@ -17,7 +17,7 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
index 36c6f7c..2417c45 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.LAUNCHER
+import android.tools.common.traces.component.ComponentNameMatcher.Companion.LAUNCHER
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.flicker.legacy.FlickerTestFactory
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
index db18edb..4b461370 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
@@ -21,7 +21,7 @@
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
index 51f0136..bfd5778 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.flicker.legacy.FlickerTestFactory
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
index 2001f48..5ac9829 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.flicker.legacy.FlickerTestFactory
import com.android.server.wm.flicker.helpers.SimpleAppHelper
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
index 6deba1b..bbb1c6c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
index a626713..6b061bbb 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
index b30f308..eb1245b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
@@ -20,7 +20,7 @@
import android.content.Intent
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
index 0c9c161..d53eac0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
@@ -19,8 +19,8 @@
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.common.datatypes.component.EdgeExtensionComponentMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.common.traces.component.EdgeExtensionComponentMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
index 625987a..1063dfd 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
@@ -19,9 +19,9 @@
import android.app.Instrumentation
import android.graphics.Point
import android.os.SystemClock
-import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.common.datatypes.component.IComponentMatcher
-import android.tools.common.datatypes.component.IComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.common.traces.component.IComponentMatcher
+import android.tools.common.traces.component.IComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.WindowManagerStateHelper
import android.tools.device.traces.parsers.toFlickerComponent
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java
index de967bf..afec1ee 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java
@@ -33,6 +33,7 @@
import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.os.Bundle;
+import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -42,6 +43,7 @@
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.bubbles.BubbleInfo;
import org.junit.Before;
import org.junit.Test;
@@ -77,7 +79,7 @@
Intent target = new Intent(mContext, BubblesTestActivity.class);
Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder(
PendingIntent.getActivity(mContext, 0, target, PendingIntent.FLAG_MUTABLE),
- Icon.createWithResource(mContext, R.drawable.bubble_ic_create_bubble))
+ Icon.createWithResource(mContext, R.drawable.bubble_ic_create_bubble))
.build();
when(mSbn.getNotification()).thenReturn(mNotif);
when(mNotif.getBubbleMetadata()).thenReturn(metadata);
@@ -179,6 +181,34 @@
assertThat(bubble.isConversation()).isFalse();
}
+ @Test
+ public void testBubbleAsBubbleBarBubble_withShortcut() {
+ Bubble bubble = createBubbleWithShortcut();
+ BubbleInfo bubbleInfo = bubble.asBubbleBarBubble();
+
+ assertThat(bubble.getShortcutInfo()).isNotNull();
+ assertThat(bubbleInfo.getShortcutId()).isNotNull();
+ assertThat(bubbleInfo.getShortcutId()).isEqualTo(bubble.getShortcutId());
+ assertThat(bubbleInfo.getKey()).isEqualTo(bubble.getKey());
+ assertThat(bubbleInfo.getUserId()).isEqualTo(bubble.getUser().getIdentifier());
+ assertThat(bubbleInfo.getPackageName()).isEqualTo(bubble.getPackageName());
+ }
+
+ @Test
+ public void testBubbleAsBubbleBarBubble_withoutShortcut() {
+ Intent intent = new Intent(mContext, BubblesTestActivity.class);
+ intent.setPackage(mContext.getPackageName());
+ Bubble bubble = Bubble.createAppBubble(intent, new UserHandle(1 /* userId */),
+ null /* icon */, mMainExecutor);
+ BubbleInfo bubbleInfo = bubble.asBubbleBarBubble();
+
+ assertThat(bubble.getShortcutInfo()).isNull();
+ assertThat(bubbleInfo.getShortcutId()).isNull();
+ assertThat(bubbleInfo.getKey()).isEqualTo(bubble.getKey());
+ assertThat(bubbleInfo.getUserId()).isEqualTo(bubble.getUser().getIdentifier());
+ assertThat(bubbleInfo.getPackageName()).isEqualTo(bubble.getPackageName());
+ }
+
private Bubble createBubbleWithShortcut() {
ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(mContext)
.setId("mockShortcutId")
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index a9f311f..92cbf7f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -180,8 +180,9 @@
TestRemoteTransition testRemote = new TestRemoteTransition();
IBinder transition = mSplitScreenTransitions.startEnterTransition(
- TRANSIT_SPLIT_SCREEN_PAIR_OPEN, new WindowContainerTransaction(),
- new RemoteTransition(testRemote, "Test"), mStageCoordinator, null, null);
+ TRANSIT_OPEN, new WindowContainerTransaction(),
+ new RemoteTransition(testRemote, "Test"), mStageCoordinator, null, null,
+ TRANSIT_SPLIT_SCREEN_PAIR_OPEN);
mMainStage.onTaskAppeared(mMainChild, createMockSurface());
mSideStage.onTaskAppeared(mSideChild, createMockSurface());
boolean accepted = mStageCoordinator.startAnimation(transition, info,
@@ -397,7 +398,7 @@
}
private TransitionInfo createEnterPairInfo() {
- return new TransitionInfoBuilder(TRANSIT_SPLIT_SCREEN_PAIR_OPEN, 0)
+ return new TransitionInfoBuilder(TRANSIT_OPEN, 0)
.addChange(TRANSIT_OPEN, mMainChild)
.addChange(TRANSIT_OPEN, mSideChild)
.build();
@@ -406,9 +407,9 @@
private void enterSplit() {
TransitionInfo enterInfo = createEnterPairInfo();
IBinder enterTransit = mSplitScreenTransitions.startEnterTransition(
- TRANSIT_SPLIT_SCREEN_PAIR_OPEN, new WindowContainerTransaction(),
+ TRANSIT_OPEN, new WindowContainerTransaction(),
new RemoteTransition(new TestRemoteTransition(), "Test"),
- mStageCoordinator, null, null);
+ mStageCoordinator, null, null, TRANSIT_SPLIT_SCREEN_PAIR_OPEN);
mMainStage.onTaskAppeared(mMainChild, createMockSurface());
mSideStage.onTaskAppeared(mSideChild, createMockSurface());
mStageCoordinator.startAnimation(enterTransit, enterInfo,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
index 784ad9b..1a1bebd 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
@@ -126,6 +126,12 @@
verify(mCallbacks).onStatusChanged(eq(mRootTask.isVisible), eq(true));
}
+ @Test(expected = IllegalArgumentException.class)
+ public void testUnknownTaskVanished() {
+ final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
+ mStageTaskListener.onTaskVanished(task);
+ }
+
@Test
public void testTaskVanished() {
// With shell transitions, the transition manages status changes, so skip this test.
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
similarity index 96%
rename from libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
index 94c064b..84ccdde 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/TaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/FluidResizeTaskPositionerTest.kt
@@ -14,10 +14,10 @@
import com.android.wm.shell.common.DisplayLayout
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.ShellTestCase
-import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_BOTTOM
-import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_RIGHT
-import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_TOP
-import com.android.wm.shell.windowdecor.TaskPositioner.CTRL_TYPE_UNDEFINED
+import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_BOTTOM
+import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT
+import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP
+import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_UNDEFINED
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -30,21 +30,21 @@
import org.mockito.MockitoAnnotations
/**
- * Tests for [TaskPositioner].
+ * Tests for [FluidResizeTaskPositioner].
*
* Build/Install/Run:
- * atest WMShellUnitTests:TaskPositionerTest
+ * atest WMShellUnitTests:FluidResizeTaskPositionerTest
*/
@SmallTest
@RunWith(AndroidTestingRunner::class)
-class TaskPositionerTest : ShellTestCase() {
+class FluidResizeTaskPositionerTest : ShellTestCase() {
@Mock
private lateinit var mockShellTaskOrganizer: ShellTaskOrganizer
@Mock
private lateinit var mockWindowDecoration: WindowDecoration<*>
@Mock
- private lateinit var mockDragStartListener: TaskPositioner.DragStartListener
+ private lateinit var mockDragStartListener: DragPositioningCallbackUtility.DragStartListener
@Mock
private lateinit var taskToken: WindowContainerToken
@@ -58,18 +58,19 @@
@Mock
private lateinit var mockDisplay: Display
- private lateinit var taskPositioner: TaskPositioner
+ private lateinit var taskPositioner: FluidResizeTaskPositioner
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- taskPositioner = TaskPositioner(
+ taskPositioner =
+ FluidResizeTaskPositioner(
mockShellTaskOrganizer,
mockWindowDecoration,
mockDisplayController,
mockDragStartListener
- )
+ )
`when`(taskToken.asBinder()).thenReturn(taskBinder)
`when`(mockDisplayController.getDisplayLayout(DISPLAY_ID)).thenReturn(mockDisplayLayout)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
new file mode 100644
index 0000000..bf365ca
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.windowdecor
+
+import android.app.ActivityManager
+import android.app.WindowConfiguration
+import android.graphics.Rect
+import android.os.IBinder
+import android.testing.AndroidTestingRunner
+import android.view.Display
+import android.window.WindowContainerToken
+import androidx.test.filters.SmallTest
+import com.android.wm.shell.common.DisplayController
+import com.android.wm.shell.common.DisplayLayout
+import com.android.wm.shell.ShellTaskOrganizer
+import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT
+import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP
+import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_UNDEFINED
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.any
+import org.mockito.Mockito.argThat
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+/**
+ * Tests for [VeiledResizeTaskPositioner].
+ *
+ * Build/Install/Run:
+ * atest WMShellUnitTests:VeiledResizeTaskPositionerTest
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class VeiledResizeTaskPositionerTest : ShellTestCase() {
+
+ @Mock
+ private lateinit var mockShellTaskOrganizer: ShellTaskOrganizer
+ @Mock
+ private lateinit var mockDesktopWindowDecoration: DesktopModeWindowDecoration
+ @Mock
+ private lateinit var mockDragStartListener: DragPositioningCallbackUtility.DragStartListener
+
+ @Mock
+ private lateinit var taskToken: WindowContainerToken
+ @Mock
+ private lateinit var taskBinder: IBinder
+
+ @Mock
+ private lateinit var mockDisplayController: DisplayController
+ @Mock
+ private lateinit var mockDisplayLayout: DisplayLayout
+ @Mock
+ private lateinit var mockDisplay: Display
+
+ private lateinit var taskPositioner: VeiledResizeTaskPositioner
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ taskPositioner =
+ VeiledResizeTaskPositioner(
+ mockShellTaskOrganizer,
+ mockDesktopWindowDecoration,
+ mockDisplayController,
+ mockDragStartListener
+ )
+
+ `when`(taskToken.asBinder()).thenReturn(taskBinder)
+ `when`(mockDisplayController.getDisplayLayout(DISPLAY_ID)).thenReturn(mockDisplayLayout)
+ `when`(mockDisplayLayout.densityDpi()).thenReturn(DENSITY_DPI)
+ `when`(mockDisplayLayout.getStableBounds(any())).thenAnswer { i ->
+ (i.arguments.first() as Rect).set(STABLE_BOUNDS)
+ }
+
+ mockDesktopWindowDecoration.mTaskInfo = ActivityManager.RunningTaskInfo().apply {
+ taskId = TASK_ID
+ token = taskToken
+ minWidth = MIN_WIDTH
+ minHeight = MIN_HEIGHT
+ defaultMinSize = DEFAULT_MIN
+ displayId = DISPLAY_ID
+ configuration.windowConfiguration.bounds = STARTING_BOUNDS
+ }
+ mockDesktopWindowDecoration.mDisplay = mockDisplay
+ `when`(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
+ }
+
+ @Test
+ fun testDragResize_noMove_showsResizeVeil() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
+ STARTING_BOUNDS.left.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+ verify(mockDesktopWindowDecoration).showResizeVeil()
+
+ taskPositioner.onDragPositioningEnd(
+ STARTING_BOUNDS.left.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+ verify(mockDesktopWindowDecoration).hideResizeVeil()
+ }
+
+ @Test
+ fun testDragResize_movesTask_doesNotShowResizeVeil() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_UNDEFINED,
+ STARTING_BOUNDS.left.toFloat() + 50,
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ taskPositioner.onDragPositioningMove(
+ STARTING_BOUNDS.left.toFloat() + 60,
+ STARTING_BOUNDS.top.toFloat() + 10
+ )
+ val rectAfterMove = Rect(STARTING_BOUNDS)
+ rectAfterMove.left += 10
+ rectAfterMove.right += 10
+ rectAfterMove.top += 10
+ rectAfterMove.bottom += 10
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ (change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
+ change.configuration.windowConfiguration.bounds == rectAfterMove
+ }
+ })
+
+ taskPositioner.onDragPositioningEnd(
+ STARTING_BOUNDS.left.toFloat() + 70,
+ STARTING_BOUNDS.top.toFloat() + 20
+ )
+ val rectAfterEnd = Rect(rectAfterMove)
+ rectAfterEnd.left += 10
+ rectAfterEnd.top += 10
+ rectAfterEnd.right += 10
+ rectAfterEnd.bottom += 10
+
+ verify(mockDesktopWindowDecoration, never()).createResizeVeil()
+ verify(mockDesktopWindowDecoration, never()).hideResizeVeil()
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ (change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
+ change.configuration.windowConfiguration.bounds == rectAfterEnd
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_resize_boundsUpdateOnEnd() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_RIGHT or CTRL_TYPE_TOP,
+ STARTING_BOUNDS.right.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+ verify(mockDesktopWindowDecoration).showResizeVeil()
+
+ taskPositioner.onDragPositioningMove(
+ STARTING_BOUNDS.right.toFloat() + 10,
+ STARTING_BOUNDS.top.toFloat() + 10
+ )
+
+ val rectAfterMove = Rect(STARTING_BOUNDS)
+ rectAfterMove.right += 10
+ rectAfterMove.top += 10
+ verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ (change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
+ change.configuration.windowConfiguration.bounds == rectAfterMove
+ }
+ })
+
+ taskPositioner.onDragPositioningEnd(
+ STARTING_BOUNDS.right.toFloat() + 20,
+ STARTING_BOUNDS.top.toFloat() + 20
+ )
+ val rectAfterEnd = Rect(rectAfterMove)
+ rectAfterEnd.right += 10
+ rectAfterEnd.top += 10
+ verify(mockDesktopWindowDecoration, times(2)).updateResizeVeil(any())
+ verify(mockDesktopWindowDecoration).hideResizeVeil()
+
+ verify(mockShellTaskOrganizer).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ (change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0 &&
+ change.configuration.windowConfiguration.bounds == rectAfterEnd
+ }
+ })
+ }
+
+ @Test
+ fun testDragResize_noEffectiveMove_skipsTransactionOnEnd() {
+ taskPositioner.onDragPositioningStart(
+ CTRL_TYPE_TOP or CTRL_TYPE_RIGHT,
+ STARTING_BOUNDS.left.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+ verify(mockDesktopWindowDecoration).showResizeVeil()
+
+ taskPositioner.onDragPositioningMove(
+ STARTING_BOUNDS.left.toFloat(),
+ STARTING_BOUNDS.top.toFloat()
+ )
+
+ taskPositioner.onDragPositioningEnd(
+ STARTING_BOUNDS.left.toFloat() + 10,
+ STARTING_BOUNDS.top.toFloat() + 10
+ )
+ verify(mockDesktopWindowDecoration).hideResizeVeil()
+
+ verify(mockShellTaskOrganizer, never()).applyTransaction(argThat { wct ->
+ return@argThat wct.changes.any { (token, change) ->
+ token == taskBinder &&
+ ((change.windowSetMask and WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)
+ }
+ })
+ }
+
+ companion object {
+ private const val TASK_ID = 5
+ private const val MIN_WIDTH = 10
+ private const val MIN_HEIGHT = 10
+ private const val DENSITY_DPI = 20
+ private const val DEFAULT_MIN = 40
+ private const val DISPLAY_ID = 1
+ private const val NAVBAR_HEIGHT = 50
+ private val DISPLAY_BOUNDS = Rect(0, 0, 2400, 1600)
+ private val STARTING_BOUNDS = Rect(0, 0, 100, 100)
+ private val STABLE_BOUNDS = Rect(
+ DISPLAY_BOUNDS.left,
+ DISPLAY_BOUNDS.top,
+ DISPLAY_BOUNDS.right,
+ DISPLAY_BOUNDS.bottom - NAVBAR_HEIGHT
+ )
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index fc4bfd97..5a2326b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -16,6 +16,8 @@
package com.android.wm.shell.windowdecor;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
import static com.android.wm.shell.MockSurfaceControlHelper.createMockSurfaceControlBuilder;
import static com.android.wm.shell.MockSurfaceControlHelper.createMockSurfaceControlTransaction;
@@ -86,6 +88,7 @@
public class WindowDecorationTests extends ShellTestCase {
private static final Rect TASK_BOUNDS = new Rect(100, 300, 400, 400);
private static final Point TASK_POSITION_IN_PARENT = new Point(40, 60);
+ private static final int CORNER_RADIUS = 20;
private final WindowDecoration.RelayoutResult<TestView> mRelayoutResult =
new WindowDecoration.RelayoutResult<>();
@@ -130,6 +133,7 @@
mCaptionMenuShadowRadiusId = R.dimen.test_caption_menu_shadow_radius;
mCaptionMenuCornerRadiusId = R.dimen.test_caption_menu_corner_radius;
mRelayoutParams.mShadowRadiusId = R.dimen.test_window_decor_shadow_radius;
+ mRelayoutParams.mCornerRadius = CORNER_RADIUS;
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
.create(any(), any(), any());
@@ -209,6 +213,7 @@
.setBounds(TASK_BOUNDS)
.setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y)
.setVisible(true)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM)
.build();
taskInfo.isFocused = true;
// Density is 2. Shadow radius is 10px. Caption height is 64px.
@@ -249,6 +254,8 @@
.setPosition(taskSurface, TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y);
verify(mMockSurfaceControlFinishT)
.setWindowCrop(taskSurface, 300, 100);
+ verify(mMockSurfaceControlStartT).setCornerRadius(taskSurface, CORNER_RADIUS);
+ verify(mMockSurfaceControlFinishT).setCornerRadius(taskSurface, CORNER_RADIUS);
verify(mMockSurfaceControlStartT)
.show(taskSurface);
verify(mMockSurfaceControlStartT)
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 193544e..88b9643 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -934,13 +934,25 @@
}
}
levelCaps = createFromProfileLevel(mMime, profile, maxLevel);
- // remove profile from this format otherwise levelCaps.isFormatSupported will
- // get into this same conditon and loop forever.
- Map<String, Object> mapWithoutProfile = new HashMap<>(map);
- mapWithoutProfile.remove(MediaFormat.KEY_PROFILE);
- MediaFormat formatWithoutProfile = new MediaFormat(mapWithoutProfile);
- if (levelCaps != null && !levelCaps.isFormatSupported(formatWithoutProfile)) {
- return false;
+ // We must remove the profile from this format otherwise levelCaps.isFormatSupported
+ // will get into this same condition and loop forever. Furthermore, since levelCaps
+ // does not contain features and bitrate specific keys, keep only keys relevant for
+ // a level check.
+ Map<String, Object> levelCriticalFormatMap = new HashMap<>(map);
+ final Set<String> criticalKeys =
+ isVideo() ? VideoCapabilities.VIDEO_LEVEL_CRITICAL_FORMAT_KEYS :
+ isAudio() ? AudioCapabilities.AUDIO_LEVEL_CRITICAL_FORMAT_KEYS :
+ null;
+
+ // critical keys will always contain KEY_MIME, but should also contain others to be
+ // meaningful
+ if (criticalKeys != null && criticalKeys.size() > 1 && levelCaps != null) {
+ levelCriticalFormatMap.keySet().retainAll(criticalKeys);
+
+ MediaFormat levelCriticalFormat = new MediaFormat(levelCriticalFormatMap);
+ if (!levelCaps.isFormatSupported(levelCriticalFormat)) {
+ return false;
+ }
}
}
if (mAudioCaps != null && !mAudioCaps.supportsFormat(format)) {
@@ -1633,6 +1645,16 @@
}
}
+ /* package private */
+ // must not contain KEY_PROFILE
+ static final Set<String> AUDIO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of(
+ // We don't set level-specific limits for audio codecs today. Key candidates would
+ // be sample rate, bit rate or channel count.
+ // MediaFormat.KEY_SAMPLE_RATE,
+ // MediaFormat.KEY_CHANNEL_COUNT,
+ // MediaFormat.KEY_BIT_RATE,
+ MediaFormat.KEY_MIME);
+
/** @hide */
public boolean supportsFormat(MediaFormat format) {
Map<String, Object> map = format.getMap();
@@ -2357,6 +2379,15 @@
return ok;
}
+ /* package private */
+ // must not contain KEY_PROFILE
+ static final Set<String> VIDEO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of(
+ MediaFormat.KEY_WIDTH,
+ MediaFormat.KEY_HEIGHT,
+ MediaFormat.KEY_FRAME_RATE,
+ MediaFormat.KEY_BIT_RATE,
+ MediaFormat.KEY_MIME);
+
/**
* @hide
* @throws java.lang.ClassCastException */
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index b6d70af..78352871 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -54,7 +54,6 @@
import com.android.internal.app.ISoundTriggerService;
import com.android.internal.app.ISoundTriggerSession;
-import com.android.internal.util.Preconditions;
import java.util.HashMap;
import java.util.List;
@@ -67,6 +66,8 @@
* models. Usage of this class is restricted to system or signature applications only. This allows
* OEMs to write apps that can manage non-voice based sound trigger models.
*
+ * If no ST module is available, {@link getModuleProperties()} will return {@code null}, and all
+ * other methods will throw {@link IllegalStateException}.
* @hide
*/
@SystemApi
@@ -82,7 +83,7 @@
// Stores a mapping from the sound model UUID to the SoundTriggerInstance created by
// the createSoundTriggerDetector() call.
- private final HashMap<UUID, SoundTriggerDetector> mReceiverInstanceMap;
+ private final HashMap<UUID, SoundTriggerDetector> mReceiverInstanceMap = new HashMap<>();
/**
* @hide
@@ -121,7 +122,6 @@
}
mContext = context;
mSoundTriggerService = soundTriggerService;
- mReceiverInstanceMap = new HashMap<UUID, SoundTriggerDetector>();
}
/**
@@ -160,7 +160,7 @@
.findFirst()
.orElse(null);
if (moduleProps == null) {
- throw new IllegalStateException("Fake ST HAL should always be available");
+ throw new AssertionError("Fake ST HAL should always be available");
}
return moduleProps;
}
@@ -183,7 +183,6 @@
}
mContext = Objects.requireNonNull(context);
mSoundTriggerService = Objects.requireNonNull(soundTriggerService);
- mReceiverInstanceMap = new HashMap<UUID, SoundTriggerDetector>();
}
/**
@@ -241,7 +240,8 @@
}
try {
GenericSoundModel model =
- mSoundTriggerSession.getSoundModel(new ParcelUuid(soundModelId));
+ mSoundTriggerSession.getSoundModel(
+ new ParcelUuid(Objects.requireNonNull(soundModelId)));
if (model == null) {
return null;
}
@@ -265,7 +265,8 @@
}
try {
- mSoundTriggerSession.deleteSoundModel(new ParcelUuid(soundModelId));
+ mSoundTriggerSession.deleteSoundModel(
+ new ParcelUuid(Objects.requireNonNull(soundModelId)));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -291,8 +292,8 @@
@RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
public SoundTriggerDetector createSoundTriggerDetector(UUID soundModelId,
@NonNull SoundTriggerDetector.Callback callback, @Nullable Handler handler) {
- if (soundModelId == null || mSoundTriggerSession == null) {
- return null;
+ if (mSoundTriggerSession == null) {
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
SoundTriggerDetector oldInstance = mReceiverInstanceMap.get(soundModelId);
@@ -301,7 +302,8 @@
}
try {
SoundTriggerDetector newInstance = new SoundTriggerDetector(mSoundTriggerSession,
- mSoundTriggerSession.getSoundModel(new ParcelUuid(soundModelId)),
+ mSoundTriggerSession.getSoundModel(
+ new ParcelUuid(Objects.requireNonNull(soundModelId))),
callback, handler);
mReceiverInstanceMap.put(soundModelId, newInstance);
return newInstance;
@@ -469,8 +471,8 @@
@UnsupportedAppUsage
@TestApi
public int loadSoundModel(@NonNull SoundModel soundModel) {
- if (soundModel == null || mSoundTriggerSession == null) {
- return STATUS_ERROR;
+ if (mSoundTriggerSession == null) {
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
@@ -513,11 +515,11 @@
@UnsupportedAppUsage
public int startRecognition(@NonNull UUID soundModelId, @Nullable Bundle params,
@NonNull ComponentName detectionService, @NonNull RecognitionConfig config) {
- Preconditions.checkNotNull(soundModelId);
- Preconditions.checkNotNull(detectionService);
- Preconditions.checkNotNull(config);
+ Objects.requireNonNull(soundModelId);
+ Objects.requireNonNull(detectionService);
+ Objects.requireNonNull(config);
if (mSoundTriggerSession == null) {
- return STATUS_ERROR;
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
return mSoundTriggerSession.startRecognitionForService(new ParcelUuid(soundModelId),
@@ -534,11 +536,12 @@
@RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int stopRecognition(UUID soundModelId) {
- if (soundModelId == null || mSoundTriggerSession == null) {
- return STATUS_ERROR;
+ if (mSoundTriggerSession == null) {
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
- return mSoundTriggerSession.stopRecognitionForService(new ParcelUuid(soundModelId));
+ return mSoundTriggerSession.stopRecognitionForService(
+ new ParcelUuid(Objects.requireNonNull(soundModelId)));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -551,12 +554,12 @@
@RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int unloadSoundModel(UUID soundModelId) {
- if (soundModelId == null || mSoundTriggerSession == null) {
- return STATUS_ERROR;
+ if (mSoundTriggerSession == null) {
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
return mSoundTriggerSession.unloadSoundModel(
- new ParcelUuid(soundModelId));
+ new ParcelUuid(Objects.requireNonNull(soundModelId)));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -604,7 +607,10 @@
@RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
@UnsupportedAppUsage
public int getModelState(UUID soundModelId) {
- if (soundModelId == null || mSoundTriggerSession == null) {
+ if (mSoundTriggerSession == null) {
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
+ }
+ if (soundModelId == null) {
return STATUS_ERROR;
}
try {
@@ -652,11 +658,12 @@
public int setParameter(@Nullable UUID soundModelId,
@ModelParams int modelParam, int value) {
if (mSoundTriggerSession == null) {
- return SoundTrigger.STATUS_INVALID_OPERATION;
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
- return mSoundTriggerSession.setParameter(new ParcelUuid(soundModelId), modelParam,
+ return mSoundTriggerSession.setParameter(
+ new ParcelUuid(Objects.requireNonNull(soundModelId)), modelParam,
value);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -679,11 +686,11 @@
public int getParameter(@NonNull UUID soundModelId,
@ModelParams int modelParam) {
if (mSoundTriggerSession == null) {
- throw new IllegalArgumentException("Sound model is not loaded: "
- + soundModelId.toString());
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
- return mSoundTriggerSession.getParameter(new ParcelUuid(soundModelId), modelParam);
+ return mSoundTriggerSession.getParameter(
+ new ParcelUuid(Objects.requireNonNull(soundModelId)), modelParam);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -703,10 +710,11 @@
public ModelParamRange queryParameter(@Nullable UUID soundModelId,
@ModelParams int modelParam) {
if (mSoundTriggerSession == null) {
- return null;
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
- return mSoundTriggerSession.queryParameter(new ParcelUuid(soundModelId), modelParam);
+ return mSoundTriggerSession.queryParameter(
+ new ParcelUuid(Objects.requireNonNull(soundModelId)), modelParam);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 9552200..44aff64 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -385,6 +385,10 @@
process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." );
+ if (env->ExceptionCheck()) {
+ return UNKNOWN_ERROR;
+ }
+
// update the piid
Parcel *request = parcelForJavaObject(env, piidParcel);
auto reply = std::make_unique<Parcel>();
@@ -407,6 +411,10 @@
process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." );
+ if (env->ExceptionCheck()) {
+ return UNKNOWN_ERROR;
+ }
+
// update the piid
Parcel *request = parcelForJavaObject(env, piidParcel);
auto reply = std::make_unique<Parcel>();
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index 905e0ca..a3b2752 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -114,13 +114,13 @@
<!-- Strings for the get flow. -->
<!-- This appears as the title of the modal bottom sheet asking for user confirmation to use the single previously saved passkey to sign in to the app. [CHAR LIMIT=200] -->
<string name="get_dialog_title_use_passkey_for">Use your saved passkey for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
- <!-- This appears as the title of the dialog asking for user confirmation to use the single previously saved credential to sign in to the app. [CHAR LIMIT=200] -->
- <string name="get_dialog_title_use_sign_in_for">Use your saved sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
- <!-- This appears as the title of the dialog asking for user to make a choice from various previously saved credentials to sign in to the app. [CHAR LIMIT=200] -->
- <string name="get_dialog_title_choose_sign_in_for">Choose a saved sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
- <!-- This appears as the title of the dialog asking for user to make a choice from various previously saved credentials to sign in to the app. [CHAR LIMIT=200] -->
+ <!-- This appears as the title of the dialog asking for user confirmation to use the single user credential (previously saved or to be created) to sign in to the app. [CHAR LIMIT=200] -->
+ <string name="get_dialog_title_use_sign_in_for">Use your sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
+ <!-- This appears as the title of the dialog asking for user to make a choice from various available user credentials (previously saved or to be created) to sign in to the app. [CHAR LIMIT=200] -->
+ <string name="get_dialog_title_choose_sign_in_for">Choose a sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
+ <!-- This appears as the title of the dialog asking for user to make a choice from options of available user information (e.g. driver's license, vaccination status) to pass to the app. [CHAR LIMIT=200] -->
<string name="get_dialog_title_choose_option_for">Choose an option for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
- <!-- This appears as the title of the dialog asking user to use a previously saved credentials to sign in to the app. [CHAR LIMIT=200] -->
+ <!-- This appears as the title of the dialog asking user to send a piece of user information (e.g. driver's license, vaccination status) to the app. [CHAR LIMIT=200] -->
<string name="get_dialog_title_use_info_on">Use this info on <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
<!-- This is a label for a button that links the user to different sign-in methods . [CHAR LIMIT=80] -->
<string name="get_dialog_use_saved_passkey_for">Sign in another way</string>
diff --git a/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java b/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java
index 76e1df1..ea4ac2c 100644
--- a/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java
+++ b/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java
@@ -62,7 +62,6 @@
private SparseIntArray mPostureRotationLockSettings;
private SparseIntArray mPostureDefaultRotationLockSettings;
private SparseIntArray mPostureRotationLockFallbackSettings;
- private String mLastSettingValue;
private List<SettableDeviceState> mSettableDeviceStates;
@VisibleForTesting
@@ -209,10 +208,7 @@
}
private void initializeInMemoryMap() {
- String serializedSetting =
- mSecureSettings.getStringForUser(
- Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
- UserHandle.USER_CURRENT);
+ String serializedSetting = getPersistedSettingValue();
if (TextUtils.isEmpty(serializedSetting)) {
// No settings saved, we should load the defaults and persist them.
fallbackOnDefaults();
@@ -290,19 +286,25 @@
}
private void persistSettingIfChanged(String newSettingValue) {
+ String lastSettingValue = getPersistedSettingValue();
Log.v(TAG, "persistSettingIfChanged: "
- + "last=" + mLastSettingValue + ", "
+ + "last=" + lastSettingValue + ", "
+ "new=" + newSettingValue);
- if (TextUtils.equals(mLastSettingValue, newSettingValue)) {
+ if (TextUtils.equals(lastSettingValue, newSettingValue)) {
return;
}
- mLastSettingValue = newSettingValue;
mSecureSettings.putStringForUser(
Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
/* value= */ newSettingValue,
UserHandle.USER_CURRENT);
}
+ private String getPersistedSettingValue() {
+ return mSecureSettings.getStringForUser(
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
+ UserHandle.USER_CURRENT);
+ }
+
private void loadDefaults() {
mSettableDeviceStates = new ArrayList<>(mPostureRotationLockDefaults.length);
mPostureDefaultRotationLockSettings = new SparseIntArray(
@@ -351,7 +353,6 @@
pw.println("mDeviceStateRotationLockSettings: " + mPostureRotationLockSettings);
pw.println("mPostureRotationLockFallbackSettings: " + mPostureRotationLockFallbackSettings);
pw.println("mSettableDeviceStates: " + mSettableDeviceStates);
- pw.println("mLastSettingValue: " + mLastSettingValue);
pw.decreaseIndent();
}
diff --git a/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/PosturesHelper.kt b/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/PosturesHelper.kt
index 9c70be9..6a13eb8 100644
--- a/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/PosturesHelper.kt
+++ b/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/PosturesHelper.kt
@@ -19,6 +19,7 @@
import android.content.Context
import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_FOLDED
import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_HALF_FOLDED
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_REAR_DISPLAY
import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_UNFOLDED
import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_UNKNOWN
import android.provider.Settings.Secure.DeviceStateRotationLockKey
@@ -33,6 +34,8 @@
context.resources.getIntArray(R.array.config_halfFoldedDeviceStates)
private val unfoldedDeviceStates =
context.resources.getIntArray(R.array.config_openDeviceStates)
+ private val rearDisplayDeviceStates =
+ context.resources.getIntArray(R.array.config_rearDisplayDeviceStates)
@DeviceStateRotationLockKey
fun deviceStateToPosture(deviceState: Int): Int {
@@ -40,6 +43,7 @@
in foldedDeviceStates -> DEVICE_STATE_ROTATION_KEY_FOLDED
in halfFoldedDeviceStates -> DEVICE_STATE_ROTATION_KEY_HALF_FOLDED
in unfoldedDeviceStates -> DEVICE_STATE_ROTATION_KEY_UNFOLDED
+ in rearDisplayDeviceStates -> DEVICE_STATE_ROTATION_KEY_REAR_DISPLAY
else -> DEVICE_STATE_ROTATION_KEY_UNKNOWN
}
}
@@ -49,6 +53,7 @@
DEVICE_STATE_ROTATION_KEY_FOLDED -> foldedDeviceStates.firstOrNull()
DEVICE_STATE_ROTATION_KEY_HALF_FOLDED -> halfFoldedDeviceStates.firstOrNull()
DEVICE_STATE_ROTATION_KEY_UNFOLDED -> unfoldedDeviceStates.firstOrNull()
+ DEVICE_STATE_ROTATION_KEY_REAR_DISPLAY -> rearDisplayDeviceStates.firstOrNull()
else -> null
}
}
diff --git a/packages/SettingsLib/MainSwitchPreference/res/drawable/settingslib_ic_info.xml b/packages/SettingsLib/MainSwitchPreference/res/drawable/settingslib_ic_info.xml
deleted file mode 100644
index c8037c8..0000000
--- a/packages/SettingsLib/MainSwitchPreference/res/drawable/settingslib_ic_info.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
- Copyright (C) 2021 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- copy from frameworks/base/core/res/res/drawable/ic_info.xml-->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24"
- android:tint="?attr/colorControlNormal">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml
index ca84db8..b1c26e8 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml
@@ -46,16 +46,6 @@
android:textAppearance="?android:attr/textAppearanceListItem"
style="@style/MainSwitchText.Settingslib" />
- <ImageView
- android:id="@+id/restricted_icon"
- android:layout_width="@dimen/settingslib_restricted_icon_size"
- android:layout_height="@dimen/settingslib_restricted_icon_size"
- android:tint="?android:attr/colorAccent"
- android:layout_gravity="center_vertical"
- android:layout_marginEnd="@dimen/settingslib_restricted_icon_margin_end"
- android:src="@drawable/settingslib_ic_info"
- android:visibility="gone" />
-
<Switch
android:id="@android:id/switch_widget"
android:layout_width="wrap_content"
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout-v33/settingslib_main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout-v33/settingslib_main_switch_bar.xml
index 2c2ad92..ab0cf31 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout-v33/settingslib_main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout-v33/settingslib_main_switch_bar.xml
@@ -49,16 +49,6 @@
android:lineBreakWordStyle="phrase"
style="@style/MainSwitchText.Settingslib" />
- <ImageView
- android:id="@+id/restricted_icon"
- android:layout_width="@dimen/settingslib_restricted_icon_size"
- android:layout_height="@dimen/settingslib_restricted_icon_size"
- android:tint="@color/settingslib_accent_primary_variant"
- android:layout_gravity="center_vertical"
- android:layout_marginEnd="@dimen/settingslib_restricted_icon_margin_end"
- android:src="@drawable/settingslib_ic_info"
- android:visibility="gone" />
-
<Switch
android:id="@android:id/switch_widget"
android:layout_width="wrap_content"
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_bar.xml
index b39d09f..bf34db9 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_bar.xml
@@ -38,17 +38,6 @@
android:layout_marginStart="@dimen/settingslib_switchbar_subsettings_margin_start"
android:textAlignment="viewStart"/>
- <ImageView
- android:id="@+id/restricted_icon"
- android:layout_width="@dimen/settingslib_restricted_icon_size"
- android:layout_height="@dimen/settingslib_restricted_icon_size"
- android:tint="?android:attr/colorAccent"
- android:theme="@android:style/Theme.Material"
- android:layout_gravity="center_vertical"
- android:layout_marginEnd="@dimen/settingslib_restricted_icon_margin_end"
- android:src="@drawable/settingslib_ic_info"
- android:visibility="gone"/>
-
<Switch
android:id="@android:id/switch_widget"
android:layout_width="wrap_content"
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values-v31/styles.xml b/packages/SettingsLib/MainSwitchPreference/res/values-v31/styles.xml
index a50fc7c..ad888e5 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/values-v31/styles.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/values-v31/styles.xml
@@ -17,9 +17,8 @@
<resources>
- <style name="MainSwitchText.Settingslib" parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
+ <style name="MainSwitchText.Settingslib" parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title.Inverse">
<item name="android:textSize">20sp</item>
<item name="android:fontFamily">@string/settingslib_config_headlineFontFamily</item>
- <item name="android:textColor">@android:color/black</item>
</style>
</resources>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml b/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml
index 88b2c87..0d9ffff 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/values/dimens.xml
@@ -17,16 +17,9 @@
<resources>
- <!-- Restricted icon size in switch bar -->
- <dimen name="settingslib_restricted_icon_size">@android:dimen/config_restrictedIconSize</dimen>
-
- <!-- Restricted icon in switch bar -->
- <dimen name="settingslib_restricted_icon_margin_end">16dp</dimen>
-
<!-- Size of title margin -->
<dimen name="settingslib_switch_title_margin">24dp</dimen>
- <!-- SwitchBar sub settings margin start / end -->
+ <!-- SwitchBar sub settings margin start -->
<dimen name="settingslib_switchbar_subsettings_margin_start">56dp</dimen>
- <dimen name="settingslib_switchbar_subsettings_margin_end">16dp</dimen>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 45c0d78..adaf4a1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -14,7 +14,9 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
@@ -26,6 +28,8 @@
import android.net.NetworkRequest;
import android.net.NetworkScoreManager;
import android.net.ScoredNetwork;
+import android.net.TransportInfo;
+import android.net.vcn.VcnTransportInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkScoreCache;
@@ -34,8 +38,9 @@
import android.os.Looper;
import android.provider.Settings;
+import androidx.annotation.Nullable;
+
import com.android.settingslib.R;
-import com.android.settingslib.Utils;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
@@ -46,6 +51,7 @@
/**
* Track status of Wi-Fi for the Sys UI.
*/
+@SuppressLint("MissingPermission")
public class WifiStatusTracker {
private static final int HISTORY_SIZE = 32;
private static final SimpleDateFormat SSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
@@ -66,8 +72,9 @@
private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
.clearCapabilities()
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build();
+ .addTransportType(TRANSPORT_WIFI)
+ .addTransportType(TRANSPORT_CELLULAR)
+ .build();
private final NetworkCallback mNetworkCallback =
new NetworkCallback(NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) {
// Note: onCapabilitiesChanged is guaranteed to be called "immediately" after onAvailable
@@ -75,18 +82,10 @@
@Override
public void onCapabilitiesChanged(
Network network, NetworkCapabilities networkCapabilities) {
- boolean isVcnOverWifi = false;
- boolean isWifi = false;
- WifiInfo wifiInfo = null;
- if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
- wifiInfo = Utils.tryGetWifiInfoForVcn(networkCapabilities);
- isVcnOverWifi = (wifiInfo != null);
- } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
- wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();
- isWifi = true;
- }
+ WifiInfo wifiInfo = getMainOrUnderlyingWifiInfo(networkCapabilities);
+ boolean isWifi = connectionIsWifi(networkCapabilities, wifiInfo);
// As long as it is a WiFi network, we will log it in the dumpsys for debugging.
- if (isVcnOverWifi || isWifi) {
+ if (isWifi) {
String log = new StringBuilder()
.append(SSDF.format(System.currentTimeMillis())).append(",")
.append("onCapabilitiesChanged: ")
@@ -303,17 +302,8 @@
return;
}
NetworkCapabilities networkCapabilities;
- isDefaultNetwork = false;
- if (mDefaultNetworkCapabilities != null) {
- boolean isWifi = mDefaultNetworkCapabilities.hasTransport(
- NetworkCapabilities.TRANSPORT_WIFI);
- boolean isVcnOverWifi = mDefaultNetworkCapabilities.hasTransport(
- NetworkCapabilities.TRANSPORT_CELLULAR)
- && (Utils.tryGetWifiInfoForVcn(mDefaultNetworkCapabilities) != null);
- if (isWifi || isVcnOverWifi) {
- isDefaultNetwork = true;
- }
- }
+ isDefaultNetwork = mDefaultNetworkCapabilities != null
+ && connectionIsWifi(mDefaultNetworkCapabilities);
if (isDefaultNetwork) {
// Wifi is connected and the default network.
networkCapabilities = mDefaultNetworkCapabilities;
@@ -352,6 +342,70 @@
? null : AccessPoint.getSpeedLabel(mContext, scoredNetwork, rssi);
}
+ @Nullable
+ private WifiInfo getMainOrUnderlyingWifiInfo(NetworkCapabilities networkCapabilities) {
+ WifiInfo mainWifiInfo = getMainWifiInfo(networkCapabilities);
+ if (mainWifiInfo != null) {
+ return mainWifiInfo;
+ }
+
+ // Only CELLULAR networks may have underlying wifi information that's relevant to SysUI,
+ // so skip the underlying network check if it's not CELLULAR.
+ if (!networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+ return mainWifiInfo;
+ }
+
+ List<Network> underlyingNetworks = networkCapabilities.getUnderlyingNetworks();
+ if (underlyingNetworks == null) {
+ return null;
+ }
+
+ // Some connections, like VPN connections, may have underlying networks that are
+ // eventually traced to a wifi or carrier merged connection. So, check those underlying
+ // networks for possible wifi information as well. See b/225902574.
+ for (Network underlyingNetwork : underlyingNetworks) {
+ NetworkCapabilities underlyingNetworkCapabilities =
+ mConnectivityManager.getNetworkCapabilities(underlyingNetwork);
+ WifiInfo underlyingWifiInfo = getMainWifiInfo(underlyingNetworkCapabilities);
+ if (underlyingWifiInfo != null) {
+ return underlyingWifiInfo;
+ }
+ }
+
+ return null;
+ }
+
+ @Nullable
+ private WifiInfo getMainWifiInfo(NetworkCapabilities networkCapabilities) {
+ boolean canHaveWifiInfo = networkCapabilities.hasTransport(TRANSPORT_WIFI)
+ || networkCapabilities.hasTransport(TRANSPORT_CELLULAR);
+ if (!canHaveWifiInfo) {
+ return null;
+ }
+
+ TransportInfo transportInfo = networkCapabilities.getTransportInfo();
+ if (transportInfo instanceof VcnTransportInfo) {
+ // This VcnTransportInfo logic is copied from
+ // [com.android.settingslib.Utils.tryGetWifiInfoForVcn]. It's copied instead of
+ // re-used because it makes the logic here clearer.
+ return ((VcnTransportInfo) transportInfo).getWifiInfo();
+ } else if (transportInfo instanceof WifiInfo) {
+ return (WifiInfo) transportInfo;
+ } else {
+ return null;
+ }
+ }
+
+ private boolean connectionIsWifi(NetworkCapabilities networkCapabilities) {
+ return connectionIsWifi(
+ networkCapabilities,
+ getMainOrUnderlyingWifiInfo(networkCapabilities));
+ }
+
+ private boolean connectionIsWifi(NetworkCapabilities networkCapabilities, WifiInfo wifiInfo) {
+ return wifiInfo != null || networkCapabilities.hasTransport(TRANSPORT_WIFI);
+ }
+
/** Refresh the status label on Locale changed. */
public void refreshLocale() {
updateStatusLabel();
diff --git a/packages/SettingsLib/tests/integ/Android.bp b/packages/SettingsLib/tests/integ/Android.bp
index d463170..ff3eeec 100644
--- a/packages/SettingsLib/tests/integ/Android.bp
+++ b/packages/SettingsLib/tests/integ/Android.bp
@@ -30,7 +30,10 @@
certificate: "platform",
- srcs: ["src/**/*.java"],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
libs: [
"android.test.runner",
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
index fdefcde..52c2a87 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
@@ -114,6 +114,21 @@
}
@Test
+ public void updateSetting_twiceWithSameValue_persistedValueDifferent_persistsAgain() {
+ mManager.updateSetting(/* deviceState= */ 1, /* rotationLocked= */ true);
+ // This persists a different setting than what was set above. It simulates the persisted
+ // setting being changed from a different process.
+ persistSettings("0:1:1:2:2:2");
+ mNumSettingsChanges = 0;
+
+ // Updating again with the same value as in the first line of the test should persist the
+ // setting, as it is different to what is actually persisted.
+ mManager.updateSetting(/* deviceState= */ 1, /* rotationLocked= */ true);
+
+ assertThat(mNumSettingsChanges).isEqualTo(1);
+ }
+
+ @Test
public void getSettableDeviceStates_returnsExpectedValuesInOriginalOrder() {
when(mMockResources.getStringArray(
R.array.config_perDeviceStateRotationLockDefaults)).thenReturn(
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/PosturesHelperTest.kt b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/PosturesHelperTest.kt
new file mode 100644
index 0000000..d91c2fa
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/PosturesHelperTest.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.devicestate
+
+import android.content.Context
+import android.content.res.Resources
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_FOLDED
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_HALF_FOLDED
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_REAR_DISPLAY
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_UNFOLDED
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_UNKNOWN
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.internal.R
+import com.google.common.truth.Expect
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+
+private const val DEVICE_STATE_UNKNOWN = 0
+private const val DEVICE_STATE_CLOSED = 1
+private const val DEVICE_STATE_HALF_FOLDED = 2
+private const val DEVICE_STATE_OPEN = 3
+private const val DEVICE_STATE_REAR_DISPLAY = 4
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class PosturesHelperTest {
+
+ @get:Rule val expect: Expect = Expect.create()
+
+ @Mock private lateinit var context: Context
+
+ @Mock private lateinit var resources: Resources
+
+ private lateinit var posturesHelper: PosturesHelper
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ whenever(context.resources).thenReturn(resources)
+ whenever(resources.getIntArray(R.array.config_foldedDeviceStates))
+ .thenReturn(intArrayOf(DEVICE_STATE_CLOSED))
+ whenever(resources.getIntArray(R.array.config_halfFoldedDeviceStates))
+ .thenReturn(intArrayOf(DEVICE_STATE_HALF_FOLDED))
+ whenever(resources.getIntArray(R.array.config_openDeviceStates))
+ .thenReturn(intArrayOf(DEVICE_STATE_OPEN))
+ whenever(resources.getIntArray(R.array.config_rearDisplayDeviceStates))
+ .thenReturn(intArrayOf(DEVICE_STATE_REAR_DISPLAY))
+
+ posturesHelper = PosturesHelper(context)
+ }
+
+ @Test
+ fun deviceStateToPosture_mapsCorrectly() {
+ expect
+ .that(posturesHelper.deviceStateToPosture(DEVICE_STATE_CLOSED))
+ .isEqualTo(DEVICE_STATE_ROTATION_KEY_FOLDED)
+ expect
+ .that(posturesHelper.deviceStateToPosture(DEVICE_STATE_HALF_FOLDED))
+ .isEqualTo(DEVICE_STATE_ROTATION_KEY_HALF_FOLDED)
+ expect
+ .that(posturesHelper.deviceStateToPosture(DEVICE_STATE_OPEN))
+ .isEqualTo(DEVICE_STATE_ROTATION_KEY_UNFOLDED)
+ expect
+ .that(posturesHelper.deviceStateToPosture(DEVICE_STATE_REAR_DISPLAY))
+ .isEqualTo(DEVICE_STATE_ROTATION_KEY_REAR_DISPLAY)
+ expect
+ .that(posturesHelper.deviceStateToPosture(DEVICE_STATE_UNKNOWN))
+ .isEqualTo(DEVICE_STATE_ROTATION_KEY_UNKNOWN)
+ }
+
+ @Test
+ fun postureToDeviceState_mapsCorrectly() {
+ expect
+ .that(posturesHelper.postureToDeviceState(DEVICE_STATE_ROTATION_KEY_FOLDED))
+ .isEqualTo(DEVICE_STATE_CLOSED)
+ expect
+ .that(posturesHelper.postureToDeviceState(DEVICE_STATE_ROTATION_KEY_HALF_FOLDED))
+ .isEqualTo(DEVICE_STATE_HALF_FOLDED)
+ expect
+ .that(posturesHelper.postureToDeviceState(DEVICE_STATE_ROTATION_KEY_UNFOLDED))
+ .isEqualTo(DEVICE_STATE_OPEN)
+ expect
+ .that(posturesHelper.postureToDeviceState(DEVICE_STATE_ROTATION_KEY_REAR_DISPLAY))
+ .isEqualTo(DEVICE_STATE_REAR_DISPLAY)
+ expect.that(posturesHelper.postureToDeviceState(DEVICE_STATE_ROTATION_KEY_UNKNOWN)).isNull()
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiStatusTrackerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiStatusTrackerTest.java
index dc7e313d..6e975cf 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiStatusTrackerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiStatusTrackerTest.java
@@ -40,6 +40,8 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
+import java.util.Arrays;
+
@RunWith(RobolectricTestRunner.class)
public class WifiStatusTrackerTest {
@Mock Context mContext;
@@ -48,13 +50,32 @@
@Mock ConnectivityManager mConnectivityManager;
@Mock Runnable mCallback;
+ private WifiStatusTracker mWifiStatusTracker;
+
private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
mNetworkCallbackCaptor =
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
+ private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
+ mDefaultNetworkCallbackCaptor =
+ ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+
+ mWifiStatusTracker = new WifiStatusTracker(
+ mContext,
+ mWifiManager,
+ mNetworkScoreManager,
+ mConnectivityManager,
+ mCallback);
+ mWifiStatusTracker.setListening(true);
+
+ verify(mConnectivityManager)
+ .registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
+ verify(mConnectivityManager)
+ .registerDefaultNetworkCallback(mDefaultNetworkCallbackCaptor.capture(), any());
}
/**
@@ -62,13 +83,6 @@
*/
@Test
public void testWifiInfoClearedOnPrimaryNetworkLost() {
- WifiStatusTracker wifiStatusTracker = new WifiStatusTracker(mContext, mWifiManager,
- mNetworkScoreManager, mConnectivityManager, mCallback);
- wifiStatusTracker.setListening(true);
-
- verify(mConnectivityManager)
- .registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
-
// Trigger a validation callback for the primary Wifi network.
WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
when(primaryWifiInfo.makeCopy(anyLong())).thenReturn(primaryWifiInfo);
@@ -86,8 +100,8 @@
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
// Verify primary wifi info is the one being used.
- assertThat(wifiStatusTracker.connected).isTrue();
- assertThat(wifiStatusTracker.rssi).isEqualTo(primaryRssi);
+ assertThat(mWifiStatusTracker.connected).isTrue();
+ assertThat(mWifiStatusTracker.rssi).isEqualTo(primaryRssi);
// Trigger a validation callback for the non-primary Wifi network.
WifiInfo nonPrimaryWifiInfo = Mockito.mock(WifiInfo.class);
@@ -106,20 +120,189 @@
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(nonPrimaryNetwork, nonPrimaryCap);
// Verify primary wifi info is still the one being used.
- assertThat(wifiStatusTracker.connected).isTrue();
- assertThat(wifiStatusTracker.rssi).isEqualTo(primaryRssi);
+ assertThat(mWifiStatusTracker.connected).isTrue();
+ assertThat(mWifiStatusTracker.rssi).isEqualTo(primaryRssi);
// Lose the non-primary network.
mNetworkCallbackCaptor.getValue().onLost(nonPrimaryNetwork);
// Verify primary wifi info is still the one being used.
- assertThat(wifiStatusTracker.connected).isTrue();
- assertThat(wifiStatusTracker.rssi).isEqualTo(primaryRssi);
+ assertThat(mWifiStatusTracker.connected).isTrue();
+ assertThat(mWifiStatusTracker.rssi).isEqualTo(primaryRssi);
// Lose the primary network.
mNetworkCallbackCaptor.getValue().onLost(primaryNetwork);
// Verify we aren't connected anymore.
- assertThat(wifiStatusTracker.connected).isFalse();
+ assertThat(mWifiStatusTracker.connected).isFalse();
+ }
+
+ @Test
+ public void isCarrierMerged_typicalWifi_false() {
+ WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
+ when(primaryWifiInfo.isPrimary()).thenReturn(true);
+
+ NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
+ when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)).thenReturn(true);
+ when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
+
+ assertThat(mWifiStatusTracker.isCarrierMerged).isFalse();
+ }
+
+ @Test
+ public void isCarrierMerged_typicalCellular_false() {
+ NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
+ when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
+
+ assertThat(mWifiStatusTracker.isCarrierMerged).isFalse();
+ }
+
+ @Test
+ public void isCarrierMerged_cellularCarrierMergedWifi_true() {
+ WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
+ when(primaryWifiInfo.isPrimary()).thenReturn(true);
+ when(primaryWifiInfo.isCarrierMerged()).thenReturn(true);
+
+ NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
+ when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
+ when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
+
+ assertThat(mWifiStatusTracker.isCarrierMerged).isTrue();
+ }
+
+ /** Test for b/225902574. */
+ @Test
+ public void isCarrierMerged_cellularWithUnderlyingCarrierMergedWifi_true() {
+ WifiInfo underlyingCarrierMergedInfo = Mockito.mock(WifiInfo.class);
+ when(underlyingCarrierMergedInfo.isPrimary()).thenReturn(true);
+ when(underlyingCarrierMergedInfo.isCarrierMerged()).thenReturn(true);
+
+ NetworkCapabilities underlyingNetworkCapabilities = Mockito.mock(NetworkCapabilities.class);
+ when(underlyingNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
+ .thenReturn(true);
+ when(underlyingNetworkCapabilities.getTransportInfo())
+ .thenReturn(underlyingCarrierMergedInfo);
+
+ Network underlyingNetwork = Mockito.mock(Network.class);
+ when(mConnectivityManager.getNetworkCapabilities(underlyingNetwork))
+ .thenReturn(underlyingNetworkCapabilities);
+
+ NetworkCapabilities mainCapabilities = Mockito.mock(NetworkCapabilities.class);
+ when(mainCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
+ .thenReturn(true);
+ when(mainCapabilities.getTransportInfo()).thenReturn(null);
+ when(mainCapabilities.getUnderlyingNetworks())
+ .thenReturn(Arrays.asList(underlyingNetwork));
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, mainCapabilities);
+
+ assertThat(mWifiStatusTracker.isCarrierMerged).isTrue();
+ }
+
+ @Test
+ public void isDefaultNetwork_typicalWifi_true() {
+ WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
+ when(primaryWifiInfo.isPrimary()).thenReturn(true);
+
+ NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
+ when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)).thenReturn(true);
+ when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
+
+ assertThat(mWifiStatusTracker.isDefaultNetwork).isTrue();
+ }
+
+ @Test
+ public void isDefaultNetwork_typicalCellular_false() {
+ NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
+ when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
+
+ assertThat(mWifiStatusTracker.isDefaultNetwork).isFalse();
+ }
+
+ @Test
+ public void isDefaultNetwork_cellularCarrierMergedWifi_true() {
+ WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
+ when(primaryWifiInfo.isPrimary()).thenReturn(true);
+ when(primaryWifiInfo.isCarrierMerged()).thenReturn(true);
+
+ NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
+ when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
+ when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
+
+ assertThat(mWifiStatusTracker.isDefaultNetwork).isTrue();
+ }
+
+ /** Test for b/225902574. */
+ @Test
+ public void isDefaultNetwork_cellularWithUnderlyingCarrierMergedWifi_true() {
+ WifiInfo underlyingCarrierMergedInfo = Mockito.mock(WifiInfo.class);
+ when(underlyingCarrierMergedInfo.isPrimary()).thenReturn(true);
+ when(underlyingCarrierMergedInfo.isCarrierMerged()).thenReturn(true);
+
+ NetworkCapabilities underlyingNetworkCapabilities = Mockito.mock(NetworkCapabilities.class);
+ when(underlyingNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
+ .thenReturn(true);
+ when(underlyingNetworkCapabilities.getTransportInfo())
+ .thenReturn(underlyingCarrierMergedInfo);
+
+ Network underlyingNetwork = Mockito.mock(Network.class);
+ when(mConnectivityManager.getNetworkCapabilities(underlyingNetwork))
+ .thenReturn(underlyingNetworkCapabilities);
+
+ NetworkCapabilities mainCapabilities = Mockito.mock(NetworkCapabilities.class);
+ when(mainCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
+ .thenReturn(true);
+ when(mainCapabilities.getTransportInfo()).thenReturn(null);
+ when(mainCapabilities.getUnderlyingNetworks())
+ .thenReturn(Arrays.asList(underlyingNetwork));
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mDefaultNetworkCallbackCaptor.getValue()
+ .onCapabilitiesChanged(primaryNetwork, mainCapabilities);
+
+ assertThat(mWifiStatusTracker.isDefaultNetwork).isTrue();
}
}
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index b95a149..e6bbf97 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -173,7 +173,6 @@
"androidx.palette_palette",
"androidx.legacy_legacy-preference-v14",
"androidx.leanback_leanback",
- "androidx.tracing_tracing",
"androidx.slice_slice-core",
"androidx.slice_slice-view",
"androidx.slice_slice-builders",
@@ -252,9 +251,11 @@
// domain
"tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt",
+ "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt",
+ "tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt",
// ui
"tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt",
@@ -263,6 +264,7 @@
"tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt",
"tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt",
"tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt",
+ "tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt",
// Keyguard helper
"tests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt",
"tests/src/com/android/systemui/dump/LogBufferHelper.kt",
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4652ef1..6e55000 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -695,7 +695,9 @@
android:relinquishTaskIdentity="true"
android:configChanges=
"screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
- android:visibleToInstantApps="true"/>
+ android:visibleToInstantApps="true"
+ android:exported="false"
+ android:permission="android.permission.MANAGE_MEDIA_PROJECTION"/>
<!-- started from TvNotificationPanel -->
<activity
@@ -966,22 +968,6 @@
android:permission="android.permission.BIND_JOB_SERVICE"/>
<!-- region Note Task -->
- <activity
- android:name=".notetask.shortcut.CreateNoteTaskShortcutActivity"
- android:enabled="false"
- android:exported="true"
- android:excludeFromRecents="true"
- android:resizeableActivity="false"
- android:theme="@android:style/Theme.NoDisplay"
- android:label="@string/note_task_button_label"
- android:icon="@drawable/ic_note_task_shortcut_widget">
-
- <intent-filter>
- <action android:name="android.intent.action.CREATE_SHORTCUT" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
-
<service android:name=".notetask.NoteTaskControllerUpdateService" />
<activity
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index 296c2ae..94b3740 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -436,8 +436,8 @@
}
@BinderThread
- override fun onAnimationCancelled(isKeyguardOccluded: Boolean) {
- context.mainExecutor.execute { delegate.onAnimationCancelled(isKeyguardOccluded) }
+ override fun onAnimationCancelled() {
+ context.mainExecutor.execute { delegate.onAnimationCancelled() }
}
}
@@ -744,7 +744,7 @@
}
@UiThread
- override fun onAnimationCancelled(isKeyguardOccluded: Boolean) {
+ override fun onAnimationCancelled() {
if (timedOut) {
return
}
@@ -754,7 +754,7 @@
removeTimeout()
animation?.cancel()
- controller.onLaunchAnimationCancelled(newKeyguardOccludedState = isKeyguardOccluded)
+ controller.onLaunchAnimationCancelled()
}
private fun IRemoteAnimationFinishedCallback.invoke() {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationDelegate.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationDelegate.kt
index 337408b..d465962 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationDelegate.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationDelegate.kt
@@ -26,5 +26,5 @@
)
/** Called on the UI thread when a signal is received to cancel the animation. */
- @UiThread fun onAnimationCancelled(isKeyguardOccluded: Boolean)
+ @UiThread fun onAnimationCancelled()
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
index 9d1dd1b..3a19990 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
@@ -22,12 +22,11 @@
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
-import android.graphics.Rect
import android.text.Layout
import android.text.TextUtils
import android.text.format.DateFormat
import android.util.AttributeSet
-import android.util.MathUtils
+import android.util.MathUtils.constrainedMap
import android.widget.TextView
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.animation.GlyphCallback
@@ -40,8 +39,6 @@
import java.util.Calendar
import java.util.Locale
import java.util.TimeZone
-import kotlin.math.max
-import kotlin.math.min
/**
* Displays the time with the hour positioned above the minutes. (ie: 09 above 30 is 9:30)
@@ -478,122 +475,56 @@
pw.println(" time=$time")
}
- fun moveForSplitShade(fromRect: Rect, toRect: Rect, fraction: Float) {
- // Do we need to cancel an in-flight animation?
- // Need to also check against 0.0f here; we can sometimes get two calls with fraction == 0,
- // which trips up the check otherwise.
- if (lastSeenAnimationProgress != 1.0f &&
- lastSeenAnimationProgress != 0.0f &&
- fraction == 0.0f) {
- // New animation, but need to stop the old one. Figure out where each glyph currently
- // is in relation to the box position. After that, use the leading digit's current
- // position as the stop target.
- currentAnimationNeededStop = true
+ private val moveToCenterDelays
+ get() = if (isLayoutRtl) MOVE_LEFT_DELAYS else MOVE_RIGHT_DELAYS
- // We assume that the current glyph offsets would be relative to the "from" position.
- val moveAmount = toRect.left - fromRect.left
+ private val moveToSideDelays
+ get() = if (isLayoutRtl) MOVE_RIGHT_DELAYS else MOVE_LEFT_DELAYS
- // Remap the current glyph offsets to be relative to the new "end" position, and figure
- // out the start/end positions for the stop animation.
- for (i in 0 until NUM_DIGITS) {
- glyphOffsets[i] = -moveAmount + glyphOffsets[i]
- animationCancelStartPosition[i] = glyphOffsets[i]
- }
-
- // Use the leading digit's offset as the stop position.
- if (toRect.left > fromRect.left) {
- // It _was_ moving left
- animationCancelStopPosition = glyphOffsets[0]
- } else {
- // It was moving right
- animationCancelStopPosition = glyphOffsets[1]
- }
- }
-
- // Is there a cancellation in progress?
- if (currentAnimationNeededStop && fraction < ANIMATION_CANCELLATION_TIME) {
- val animationStopProgress = MathUtils.constrainedMap(
- 0.0f, 1.0f, 0.0f, ANIMATION_CANCELLATION_TIME, fraction
- )
-
- // One of the digits has already stopped.
- val animationStopStep = 1.0f / (NUM_DIGITS - 1)
-
- for (i in 0 until NUM_DIGITS) {
- val stopAmount = if (toRect.left > fromRect.left) {
- // It was moving left (before flipping)
- MOVE_LEFT_DELAYS[i] * animationStopStep
- } else {
- // It was moving right (before flipping)
- MOVE_RIGHT_DELAYS[i] * animationStopStep
- }
-
- // Leading digit stops immediately.
- if (stopAmount == 0.0f) {
- glyphOffsets[i] = animationCancelStopPosition
- } else {
- val actualStopAmount = MathUtils.constrainedMap(
- 0.0f, 1.0f, 0.0f, stopAmount, animationStopProgress
+ /**
+ * Offsets the glyphs of the clock for the step clock animation.
+ *
+ * The animation makes the glyphs of the clock move at different speeds, when the clock is
+ * moving horizontally.
+ *
+ * @param clockStartLeft the [getLeft] position of the clock, before it started moving.
+ * @param clockMoveDirection the direction in which it is moving. A positive number means right,
+ * and negative means left.
+ * @param moveFraction fraction of the clock movement. 0 means it is at the beginning, and 1
+ * means it finished moving.
+ */
+ fun offsetGlyphsForStepClockAnimation(
+ clockStartLeft: Int,
+ clockMoveDirection: Int,
+ moveFraction: Float
+ ) {
+ val isMovingToCenter = if (isLayoutRtl) clockMoveDirection < 0 else clockMoveDirection > 0
+ val currentMoveAmount = left - clockStartLeft
+ val digitOffsetDirection = if (isLayoutRtl) -1 else 1
+ for (i in 0 until NUM_DIGITS) {
+ // The delay for the digit, in terms of fraction (i.e. the digit should not move
+ // during 0.0 - 0.1).
+ val digitInitialDelay =
+ if (isMovingToCenter) {
+ moveToCenterDelays[i] * MOVE_DIGIT_STEP
+ } else {
+ moveToSideDelays[i] * MOVE_DIGIT_STEP
+ }
+ val digitFraction =
+ MOVE_INTERPOLATOR.getInterpolation(
+ constrainedMap(
+ 0.0f,
+ 1.0f,
+ digitInitialDelay,
+ digitInitialDelay + AVAILABLE_ANIMATION_TIME,
+ moveFraction
+ )
)
- val easedProgress = MOVE_INTERPOLATOR.getInterpolation(actualStopAmount)
- val glyphMoveAmount =
- animationCancelStopPosition - animationCancelStartPosition[i]
- glyphOffsets[i] =
- animationCancelStartPosition[i] + glyphMoveAmount * easedProgress
- }
- }
- } else {
- // Normal part of the animation.
- // Do we need to remap the animation progress to take account of the cancellation?
- val actualFraction = if (currentAnimationNeededStop) {
- MathUtils.constrainedMap(
- 0.0f, 1.0f, ANIMATION_CANCELLATION_TIME, 1.0f, fraction
- )
- } else {
- fraction
- }
-
- val digitFractions = (0 until NUM_DIGITS).map {
- // The delay for each digit, in terms of fraction (i.e. the digit should not move
- // during 0.0 - 0.1).
- val initialDelay = if (toRect.left > fromRect.left) {
- MOVE_RIGHT_DELAYS[it] * MOVE_DIGIT_STEP
- } else {
- MOVE_LEFT_DELAYS[it] * MOVE_DIGIT_STEP
- }
-
- val f = MathUtils.constrainedMap(
- 0.0f, 1.0f,
- initialDelay, initialDelay + AVAILABLE_ANIMATION_TIME,
- actualFraction
- )
- MOVE_INTERPOLATOR.getInterpolation(max(min(f, 1.0f), 0.0f))
- }
-
- // Was there an animation halt?
- val moveAmount = if (currentAnimationNeededStop) {
- // Only need to animate over the remaining space if the animation was aborted.
- -animationCancelStopPosition
- } else {
- toRect.left.toFloat() - fromRect.left.toFloat()
- }
-
- for (i in 0 until NUM_DIGITS) {
- glyphOffsets[i] = -moveAmount + (moveAmount * digitFractions[i])
- }
+ val moveAmountForDigit = currentMoveAmount * digitFraction
+ val moveAmountDeltaForDigit = moveAmountForDigit - currentMoveAmount
+ glyphOffsets[i] = digitOffsetDirection * moveAmountDeltaForDigit
}
-
invalidate()
-
- if (fraction == 1.0f) {
- // Reset
- currentAnimationNeededStop = false
- }
-
- lastSeenAnimationProgress = fraction
-
- // Ensure that the actual clock container is always in the "end" position.
- this.setLeftTopRightBottom(toRect.left, toRect.top, toRect.right, toRect.bottom)
}
// DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often.
@@ -647,9 +578,6 @@
private const val NUM_DIGITS = 4
private const val DIGITS_PER_LINE = 2
- // How much of "fraction" to spend on canceling the animation, if needed
- private const val ANIMATION_CANCELLATION_TIME = 0f
-
// Delays. Each digit's animation should have a slight delay, so we get a nice
// "stepping" effect. When moving right, the second digit of the hour should move first.
// When moving left, the first digit of the hour should move first. The lists encode
@@ -668,6 +596,6 @@
// Total available transition time for each digit, taking into account the step. If step is
// 0.1, then digit 0 would animate over 0.0 - 0.7, making availableTime 0.7.
- private val AVAILABLE_ANIMATION_TIME = 1.0f - MOVE_DIGIT_STEP * (NUM_DIGITS - 1)
+ private const val AVAILABLE_ANIMATION_TIME = 1.0f - MOVE_DIGIT_STEP * (NUM_DIGITS - 1)
}
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index f57432c..b0c0240 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -151,6 +151,7 @@
{ str1 = id },
{ "Clock Id conflict on load: $str1 is double registered" }
)
+ manager.unloadPlugin()
continue
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index 3fda83d..2cc3600 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -189,8 +189,9 @@
view.setLayoutParams(lp)
}
- fun moveForSplitShade(fromRect: Rect, toRect: Rect, fraction: Float) {
- view.moveForSplitShade(fromRect, toRect, fraction)
+ /** See documentation at [AnimatableClockView.offsetGlyphsForStepClockAnimation]. */
+ fun offsetGlyphsForStepClockAnimation(fromLeft: Int, direction: Int, fraction: Float) {
+ view.offsetGlyphsForStepClockAnimation(fromLeft, direction, fraction)
}
}
@@ -277,8 +278,8 @@
dozeFraction: Float,
foldFraction: Float,
) : DefaultClockAnimations(view, dozeFraction, foldFraction) {
- override fun onPositionUpdated(fromRect: Rect, toRect: Rect, fraction: Float) {
- largeClock.moveForSplitShade(fromRect, toRect, fraction)
+ override fun onPositionUpdated(fromLeft: Int, direction: Int, fraction: Float) {
+ largeClock.offsetGlyphsForStepClockAnimation(fromLeft, direction, fraction)
}
}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
index e6b2c2f..e839d9b 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/DynamicColor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -71,12 +71,11 @@
* The base constructor for DynamicColor.
*
* <p>Functional arguments allow overriding without risks that come with subclasses. _Strongly_
- * prefer using one of the static convenience constructors. This class is arguably too flexible
- * to
+ * prefer using one of the static convenience constructors. This class is arguably too
+ * flexible to
* ensure it can support any scenario.
*
- * <p>For example, the default behavior of adjust tone at max contrast to be at a 7.0 ratio
- * with
+ * <p>For example, the default behavior of adjust tone at max contrast to be at a 7.0 ratio with
* its background is principled and matches a11y guidance. That does not mean it's the desired
* approach for _every_ design system, and every color pairing, always, in every case.
*
@@ -89,23 +88,23 @@
* lower and raise contrast are
* made.
* @param toneMinContrast given DynamicScheme, return tone in HCT/L* in L*a*b* this color
- * should
- * be at minimum contrast. See toneMinContrastDefault for the default
- * behavior, and strongly
+ * should
+ * be at minimum contrast. See toneMinContrastDefault for the
+ * default behavior, and strongly
* consider using it unless you have strong opinions on a11y. The
* static constructors use it.
* @param toneMaxContrast given DynamicScheme, return tone in HCT/L* in L*a*b* this color
- * should
- * be at maximum contrast. See toneMaxContrastDefault for the default
- * behavior, and strongly
+ * should
+ * be at maximum contrast. See toneMaxContrastDefault for the
+ * default behavior, and strongly
* consider using it unless you have strong opinions on a11y. The
* static constructors use it.
* @param toneDeltaConstraint given DynamicScheme, return a ToneDeltaConstraint instance that
* describes a requirement that this DynamicColor must always have
* some difference in tone/L*
* from another DynamicColor.<br>
- * Unlikely to be useful unless a design system has some distortions
- * where colors that don't
+ * Unlikely to be useful unless a design system has some
+ * distortions where colors that don't
* have a background/foreground relationship must have _some_
* difference in tone, yet, not
* enough difference to create meaningful contrast.
@@ -164,8 +163,8 @@
* <p>If the design system uses the same hex code on multiple backgrounds, define that in
* multiple
* DynamicColors so that the background is accurate for each one. If you define a DynamicColor
- * with one background, and actually use it on another, DynamicColor can't guarantee contrast.
- * For
+ * with one background, and actually use it on another, DynamicColor can't guarantee contrast
+ * . For
* example, if you use a color on both black and white, increasing the contrast on one
* necessarily
* decreases contrast of the other.
@@ -195,8 +194,8 @@
* for contrast, given a background, colors can adjust to
* increase/decrease contrast.
* @param toneDeltaConstraint Function that provides a ToneDeltaConstraint given DynamicScheme.
- * Useful for ensuring lightness difference between colors that don't
- * _require_ contrast or
+ * Useful for ensuring lightness difference between colors that
+ * don't _require_ contrast or
* have a formal background/foreground relationship.
*/
public static DynamicColor fromArgb(
@@ -212,17 +211,17 @@
* Create a DynamicColor.
*
* @param palette Function that provides a TonalPalette given DynamicScheme. A TonalPalette is
- * defined by a hue and chroma, so this replaces the need to specify hue/chroma.
- * By providing
+ * defined by a hue and chroma, so this replaces the need to specify
+ * hue/chroma. By providing
* a tonal palette, when contrast adjustments are made, intended chroma can be
* preserved. For
* example, at T/L* 90, there is a significant limit to the amount of chroma.
* There is no
- * colorful red, a red that light is pink. By preserving the _intended_ chroma if
- * lightness
+ * colorful red, a red that light is pink. By preserving the _intended_ chroma
+ * if lightness
* lowers for contrast adjustments, the intended chroma is restored.
- * @param tone Function that provides a tone given DynamicScheme. (useful for dark vs. light
- * mode)
+ * @param tone Function that provides a tone given DynamicScheme. (useful for dark vs.
+ * light mode)
*/
public static DynamicColor fromPalette(
Function<DynamicScheme, TonalPalette> palette, Function<DynamicScheme, Double> tone) {
@@ -232,16 +231,16 @@
/**
* Create a DynamicColor.
*
- * @param palette Function that provides a TonalPalette given DynamicScheme. A TonalPalette
- * is
+ * @param palette Function that provides a TonalPalette given DynamicScheme. A
+ * TonalPalette is
* defined by a hue and chroma, so this replaces the need to specify
* hue/chroma. By providing
- * a tonal palette, when contrast adjustments are made, intended chroma can be
- * preserved. For
- * example, at T/L* 90, there is a significant limit to the amount of chroma.
- * There is no
- * colorful red, a red that light is pink. By preserving the _intended_ chroma
- * if lightness
+ * a tonal palette, when contrast adjustments are made, intended chroma can
+ * be preserved. For
+ * example, at T/L* 90, there is a significant limit to the amount of
+ * chroma. There is no
+ * colorful red, a red that light is pink. By preserving the _intended_
+ * chroma if lightness
* lowers for contrast adjustments, the intended chroma is restored.
* @param tone Function that provides a tone given DynamicScheme. (useful for dark vs.
* light mode)
@@ -261,12 +260,12 @@
*
* @param palette Function that provides a TonalPalette given DynamicScheme. A
* TonalPalette is
- * defined by a hue and chroma, so this replaces the need to specify
- * hue/chroma. By providing
+ * defined by a hue and chroma, so this replaces the need to
+ * specify hue/chroma. By providing
* a tonal palette, when contrast adjustments are made, intended
* chroma can be preserved. For
- * example, at T/L* 90, there is a significant limit to the amount of
- * chroma. There is no
+ * example, at T/L* 90, there is a significant limit to the amount
+ * of chroma. There is no
* colorful red, a red that light is pink. By preserving the
* _intended_ chroma if lightness
* lowers for contrast adjustments, the intended chroma is restored.
@@ -277,8 +276,8 @@
* for contrast, given a background, colors can adjust to
* increase/decrease contrast.
* @param toneDeltaConstraint Function that provides a ToneDeltaConstraint given DynamicScheme.
- * Useful for ensuring lightness difference between colors that don't
- * _require_ contrast or
+ * Useful for ensuring lightness difference between colors that
+ * don't _require_ contrast or
* have a formal background/foreground relationship.
*/
public static DynamicColor fromPalette(
@@ -297,96 +296,6 @@
toneDeltaConstraint);
}
- /** Returns the ARGB (i.e. hex code) representation of the resolved color given scheme. */
- public int getArgb(DynamicScheme scheme) {
- final int argb = getHct(scheme).toInt();
- if (opacity == null) {
- return argb;
- }
- final double percentage = opacity.apply(scheme);
- final int alpha = MathUtils.clampInt(0, 255, (int) Math.round(percentage * 255));
- return (argb & 0x00ffffff) | (alpha << 24);
- }
-
- /** Returns the HCT representation of the resolved color given scheme. */
- public Hct getHct(DynamicScheme scheme) {
- final Hct cachedAnswer = hctCache.get(scheme);
- if (cachedAnswer != null) {
- return cachedAnswer;
- }
- // This is crucial for aesthetics: we aren't simply the taking the standard color
- // and changing its tone for contrast. Rather, we find the tone for contrast, then
- // use the specified chroma from the palette to construct a new color.
- //
- // For example, this enables colors with standard tone of T90, which has limited chroma, to
- // "recover" intended chroma as contrast increases.
- final Hct answer = Hct.from(hue.apply(scheme), chroma.apply(scheme), getTone(scheme));
- // NOMUTANTS--trivial test with onerous dependency injection requirement.
- if (hctCache.size() > 4) {
- hctCache.clear();
- }
- // NOMUTANTS--trivial test with onerous dependency injection requirement.
- hctCache.put(scheme, answer);
- return answer;
- }
-
- /** Returns the tone in HCT, ranging from 0 to 100, of the resolved color given scheme. */
- public double getTone(DynamicScheme scheme) {
- double answer = tone.apply(scheme);
-
- final boolean decreasingContrast = scheme.contrastLevel < 0.0;
- if (scheme.contrastLevel != 0.0) {
- final double startTone = tone.apply(scheme);
- final double endTone =
- decreasingContrast ? toneMinContrast.apply(scheme) : toneMaxContrast.apply(
- scheme);
- final double delta = (endTone - startTone) * Math.abs(scheme.contrastLevel);
- answer = delta + startTone;
- }
-
- final DynamicColor bgDynamicColor = background == null ? null : background.apply(scheme);
- double minRatio = Contrast.RATIO_MIN;
- double maxRatio = Contrast.RATIO_MAX;
- if (bgDynamicColor != null) {
- final boolean bgHasBg =
- bgDynamicColor.background != null && bgDynamicColor.background.apply(scheme)
- != null;
- final double standardRatio =
- Contrast.ratioOfTones(tone.apply(scheme), bgDynamicColor.tone.apply(scheme));
- if (decreasingContrast) {
- final double minContrastRatio =
- Contrast.ratioOfTones(
- toneMinContrast.apply(scheme),
- bgDynamicColor.toneMinContrast.apply(scheme));
- minRatio = bgHasBg ? minContrastRatio : 1.0;
- maxRatio = standardRatio;
- } else {
- final double maxContrastRatio =
- Contrast.ratioOfTones(
- toneMaxContrast.apply(scheme),
- bgDynamicColor.toneMaxContrast.apply(scheme));
- minRatio = bgHasBg ? min(maxContrastRatio, standardRatio) : 1.0;
- maxRatio = bgHasBg ? max(maxContrastRatio, standardRatio) : 21.0;
- }
- }
-
- final double finalMinRatio = minRatio;
- final double finalMaxRatio = maxRatio;
- final double finalAnswer = answer;
- answer =
- calculateDynamicTone(
- scheme,
- this.tone,
- (dynamicColor) -> dynamicColor.getTone(scheme),
- (a, b) -> finalAnswer,
- (s) -> bgDynamicColor,
- toneDeltaConstraint,
- (s) -> finalMinRatio,
- (s) -> finalMaxRatio);
-
- return answer;
- }
-
/**
* The default algorithm for calculating the tone of a color at minimum contrast.<br>
* If the original contrast ratio was >= 7.0, reach contrast 4.5.<br>
@@ -475,8 +384,8 @@
* <p>It enforces important properties:<br>
* #1. Desired contrast ratio is reached.<br>
* As contrast increases from standard to max, the tones involved should always be at least the
- * standard ratio. For example, if a button is T90, and button text is T0, and the button is T0
- * at
+ * standard ratio. For example, if a button is T90, and button text is T0, and the button is
+ * T0 at
* max contrast, the button text cannot simply linearly interpolate from T0 to T100, or at some
* point they'll both be at the same tone.
*
@@ -489,8 +398,7 @@
*
* <p>#3. Ensure tone delta with another color.<br>
* In design systems, there may be colors that don't have a pure background/foreground
- * relationship, but, do require different tones for visual differentiation.
- * ToneDeltaConstraint
+ * relationship, but, do require different tones for visual differentiation. ToneDeltaConstraint
* models this requirement, and DynamicColor enforces it.
*/
public static double calculateDynamicTone(
@@ -596,13 +504,16 @@
final boolean preferLighter = tonePrefersLightForeground(bgTone);
if (preferLighter) {
- // "Negligible difference" handles an edge case where the initial contrast ratio is high
+ // "Neglible difference" handles an edge case where the initial contrast ratio is high
// (ex. 13.0), and the ratio passed to the function is that high ratio, and both the
- // lighter and darker ratio fails to pass that ratio.
+ // lighter
+ // and darker ratio fails to pass that ratio.
//
// This was observed with Tonal Spot's On Primary Container turning black momentarily
- // between high and max contrast in light mode. PC's standard tone was T90, OPC's was
- // T10, it was light mode, and the contrast level was 0.6568521221032331.
+ // between
+ // high and max contrast in light mode. PC's standard tone was T90, OPC's was T10, it
+ // was
+ // light mode, and the contrast level was 0.6568521221032331.
final boolean negligibleDifference =
Math.abs(lighterRatio - darkerRatio) < 0.1 && lighterRatio < ratio
&& darkerRatio < ratio;
@@ -634,13 +545,109 @@
* <p>T60 used as to create the smallest discontinuity possible when skipping down to T49 in
* order
* to ensure light foregrounds.
+ *
+ * <p>Since `tertiaryContainer` in dark monochrome scheme requires a tone of 60, it should
+ * not be
+ * adjusted. Therefore, 60 is excluded here.
*/
public static boolean tonePrefersLightForeground(double tone) {
- return Math.round(tone) <= 60;
+ return Math.round(tone) < 60;
}
- /** Tones less than ~T50 always permit white at 4.5 contrast. */
+ /**
+ * Tones less than ~T50 always permit white at 4.5 contrast.
+ */
public static boolean toneAllowsLightForeground(double tone) {
return Math.round(tone) <= 49;
}
+
+ public int getArgb(DynamicScheme scheme) {
+ final int argb = getHct(scheme).toInt();
+ if (opacity == null) {
+ return argb;
+ }
+ final double percentage = opacity.apply(scheme);
+ final int alpha = MathUtils.clampInt(0, 255, (int) Math.round(percentage * 255));
+ return (argb & 0x00ffffff) | (alpha << 24);
+ }
+
+ public Hct getHct(DynamicScheme scheme) {
+ final Hct cachedAnswer = hctCache.get(scheme);
+ if (cachedAnswer != null) {
+ return cachedAnswer;
+ }
+ // This is crucial for aesthetics: we aren't simply the taking the standard color
+ // and changing its tone for contrast. Rather, we find the tone for contrast, then
+ // use the specified chroma from the palette to construct a new color.
+ //
+ // For example, this enables colors with standard tone of T90, which has limited chroma, to
+ // "recover" intended chroma as contrast increases.
+ final Hct answer = Hct.from(hue.apply(scheme), chroma.apply(scheme), getTone(scheme));
+ // NOMUTANTS--trivial test with onerous dependency injection requirement.
+ if (hctCache.size() > 4) {
+ hctCache.clear();
+ }
+ // NOMUTANTS--trivial test with onerous dependency injection requirement.
+ hctCache.put(scheme, answer);
+ return answer;
+ }
+
+ /**
+ * Returns the tone in HCT, ranging from 0 to 100, of the resolved color given scheme.
+ */
+ public double getTone(DynamicScheme scheme) {
+ double answer = tone.apply(scheme);
+
+ final boolean decreasingContrast = scheme.contrastLevel < 0.0;
+ if (scheme.contrastLevel != 0.0) {
+ final double startTone = tone.apply(scheme);
+ final double endTone =
+ decreasingContrast ? toneMinContrast.apply(scheme) : toneMaxContrast.apply(
+ scheme);
+ final double delta = (endTone - startTone) * Math.abs(scheme.contrastLevel);
+ answer = delta + startTone;
+ }
+
+ final DynamicColor bgDynamicColor = background == null ? null : background.apply(scheme);
+ double minRatio = Contrast.RATIO_MIN;
+ double maxRatio = Contrast.RATIO_MAX;
+ if (bgDynamicColor != null) {
+ final boolean bgHasBg =
+ bgDynamicColor.background != null && bgDynamicColor.background.apply(scheme)
+ != null;
+ final double standardRatio =
+ Contrast.ratioOfTones(tone.apply(scheme), bgDynamicColor.tone.apply(scheme));
+ if (decreasingContrast) {
+ final double minContrastRatio =
+ Contrast.ratioOfTones(
+ toneMinContrast.apply(scheme),
+ bgDynamicColor.toneMinContrast.apply(scheme));
+ minRatio = bgHasBg ? minContrastRatio : 1.0;
+ maxRatio = standardRatio;
+ } else {
+ final double maxContrastRatio =
+ Contrast.ratioOfTones(
+ toneMaxContrast.apply(scheme),
+ bgDynamicColor.toneMaxContrast.apply(scheme));
+ minRatio = bgHasBg ? min(maxContrastRatio, standardRatio) : 1.0;
+ maxRatio = bgHasBg ? max(maxContrastRatio, standardRatio) : 21.0;
+ }
+ }
+
+ final double finalMinRatio = minRatio;
+ final double finalMaxRatio = maxRatio;
+ final double finalAnswer = answer;
+ answer =
+ calculateDynamicTone(
+ scheme,
+ this.tone,
+ (dynamicColor) -> dynamicColor.getTone(scheme),
+ (a, b) -> finalAnswer,
+ (s) -> bgDynamicColor,
+ toneDeltaConstraint,
+ (s) -> finalMinRatio,
+ (s) -> finalMaxRatio);
+
+ return answer;
+ }
}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java
index 5212e8e..21218a2 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java
@@ -22,7 +22,7 @@
import com.android.systemui.monet.scheme.DynamicScheme;
import com.android.systemui.monet.scheme.Variant;
-/** Named colors, otherwise known as tokens, or roles, in the Material Design system. */
+/** Named colors, otherwise known as tokens, or roles, in the Material Design system.*/
// Prevent lint for Function.apply not being available on Android before API level 14 (4.0.1).
// "AndroidJdkLibsChecker" for Function, "NewApi" for Function.apply().
// A java_library Bazel rule with an Android constraint cannot skip these warnings without this
@@ -33,341 +33,54 @@
private static final double CONTAINER_ACCENT_TONE_DELTA = 15.0;
- private MaterialDynamicColors() {
+ public MaterialDynamicColors() {
}
- public static DynamicColor highestSurface(DynamicScheme s) {
- return s.isDark ? surfaceBright : surfaceDim;
- }
-
- public static final DynamicColor background =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 98.0);
-
- public static final DynamicColor onBackground =
- DynamicColor.fromPalette(
- (s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 10.0, (s) -> background);
-
- public static final DynamicColor surface =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 98.0);
-
- public static final DynamicColor surfaceInverse =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 30.0);
-
- public static final DynamicColor surfaceBright =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 24.0 : 98.0);
-
- public static final DynamicColor surfaceDim =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 87.0);
-
- public static final DynamicColor surfaceSub2 =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 4.0 : 100.0);
-
- public static final DynamicColor surfaceSub1 =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 96.0);
-
- public static final DynamicColor surfaceContainer =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 12.0 : 94.0);
-
- public static final DynamicColor surfaceAdd1 =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 17.0 : 92.0);
-
- public static final DynamicColor surfaceAdd2 =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 22.0 : 90.0);
-
- public static final DynamicColor onSurface =
- DynamicColor.fromPalette(
- (s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 10.0,
- (s) -> highestSurface(s));
-
- public static final DynamicColor onSurfaceInverse =
- DynamicColor.fromPalette(
- (s) -> s.neutralPalette, (s) -> s.isDark ? 20.0 : 95.0, (s) -> surfaceInverse);
-
- public static final DynamicColor surfaceVariant =
- DynamicColor.fromPalette((s) -> s.neutralVariantPalette, (s) -> s.isDark ? 30.0 : 90.0);
-
- public static final DynamicColor onSurfaceVariant =
- DynamicColor.fromPalette(
- (s) -> s.neutralVariantPalette, (s) -> s.isDark ? 80.0 : 30.0,
- (s) -> surfaceVariant);
-
- public static final DynamicColor outline =
- DynamicColor.fromPalette(
- (s) -> s.neutralVariantPalette, (s) -> 50.0, (s) -> highestSurface(s));
-
- public static final DynamicColor outlineVariant =
- DynamicColor.fromPalette(
- (s) -> s.neutralVariantPalette, (s) -> s.isDark ? 30.0 : 80.0,
- (s) -> highestSurface(s));
-
- public static final DynamicColor primaryContainer =
- DynamicColor.fromPalette(
- (s) -> s.primaryPalette,
- (s) -> {
- if (!isFidelity(s)) {
- return s.isDark ? 30.0 : 90.0;
- }
- return performAlbers(s.sourceColorHct, s);
- },
- (s) -> highestSurface(s));
-
- public static final DynamicColor onPrimaryContainer =
- DynamicColor.fromPalette(
- (s) -> s.primaryPalette,
- (s) -> {
- if (!isFidelity(s)) {
- return s.isDark ? 90.0 : 10.0;
- }
- return DynamicColor.contrastingTone(primaryContainer.tone.apply(s), 4.5);
- },
- (s) -> primaryContainer,
- null);
-
- public static final DynamicColor primary =
- DynamicColor.fromPalette(
- (s) -> s.primaryPalette,
- (s) -> s.isDark ? 80.0 : 40.0,
- (s) -> highestSurface(s),
- (s) ->
- new ToneDeltaConstraint(
- CONTAINER_ACCENT_TONE_DELTA,
- primaryContainer,
- s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER));
-
- public static final DynamicColor primaryInverse =
- DynamicColor.fromPalette(
- (s) -> s.primaryPalette, (s) -> s.isDark ? 40.0 : 80.0, (s) -> surfaceInverse);
-
- public static final DynamicColor onPrimary =
- DynamicColor.fromPalette(
- (s) -> s.primaryPalette, (s) -> s.isDark ? 20.0 : 100.0, (s) -> primary);
-
- public static final DynamicColor secondaryContainer =
- DynamicColor.fromPalette(
- (s) -> s.secondaryPalette,
- (s) -> {
- final double initialTone = s.isDark ? 30.0 : 90.0;
- if (!isFidelity(s)) {
- return initialTone;
- }
- double answer =
- findDesiredChromaByTone(
- s.secondaryPalette.getHue(),
- s.secondaryPalette.getChroma(),
- initialTone,
- !s.isDark);
- answer = performAlbers(s.secondaryPalette.getHct(answer), s);
- return answer;
- },
- (s) -> highestSurface(s));
-
- public static final DynamicColor onSecondaryContainer =
- DynamicColor.fromPalette(
- (s) -> s.secondaryPalette,
- (s) -> {
- if (!isFidelity(s)) {
- return s.isDark ? 90.0 : 10.0;
- }
- return DynamicColor.contrastingTone(secondaryContainer.tone.apply(s), 4.5);
- },
- (s) -> secondaryContainer);
-
- public static final DynamicColor secondary =
- DynamicColor.fromPalette(
- (s) -> s.secondaryPalette,
- (s) -> s.isDark ? 80.0 : 40.0,
- (s) -> highestSurface(s),
- (s) ->
- new ToneDeltaConstraint(
- CONTAINER_ACCENT_TONE_DELTA,
- secondaryContainer,
- s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER));
-
- public static final DynamicColor onSecondary =
- DynamicColor.fromPalette(
- (s) -> s.secondaryPalette, (s) -> s.isDark ? 20.0 : 100.0, (s) -> secondary);
-
- public static final DynamicColor tertiaryContainer =
- DynamicColor.fromPalette(
- (s) -> s.tertiaryPalette,
- (s) -> {
- if (!isFidelity(s)) {
- return s.isDark ? 30.0 : 90.0;
- }
- final double albersTone =
- performAlbers(s.tertiaryPalette.getHct(s.sourceColorHct.getTone()),
- s);
- final Hct proposedHct = s.tertiaryPalette.getHct(albersTone);
- return DislikeAnalyzer.fixIfDisliked(proposedHct).getTone();
- },
- (s) -> highestSurface(s));
-
- public static final DynamicColor onTertiaryContainer =
- DynamicColor.fromPalette(
- (s) -> s.tertiaryPalette,
- (s) -> {
- if (!isFidelity(s)) {
- return s.isDark ? 90.0 : 10.0;
- }
- return DynamicColor.contrastingTone(tertiaryContainer.tone.apply(s), 4.5);
- },
- (s) -> tertiaryContainer);
-
- public static final DynamicColor tertiary =
- DynamicColor.fromPalette(
- (s) -> s.tertiaryPalette,
- (s) -> s.isDark ? 80.0 : 40.0,
- (s) -> highestSurface(s),
- (s) ->
- new ToneDeltaConstraint(
- CONTAINER_ACCENT_TONE_DELTA,
- tertiaryContainer,
- s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER));
-
- public static final DynamicColor onTertiary =
- DynamicColor.fromPalette(
- (s) -> s.tertiaryPalette, (s) -> s.isDark ? 20.0 : 100.0, (s) -> tertiary);
-
- public static final DynamicColor errorContainer =
- DynamicColor.fromPalette(
- (s) -> s.errorPalette, (s) -> s.isDark ? 30.0 : 90.0, (s) -> highestSurface(s));
-
- public static final DynamicColor onErrorContainer =
- DynamicColor.fromPalette(
- (s) -> s.errorPalette, (s) -> s.isDark ? 90.0 : 10.0, (s) -> errorContainer);
-
- public static final DynamicColor error =
- DynamicColor.fromPalette(
- (s) -> s.errorPalette,
- (s) -> s.isDark ? 80.0 : 40.0,
- (s) -> highestSurface(s),
- (s) ->
- new ToneDeltaConstraint(
- CONTAINER_ACCENT_TONE_DELTA,
- errorContainer,
- s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER));
-
- public static final DynamicColor onError =
- DynamicColor.fromPalette((s) -> s.errorPalette, (s) -> s.isDark ? 20.0 : 100.0,
- (s) -> error);
-
- public static final DynamicColor primaryFixed =
- DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> 90.0,
- (s) -> highestSurface(s));
-
- public static final DynamicColor primaryFixedDarker =
- DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> 80.0,
- (s) -> highestSurface(s));
-
- public static final DynamicColor onPrimaryFixed =
- DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> 10.0,
- (s) -> primaryFixedDarker);
-
- public static final DynamicColor onPrimaryFixedVariant =
- DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> 30.0,
- (s) -> primaryFixedDarker);
-
- public static final DynamicColor secondaryFixed =
- DynamicColor.fromPalette((s) -> s.secondaryPalette, (s) -> 90.0,
- (s) -> highestSurface(s));
-
- public static final DynamicColor secondaryFixedDarker =
- DynamicColor.fromPalette((s) -> s.secondaryPalette, (s) -> 80.0,
- (s) -> highestSurface(s));
-
- public static final DynamicColor onSecondaryFixed =
- DynamicColor.fromPalette((s) -> s.secondaryPalette, (s) -> 10.0,
- (s) -> secondaryFixedDarker);
-
- public static final DynamicColor onSecondaryFixedVariant =
- DynamicColor.fromPalette((s) -> s.secondaryPalette, (s) -> 30.0,
- (s) -> secondaryFixedDarker);
-
- public static final DynamicColor tertiaryFixed =
- DynamicColor.fromPalette((s) -> s.tertiaryPalette, (s) -> 90.0,
- (s) -> highestSurface(s));
-
- public static final DynamicColor tertiaryFixedDarker =
- DynamicColor.fromPalette((s) -> s.tertiaryPalette, (s) -> 80.0,
- (s) -> highestSurface(s));
-
- public static final DynamicColor onTertiaryFixed =
- DynamicColor.fromPalette((s) -> s.tertiaryPalette, (s) -> 10.0,
- (s) -> tertiaryFixedDarker);
-
- public static final DynamicColor onTertiaryFixedVariant =
- DynamicColor.fromPalette((s) -> s.tertiaryPalette, (s) -> 30.0,
- (s) -> tertiaryFixedDarker);
-
/**
* These colors were present in Android framework before Android U, and used by MDC controls.
* They
* should be avoided, if possible. It's unclear if they're used on multiple backgrounds, and if
- * they are, they can't be adjusted for contrast.* For now, they will be set with no
- * background,
+ * they are, they can't be adjusted for contrast.* For now, they will be set with no background,
* and those won't adjust for contrast, avoiding issues.
*
- * <p>* For example, if the same color is on a white background _and_ black background, there's
- * no
+ * <p>* For example, if the same color is on a white background _and_ black background,
+ * there's no
* way to increase contrast with either without losing contrast with the other.
*/
// colorControlActivated documented as colorAccent in M3 & GM3.
// colorAccent documented as colorSecondary in M3 and colorPrimary in GM3.
// Android used Material's Container as Primary/Secondary/Tertiary at launch.
// Therefore, this is a duplicated version of Primary Container.
- public static final DynamicColor controlActivated =
- DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> s.isDark ? 30.0 : 90.0, null);
+ public static DynamicColor controlActivated() {
+ return DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> s.isDark ? 30.0 : 90.0, null);
+ }
- // colorControlNormal documented as textColorSecondary in M3 & GM3.
- // In Material, textColorSecondary points to onSurfaceVariant in the non-disabled state,
- // which is Neutral Variant T30/80 in light/dark.
- public static final DynamicColor controlNormal =
- DynamicColor.fromPalette((s) -> s.neutralVariantPalette, (s) -> s.isDark ? 80.0 : 30.0);
+ // Compatibility Keys Colors for Android
+ public static DynamicColor primaryPaletteKeyColor() {
+ return DynamicColor.fromPalette(
+ (s) -> s.primaryPalette, (s) -> s.primaryPalette.getKeyColor().getTone());
+ }
- // colorControlHighlight documented, in both M3 & GM3:
- // Light mode: #1f000000 dark mode: #33ffffff.
- // These are black and white with some alpha.
- // 1F hex = 31 decimal; 31 / 255 = 12% alpha.
- // 33 hex = 51 decimal; 51 / 255 = 20% alpha.
- // DynamicColors do not support alpha currently, and _may_ not need it for this use case,
- // depending on how MDC resolved alpha for the other cases.
- // Returning black in dark mode, white in light mode.
- public static final DynamicColor controlHighlight =
- new DynamicColor(
- s -> 0.0,
- s -> 0.0,
- s -> s.isDark ? 100.0 : 0.0,
- s -> s.isDark ? 0.20 : 0.12,
- null,
- scheme ->
- DynamicColor.toneMinContrastDefault(
- (s) -> s.isDark ? 100.0 : 0.0, null, scheme, null),
- scheme ->
- DynamicColor.toneMaxContrastDefault(
- (s) -> s.isDark ? 100.0 : 0.0, null, scheme, null),
- null);
+ public static DynamicColor secondaryPaletteKeyColor() {
+ return DynamicColor.fromPalette(
+ (s) -> s.secondaryPalette, (s) -> s.secondaryPalette.getKeyColor().getTone());
+ }
- // textColorPrimaryInverse documented, in both M3 & GM3, documented as N10/N90.
- public static final DynamicColor textPrimaryInverse =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0);
+ public static DynamicColor tertiaryPaletteKeyColor() {
+ return DynamicColor.fromPalette(
+ (s) -> s.tertiaryPalette, (s) -> s.tertiaryPalette.getKeyColor().getTone());
+ }
- // textColorSecondaryInverse and textColorTertiaryInverse both documented, in both M3 & GM3, as
- // NV30/NV80
- public static final DynamicColor textSecondaryAndTertiaryInverse =
- DynamicColor.fromPalette((s) -> s.neutralVariantPalette, (s) -> s.isDark ? 30.0 : 80.0);
+ public static DynamicColor neutralPaletteKeyColor() {
+ return DynamicColor.fromPalette(
+ (s) -> s.neutralPalette, (s) -> s.neutralPalette.getKeyColor().getTone());
+ }
- // textColorPrimaryInverseDisableOnly documented, in both M3 & GM3, as N10/N90
- public static final DynamicColor textPrimaryInverseDisableOnly =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0);
-
- // textColorSecondaryInverse and textColorTertiaryInverse in disabled state both documented,
- // in both M3 & GM3, as N10/N90
- public static final DynamicColor textSecondaryAndTertiaryInverseDisabled =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0);
-
- // textColorHintInverse documented, in both M3 & GM3, as N10/N90
- public static final DynamicColor textHintInverse =
- DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0);
+ public static DynamicColor neutralVariantPaletteKeyColor() {
+ return DynamicColor.fromPalette(
+ (s) -> s.neutralVariantPalette,
+ (s) -> s.neutralVariantPalette.getKeyColor().getTone());
+ }
private static ViewingConditions viewingConditionsForAlbers(DynamicScheme scheme) {
return ViewingConditions.defaultWithBackgroundLstar(scheme.isDark ? 30.0 : 80.0);
@@ -377,6 +90,10 @@
return scheme.variant == Variant.FIDELITY || scheme.variant == Variant.CONTENT;
}
+ private static boolean isMonochrome(DynamicScheme scheme) {
+ return scheme.variant == Variant.MONOCHROME;
+ }
+
static double findDesiredChromaByTone(
double hue, double chroma, double tone, boolean byDecreasingTone) {
double answer = tone;
@@ -416,34 +133,456 @@
}
}
- // Compatibility mappings for Android
- public static final DynamicColor surfaceContainerLow = surfaceSub1;
- public static final DynamicColor surfaceContainerLowest = surfaceSub2;
- public static final DynamicColor surfaceContainerHigh = surfaceAdd1;
- public static final DynamicColor surfaceContainerHighest = surfaceAdd2;
- public static final DynamicColor primaryFixedDim = primaryFixedDarker;
- public static final DynamicColor secondaryFixedDim = secondaryFixedDarker;
- public static final DynamicColor tertiaryFixedDim = tertiaryFixedDarker;
+ public static DynamicColor highestSurface(DynamicScheme s) {
+ return s.isDark ? surfaceBright() : surfaceDim();
+ }
- // Compatibility Keys Colors for Android
- public static final DynamicColor primaryPaletteKeyColor =
- DynamicColor.fromPalette(
- (s) -> s.primaryPalette, (s) -> s.primaryPalette.getKeyColor().getTone());
+ public static DynamicColor background() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 98.0);
+ }
- public static final DynamicColor secondaryPaletteKeyColor =
- DynamicColor.fromPalette(
- (s) -> s.secondaryPalette, (s) -> s.secondaryPalette.getKeyColor().getTone());
+ public static DynamicColor onBackground() {
+ return DynamicColor.fromPalette(
+ (s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 10.0, (s) -> background());
+ }
- public static final DynamicColor tertiaryPaletteKeyColor =
- DynamicColor.fromPalette(
- (s) -> s.tertiaryPalette, (s) -> s.tertiaryPalette.getKeyColor().getTone());
+ public static DynamicColor surface() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 98.0);
+ }
- public static final DynamicColor neutralPaletteKeyColor =
- DynamicColor.fromPalette(
- (s) -> s.neutralPalette, (s) -> s.neutralPalette.getKeyColor().getTone());
+ public static DynamicColor inverseSurface() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 20.0);
+ }
- public static final DynamicColor neutralVariantPaletteKeyColor =
- DynamicColor.fromPalette(
- (s) -> s.neutralVariantPalette,
- (s) -> s.neutralVariantPalette.getKeyColor().getTone());
+ public static DynamicColor surfaceBright() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 24.0 : 98.0);
+ }
+
+ public static DynamicColor surfaceDim() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 87.0);
+ }
+
+ public static DynamicColor surfaceContainerLowest() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 4.0 : 100.0);
+ }
+
+ public static DynamicColor surfaceContainerLow() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 96.0);
+ }
+
+ public static DynamicColor surfaceContainer() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 12.0 : 94.0);
+ }
+
+ public static DynamicColor surfaceContainerHigh() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 17.0 : 92.0);
+ }
+
+ public static DynamicColor surfaceContainerHighest() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 22.0 : 90.0);
+ }
+
+ public static DynamicColor onSurface() {
+ return DynamicColor.fromPalette(
+ (s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 10.0,
+ MaterialDynamicColors::highestSurface);
+ }
+
+ public static DynamicColor inverseOnSurface() {
+ return DynamicColor.fromPalette(
+ (s) -> s.neutralPalette, (s) -> s.isDark ? 20.0 : 95.0, (s) -> inverseSurface());
+ }
+
+ public static DynamicColor surfaceVariant() {
+ return DynamicColor.fromPalette((s) -> s.neutralVariantPalette,
+ (s) -> s.isDark ? 30.0 : 90.0);
+ }
+
+ public static DynamicColor onSurfaceVariant() {
+ return DynamicColor.fromPalette(
+ (s) -> s.neutralVariantPalette, (s) -> s.isDark ? 80.0 : 30.0,
+ (s) -> surfaceVariant());
+ }
+
+ public static DynamicColor outline() {
+ return DynamicColor.fromPalette(
+ (s) -> s.neutralVariantPalette, (s) -> 50.0, MaterialDynamicColors::highestSurface);
+ }
+
+ public static DynamicColor outlineVariant() {
+ return DynamicColor.fromPalette(
+ (s) -> s.neutralVariantPalette, (s) -> s.isDark ? 30.0 : 80.0,
+ MaterialDynamicColors::highestSurface);
+ }
+
+ public static DynamicColor primaryContainer() {
+ return DynamicColor.fromPalette(
+ (s) -> s.primaryPalette,
+ (s) -> {
+ if (isFidelity(s)) {
+ return performAlbers(s.sourceColorHct, s);
+ }
+ if (isMonochrome(s)) {
+ return s.isDark ? 85.0 : 25.0;
+ }
+ return s.isDark ? 30.0 : 90.0;
+ },
+ MaterialDynamicColors::highestSurface);
+ }
+
+ public static DynamicColor onPrimaryContainer() {
+ return DynamicColor.fromPalette(
+ (s) -> s.primaryPalette,
+ (s) -> {
+ if (isFidelity(s)) {
+ return DynamicColor.contrastingTone(primaryContainer().tone.apply(s), 4.5);
+ }
+ if (isMonochrome(s)) {
+ return s.isDark ? 0.0 : 100.0;
+ }
+ return s.isDark ? 90.0 : 10.0;
+ },
+ (s) -> primaryContainer(),
+ null);
+ }
+
+ public static DynamicColor primary() {
+ return DynamicColor.fromPalette(
+ (s) -> s.primaryPalette,
+ (s) -> {
+ if (isMonochrome(s)) {
+ return s.isDark ? 100.0 : 0.0;
+ }
+ return s.isDark ? 80.0 : 40.0;
+ },
+ MaterialDynamicColors::highestSurface,
+ (s) ->
+ new ToneDeltaConstraint(
+ CONTAINER_ACCENT_TONE_DELTA,
+ primaryContainer(),
+ s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER));
+ }
+
+ public static DynamicColor inversePrimary() {
+ return DynamicColor.fromPalette(
+ (s) -> s.primaryPalette, (s) -> s.isDark ? 40.0 : 80.0, (s) -> inverseSurface());
+ }
+
+ public static DynamicColor onPrimary() {
+ return DynamicColor.fromPalette(
+ (s) -> s.primaryPalette,
+ (s) -> {
+ if (isMonochrome(s)) {
+ return s.isDark ? 10.0 : 90.0;
+ }
+ return s.isDark ? 20.0 : 100.0;
+ },
+ (s) -> primary());
+ }
+
+ public static DynamicColor secondaryContainer() {
+ return DynamicColor.fromPalette(
+ (s) -> s.secondaryPalette,
+ (s) -> {
+ if (isMonochrome(s)) {
+ return s.isDark ? 30.0 : 85.0;
+ }
+ final double initialTone = s.isDark ? 30.0 : 90.0;
+ if (!isFidelity(s)) {
+ return initialTone;
+ }
+ double answer =
+ findDesiredChromaByTone(
+ s.secondaryPalette.getHue(),
+ s.secondaryPalette.getChroma(),
+ initialTone,
+ !s.isDark);
+ answer = performAlbers(s.secondaryPalette.getHct(answer), s);
+ return answer;
+ },
+ MaterialDynamicColors::highestSurface);
+ }
+
+ public static DynamicColor onSecondaryContainer() {
+ return DynamicColor.fromPalette(
+ (s) -> s.secondaryPalette,
+ (s) -> {
+ if (!isFidelity(s)) {
+ return s.isDark ? 90.0 : 10.0;
+ }
+ return DynamicColor.contrastingTone(secondaryContainer().tone.apply(s), 4.5);
+ },
+ (s) -> secondaryContainer());
+ }
+
+ public static DynamicColor secondary() {
+ return DynamicColor.fromPalette(
+ (s) -> s.secondaryPalette,
+ (s) -> s.isDark ? 80.0 : 40.0,
+ MaterialDynamicColors::highestSurface,
+ (s) ->
+ new ToneDeltaConstraint(
+ CONTAINER_ACCENT_TONE_DELTA,
+ secondaryContainer(),
+ s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER));
+ }
+
+ public static DynamicColor onSecondary() {
+ return DynamicColor.fromPalette(
+ (s) -> s.secondaryPalette,
+ (s) -> {
+ if (isMonochrome(s)) {
+ return s.isDark ? 10.0 : 100.0;
+ }
+ return s.isDark ? 20.0 : 100.0;
+ },
+ (s) -> secondary());
+ }
+
+ public static DynamicColor tertiaryContainer() {
+ return DynamicColor.fromPalette(
+ (s) -> s.tertiaryPalette,
+ (s) -> {
+ if (isMonochrome(s)) {
+ return s.isDark ? 60.0 : 49.0;
+ }
+ if (!isFidelity(s)) {
+ return s.isDark ? 30.0 : 90.0;
+ }
+ final double albersTone =
+ performAlbers(s.tertiaryPalette.getHct(s.sourceColorHct.getTone()), s);
+ final Hct proposedHct = s.tertiaryPalette.getHct(albersTone);
+ return DislikeAnalyzer.fixIfDisliked(proposedHct).getTone();
+ },
+ MaterialDynamicColors::highestSurface);
+ }
+
+ public static DynamicColor onTertiaryContainer() {
+ return DynamicColor.fromPalette(
+ (s) -> s.tertiaryPalette,
+ (s) -> {
+ if (isMonochrome(s)) {
+ return s.isDark ? 0.0 : 100.0;
+ }
+ if (!isFidelity(s)) {
+ return s.isDark ? 90.0 : 10.0;
+ }
+ return DynamicColor.contrastingTone(tertiaryContainer().tone.apply(s), 4.5);
+ },
+ (s) -> tertiaryContainer());
+ }
+
+ public static DynamicColor tertiary() {
+ return DynamicColor.fromPalette(
+ (s) -> s.tertiaryPalette,
+ (s) -> {
+ if (isMonochrome(s)) {
+ return s.isDark ? 90.0 : 25.0;
+ }
+ return s.isDark ? 80.0 : 40.0;
+ },
+ MaterialDynamicColors::highestSurface,
+ (s) ->
+ new ToneDeltaConstraint(
+ CONTAINER_ACCENT_TONE_DELTA,
+ tertiaryContainer(),
+ s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER));
+ }
+
+ public static DynamicColor onTertiary() {
+ return DynamicColor.fromPalette(
+ (s) -> s.tertiaryPalette,
+ (s) -> {
+ if (isMonochrome(s)) {
+ return s.isDark ? 10.0 : 90.0;
+ }
+ return s.isDark ? 20.0 : 100.0;
+ },
+ (s) -> tertiary());
+ }
+
+ public static DynamicColor errorContainer() {
+ return DynamicColor.fromPalette(
+ (s) -> s.errorPalette, (s) -> s.isDark ? 30.0 : 90.0,
+ MaterialDynamicColors::highestSurface);
+ }
+
+ public static DynamicColor onErrorContainer() {
+ return DynamicColor.fromPalette(
+ (s) -> s.errorPalette, (s) -> s.isDark ? 90.0 : 10.0, (s) -> errorContainer());
+ }
+
+ public static DynamicColor error() {
+ return DynamicColor.fromPalette(
+ (s) -> s.errorPalette,
+ (s) -> s.isDark ? 80.0 : 40.0,
+ MaterialDynamicColors::highestSurface,
+ (s) ->
+ new ToneDeltaConstraint(
+ CONTAINER_ACCENT_TONE_DELTA,
+ errorContainer(),
+ s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER));
+ }
+
+ public static DynamicColor onError() {
+ return DynamicColor.fromPalette(
+ (s) -> s.errorPalette, (s) -> s.isDark ? 20.0 : 100.0, (s) -> error());
+ }
+
+ public static DynamicColor primaryFixed() {
+ return DynamicColor.fromPalette(
+ (s) -> s.primaryPalette,
+ (s) -> {
+ if (isMonochrome(s)) {
+ return s.isDark ? 100.0 : 10.0;
+ }
+ return 90.0;
+ },
+ MaterialDynamicColors::highestSurface);
+ }
+
+ public static DynamicColor primaryFixedDim() {
+ return DynamicColor.fromPalette(
+ (s) -> s.primaryPalette,
+ (s) -> {
+ if (isMonochrome(s)) {
+ return s.isDark ? 90.0 : 20.0;
+ }
+ return 80.0;
+ },
+ MaterialDynamicColors::highestSurface);
+ }
+
+ public static DynamicColor onPrimaryFixed() {
+ return DynamicColor.fromPalette(
+ (s) -> s.primaryPalette,
+ (s) -> {
+ if (isMonochrome(s)) {
+ return s.isDark ? 10.0 : 90.0;
+ }
+ return 10.0;
+ },
+ (s) -> primaryFixedDim());
+ }
+
+ public static DynamicColor onPrimaryFixedVariant() {
+ return DynamicColor.fromPalette(
+ (s) -> s.primaryPalette,
+ (s) -> {
+ if (isMonochrome(s)) {
+ return s.isDark ? 30.0 : 70.0;
+ }
+ return 30.0;
+ },
+ (s) -> primaryFixedDim());
+ }
+
+ public static DynamicColor secondaryFixed() {
+ return DynamicColor.fromPalette(
+ (s) -> s.secondaryPalette, (s) -> isMonochrome(s) ? 80.0 : 90.0,
+ MaterialDynamicColors::highestSurface);
+ }
+
+ public static DynamicColor secondaryFixedDim() {
+ return DynamicColor.fromPalette(
+ (s) -> s.secondaryPalette, (s) -> isMonochrome(s) ? 70.0 : 80.0,
+ MaterialDynamicColors::highestSurface);
+ }
+
+ public static DynamicColor onSecondaryFixed() {
+ return DynamicColor.fromPalette(
+ (s) -> s.secondaryPalette, (s) -> 10.0, (s) -> secondaryFixedDim());
+ }
+
+ public static DynamicColor onSecondaryFixedVariant() {
+ return DynamicColor.fromPalette(
+ (s) -> s.secondaryPalette,
+ (s) -> isMonochrome(s) ? 25.0 : 30.0,
+ (s) -> secondaryFixedDim());
+ }
+
+ public static DynamicColor tertiaryFixed() {
+ return DynamicColor.fromPalette(
+ (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 40.0 : 90.0,
+ MaterialDynamicColors::highestSurface);
+ }
+
+ public static DynamicColor tertiaryFixedDim() {
+ return DynamicColor.fromPalette(
+ (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 30.0 : 80.0,
+ MaterialDynamicColors::highestSurface);
+ }
+
+ public static DynamicColor onTertiaryFixed() {
+ return DynamicColor.fromPalette(
+ (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 90.0 : 10.0,
+ (s) -> tertiaryFixedDim());
+ }
+
+ public static DynamicColor onTertiaryFixedVariant() {
+ return DynamicColor.fromPalette(
+ (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 70.0 : 30.0,
+ (s) -> tertiaryFixedDim());
+ }
+
+ // colorControlNormal documented as textColorSecondary in M3 & GM3.
+ // In Material, textColorSecondary points to onSurfaceVariant in the non-disabled state,
+ // which is Neutral Variant T30/80 in light/dark.
+ public static DynamicColor controlNormal() {
+ return DynamicColor.fromPalette((s) -> s.neutralVariantPalette,
+ (s) -> s.isDark ? 80.0 : 30.0);
+ }
+
+ // colorControlHighlight documented, in both M3 & GM3:
+ // Light mode: #1f000000 dark mode: #33ffffff.
+ // These are black and white with some alpha.
+ // 1F hex = 31 decimal; 31 / 255 = 12% alpha.
+ // 33 hex = 51 decimal; 51 / 255 = 20% alpha.
+ // DynamicColors do not support alpha currently, and _may_ not need it for this use case,
+ // depending on how MDC resolved alpha for the other cases.
+ // Returning black in dark mode, white in light mode.
+ public static DynamicColor controlHighlight() {
+ return new DynamicColor(
+ s -> 0.0,
+ s -> 0.0,
+ s -> s.isDark ? 100.0 : 0.0,
+ s -> s.isDark ? 0.20 : 0.12,
+ null,
+ scheme ->
+
+ DynamicColor.toneMinContrastDefault((s) -> s.isDark ? 100.0 : 0.0, null,
+ scheme, null),
+ scheme ->
+ DynamicColor.toneMaxContrastDefault((s) -> s.isDark ? 100.0 : 0.0, null,
+ scheme, null),
+ null);
+ }
+
+ // textColorPrimaryInverse documented, in both M3 & GM3, documented as N10/N90.
+ public static DynamicColor textPrimaryInverse() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0);
+ }
+
+ // textColorSecondaryInverse and textColorTertiaryInverse both documented, in both M3 & GM3, as
+ // NV30/NV80
+ public static DynamicColor textSecondaryAndTertiaryInverse() {
+ return DynamicColor.fromPalette((s) -> s.neutralVariantPalette,
+ (s) -> s.isDark ? 30.0 : 80.0);
+ }
+
+ // textColorPrimaryInverseDisableOnly documented, in both M3 & GM3, as N10/N90
+ public static DynamicColor textPrimaryInverseDisableOnly() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0);
+ }
+
+ // textColorSecondaryInverse and textColorTertiaryInverse in disabled state both documented,
+ // in both M3 & GM3, as N10/N90
+ public static DynamicColor textSecondaryAndTertiaryInverseDisabled() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0);
+ }
+
+ // textColorHintInverse documented, in both M3 & GM3, as N10/N90
+ public static DynamicColor textHintInverse() {
+ return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0);
+ }
}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeTonalSpot.java b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeTonalSpot.java
index 8480684..cc6b492 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeTonalSpot.java
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/scheme/SchemeTonalSpot.java
@@ -32,7 +32,7 @@
TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 16.0),
TonalPalette.fromHueAndChroma(
MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() + 60.0), 24.0),
- TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 4.0),
+ TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 6.0),
TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 8.0));
}
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
index 8ef2d80..ca3e710 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -141,8 +141,16 @@
/** Runs the battery animation (if any). */
fun charge() {}
- /** Move the clock, for example, if the notification tray appears in split-shade mode. */
- fun onPositionUpdated(fromRect: Rect, toRect: Rect, fraction: Float) {}
+ /**
+ * Runs when the clock's position changed during the move animation.
+ *
+ * @param fromLeft the [View.getLeft] position of the clock, before it started moving.
+ * @param direction the direction in which it is moving. A positive number means right, and
+ * negative means left.
+ * @param fraction fraction of the clock movement. 0 means it is at the beginning, and 1 means
+ * it finished moving.
+ */
+ fun onPositionUpdated(fromLeft: Int, direction: Int, fraction: Float) {}
/**
* Runs when swiping clock picker, swipingFraction: 1.0 -> clock is scaled up in the preview,
diff --git a/packages/SystemUI/res-keyguard/color/numpad_key_color_secondary.xml b/packages/SystemUI/res-keyguard/color/numpad_key_color_secondary.xml
index 08c66a2..47641ee 100644
--- a/packages/SystemUI/res-keyguard/color/numpad_key_color_secondary.xml
+++ b/packages/SystemUI/res-keyguard/color/numpad_key_color_secondary.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
- <item android:color="?androidprv:attr/colorAccentSecondaryVariant"/>
+ <item android:color="?androidprv:attr/materialColorSecondaryFixedDim"/>
</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/drawable/kg_emergency_button_background.xml b/packages/SystemUI/res-keyguard/drawable/kg_emergency_button_background.xml
index 0764273..5e7cf3e 100644
--- a/packages/SystemUI/res-keyguard/drawable/kg_emergency_button_background.xml
+++ b/packages/SystemUI/res-keyguard/drawable/kg_emergency_button_background.xml
@@ -19,7 +19,7 @@
android:color="?attr/wallpaperTextColorSecondary">
<item android:id="@android:id/background">
<shape android:shape="rectangle">
- <solid android:color="?androidprv:attr/colorAccentTertiary"/>
+ <solid android:color="?androidprv:attr/materialColorTertiaryFixed"/>
<corners android:radius="24dp"/>
</shape>
</item>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml
index 67fd5b9..83736e9 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml
@@ -19,6 +19,7 @@
<!-- This contains disable eSim buttons shared by sim_pin/sim_puk screens -->
<com.android.keyguard.KeyguardEsimArea xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/keyguard_disable_esim"
style="@style/Keyguard.TextView"
android:layout_width="wrap_content"
@@ -26,8 +27,8 @@
android:background="@drawable/kg_bouncer_secondary_button"
android:drawablePadding="10dp"
android:drawableStart="@drawable/ic_no_sim"
- android:drawableTint="?android:attr/textColorPrimary"
+ android:drawableTint="?androidprv:attr/materialColorOnSurface"
android:text="@string/disable_carrier_button_text"
- android:textColor="?android:attr/textColorPrimary"
+ android:textColor="?androidprv:attr/materialColorOnSurface"
android:textSize="@dimen/kg_status_line_font_size"
android:visibility="gone" />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml
index 426cfaf..751b07a 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_security_container_view.xml
@@ -19,13 +19,14 @@
<com.android.keyguard.KeyguardSecurityContainer
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/keyguard_security_container"
+ android:background="?androidprv:attr/materialColorSurfaceContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
- android:paddingTop="@dimen/keyguard_lock_padding"
+ android:paddingTop="@dimen/status_bar_height"
android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent
from this view when bouncer is shown -->
<com.android.keyguard.KeyguardSecurityViewFlipper
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 04dffb6..4d289eb 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -22,9 +22,10 @@
<!-- Keyguard PIN pad styles -->
<style name="Keyguard.TextView" parent="@android:style/Widget.DeviceDefault.TextView">
<item name="android:textSize">@dimen/kg_status_line_font_size</item>
+ <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
</style>
<style name="Keyguard.TextView.EmergencyButton" parent="Theme.SystemUI">
- <item name="android:textColor">?androidprv:attr/textColorOnAccent</item>
+ <item name="android:textColor">?androidprv:attr/materialColorOnTertiaryFixed</item>
<item name="android:textSize">16sp</item>
<item name="android:background">@drawable/kg_emergency_button_background</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
diff --git a/packages/SystemUI/res/drawable/dream_overlay_assistant_attention_indicator.xml b/packages/SystemUI/res/drawable/dream_overlay_assistant_attention_indicator.xml
index dad2cdf8e..54bdf18 100644
--- a/packages/SystemUI/res/drawable/dream_overlay_assistant_attention_indicator.xml
+++ b/packages/SystemUI/res/drawable/dream_overlay_assistant_attention_indicator.xml
@@ -13,20 +13,30 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="56dp"
android:height="24dp"
android:viewportWidth="56"
android:viewportHeight="24">
- <group>
- <clip-path
- android:pathData="M12 0H44C50.6274 0 56 5.37258 56 12C56 18.6274 50.6274 24 44 24H12C5.37258 24 0 18.6274 0 12C0 5.37258 5.37258 0 12 0Z"
- />
+ <path
+ android:pathData="M12,0L44,0A12,12 0,0 1,56 12L56,12A12,12 0,0 1,44 24L12,24A12,12 0,0 1,0 12L0,12A12,12 0,0 1,12 0z"
+ android:fillColor="#ffffff"/>
+ <group
+ android:scaleX="0.8"
+ android:scaleY="0.8"
+ android:translateY="2"
+ android:translateX="18">
<path
- android:pathData="M0 0V24H56V0"
- android:fillColor="#FFFFFF"
- />
+ android:pathData="M21.5,9C22.3284,9 23,8.3284 23,7.5C23,6.6716 22.3284,6 21.5,6C20.6716,6 20,6.6716 20,7.5C20,8.3284 20.6716,9 21.5,9Z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M17,14C18.6569,14 20,12.6569 20,11C20,9.3432 18.6569,8 17,8C15.3431,8 14,9.3432 14,11C14,12.6569 15.3431,14 17,14Z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M17,22C18.933,22 20.5,20.433 20.5,18.5C20.5,16.567 18.933,15 17,15C15.067,15 13.5,16.567 13.5,18.5C13.5,20.433 15.067,22 17,22Z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M7,14C10.3137,14 13,11.3137 13,8C13,4.6863 10.3137,2 7,2C3.6863,2 1,4.6863 1,8C1,11.3137 3.6863,14 7,14Z"
+ android:fillColor="#000000"/>
</group>
-</vector>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/auth_credential_password_view.xml b/packages/SystemUI/res/layout/auth_credential_password_view.xml
index 021ebe6..33f1b10 100644
--- a/packages/SystemUI/res/layout/auth_credential_password_view.xml
+++ b/packages/SystemUI/res/layout/auth_credential_password_view.xml
@@ -23,40 +23,47 @@
android:orientation="vertical"
android:theme="?app:attr/lockPinPasswordStyle">
- <RelativeLayout
+ <ScrollView
android:id="@+id/auth_credential_header"
- style="?headerStyle"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="wrap_content">
- <ImageView
- android:id="@+id/icon"
- style="?headerIconStyle"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:contentDescription="@null"/>
-
- <TextView
- android:id="@+id/title"
- style="?titleTextAppearance"
- android:layout_below="@id/icon"
+ <RelativeLayout
+ style="?headerStyle"
android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content">
- <TextView
- android:id="@+id/subtitle"
- style="?subTitleTextAppearance"
- android:layout_below="@id/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
+ <ImageView
+ android:id="@+id/icon"
+ style="?headerIconStyle"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:contentDescription="@null" />
- <TextView
- android:id="@+id/description"
- style="?descriptionTextAppearance"
- android:layout_below="@id/subtitle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
- </RelativeLayout>
+ <TextView
+ android:id="@+id/title"
+ style="?titleTextAppearance"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/icon" />
+
+ <TextView
+ android:id="@+id/subtitle"
+ style="?subTitleTextAppearance"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/title" />
+
+ <TextView
+ android:id="@+id/description"
+ style="?descriptionTextAppearance"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/subtitle" />
+
+ </RelativeLayout>
+
+ </ScrollView>
<LinearLayout
android:id="@+id/auth_credential_input"
diff --git a/packages/SystemUI/res/layout/screen_record_dialog.xml b/packages/SystemUI/res/layout/screen_record_dialog.xml
index ab38dd2..ae052502 100644
--- a/packages/SystemUI/res/layout/screen_record_dialog.xml
+++ b/packages/SystemUI/res/layout/screen_record_dialog.xml
@@ -49,13 +49,13 @@
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:fontFamily="@*android:string/config_headlineFontFamily"
- android:text="@string/screenrecord_start_label"
+ android:text="@string/screenrecord_permission_dialog_title"
android:layout_marginTop="22dp"
android:layout_marginBottom="15dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/screenrecord_description"
+ android:text="@string/screenrecord_permission_dialog_warning_entire_screen"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:textColorSecondary"
android:gravity="center"
@@ -168,7 +168,7 @@
android:layout_height="wrap_content"
android:layout_weight="0"
android:layout_gravity="end"
- android:text="@string/screenrecord_start"
+ android:text="@string/screenrecord_continue"
style="@style/Widget.Dialog.Button" />
</LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/screen_share_dialog.xml b/packages/SystemUI/res/layout/screen_share_dialog.xml
index bd71989..0d86e0a 100644
--- a/packages/SystemUI/res/layout/screen_share_dialog.xml
+++ b/packages/SystemUI/res/layout/screen_share_dialog.xml
@@ -63,7 +63,7 @@
android:id="@+id/text_warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/screenrecord_description"
+ android:text="@string/screenrecord_permission_dialog_warning_entire_screen"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:textColorSecondary"
android:gravity="start"
@@ -76,7 +76,7 @@
android:orientation="horizontal"
android:layout_marginTop="@dimen/screenrecord_buttons_margin_top">
<TextView
- android:id="@+id/button_cancel"
+ android:id="@android:id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
@@ -87,11 +87,11 @@
android:layout_height="match_parent"
android:layout_weight="1"/>
<TextView
- android:id="@+id/button_start"
+ android:id="@android:id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
- android:text="@string/screenrecord_start"
+ android:text="@string/screenrecord_continue"
style="@style/Widget.Dialog.Button" />
</LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index fe9542b..d9fe949 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -101,7 +101,6 @@
</LinearLayout>
<FrameLayout android:id="@+id/keyguard_bouncer_container"
- android:paddingTop="@dimen/status_bar_height"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index a2eba81..0aa880f 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -808,6 +808,8 @@
<dimen name="keyguard_lock_height">42dp</dimen>
<dimen name="keyguard_lock_padding">20dp</dimen>
+ <dimen name="keyguard_security_container_padding_top">20dp</dimen>
+
<dimen name="keyguard_indication_margin_bottom">32dp</dimen>
<dimen name="lock_icon_margin_bottom">74dp</dimen>
<dimen name="ambient_indication_margin_bottom">71dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4e68efe..6b461ee 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -251,25 +251,22 @@
<string name="app_clips_save_add_to_note">Add to note</string>
<!-- Notification title displayed for screen recording [CHAR LIMIT=50]-->
- <string name="screenrecord_name">Screen Recorder</string>
+ <string name="screenrecord_title">Screen Recorder</string>
<!-- Processing screen recoding video in the background [CHAR LIMIT=30]-->
<string name="screenrecord_background_processing_label">Processing screen recording</string>
<!-- Description of the screen recording notification channel [CHAR LIMIT=NONE]-->
<string name="screenrecord_channel_description">Ongoing notification for a screen record session</string>
+
+ <!-- For updated Screen Recording permission dialog (i.e. with PSS)-->
<!-- Title for the screen prompting the user to begin recording their screen [CHAR LIMIT=NONE]-->
- <string name="screenrecord_start_label">Start Recording?</string>
- <!-- Message reminding the user that sensitive information may be captured during a screen recording [CHAR_LIMIT=NONE]-->
- <string name="screenrecord_description">While recording, Android System can capture any sensitive information that\u2019s visible on your screen or played on your device. This includes passwords, payment info, photos, messages, and audio.</string>
- <!-- Dropdown option to record the entire screen [CHAR_LIMIT=30]-->
- <string name="screenrecord_option_entire_screen">Record entire screen</string>
- <!-- Dropdown option to record a single app [CHAR_LIMIT=30]-->
- <string name="screenrecord_option_single_app">Record a single app</string>
+ <string name="screenrecord_permission_dialog_title">Start Recording?</string>
<!-- Message reminding the user that sensitive information may be captured during a full screen recording for the updated dialog that includes partial screen sharing option [CHAR_LIMIT=350]-->
- <string name="screenrecord_warning_entire_screen">While you\'re recording, Android has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages, or other sensitive information.</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen">While you’re recording, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
<!-- Message reminding the user that sensitive information may be captured during a single app screen recording for the updated dialog that includes partial screen sharing option [CHAR_LIMIT=350]-->
- <string name="screenrecord_warning_single_app">While you\'re recording an app, Android has access to anything shown or played on that app. So be careful with passwords, payment details, messages, or other sensitive information.</string>
+ <string name="screenrecord_permission_dialog_warning_single_app">While you’re recording an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
<!-- Button to start a screen recording in the updated screen record dialog that allows to select an app to record [CHAR LIMIT=50]-->
- <string name="screenrecord_start_recording">Start recording</string>
+ <string name="screenrecord_permission_dialog_continue">Start recording</string>
+
<!-- Label for a switch to enable recording audio [CHAR LIMIT=NONE]-->
<string name="screenrecord_audio_label">Record audio</string>
<!-- Label for the option to record audio from the device [CHAR LIMIT=NONE]-->
@@ -281,7 +278,7 @@
<!-- Label for an option to record audio from both device and microphone [CHAR LIMIT=NONE]-->
<string name="screenrecord_device_audio_and_mic_label">Device audio and microphone</string>
<!-- Button to start a screen recording [CHAR LIMIT=50]-->
- <string name="screenrecord_start">Start</string>
+ <string name="screenrecord_continue">Start</string>
<!-- Notification text displayed when we are recording the screen [CHAR LIMIT=100]-->
<string name="screenrecord_ongoing_screen_only">Recording screen</string>
<!-- Notification text displayed when we are recording both the screen and audio [CHAR LIMIT=100]-->
@@ -1064,47 +1061,52 @@
<!-- Label for button in confirmation dialog when exiting guest session [CHAR LIMIT=35] -->
<string name="user_remove_user_remove">Remove</string>
- <!-- Media projection permission dialog warning text. [CHAR LIMIT=NONE] -->
- <string name="media_projection_dialog_text"><xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.</string>
-
- <!-- Media projection permission dialog warning text for system services. [CHAR LIMIT=NONE] -->
- <string name="media_projection_dialog_service_text">The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.</string>
-
- <!-- Media projection permission dialog warning title for system services. [CHAR LIMIT=NONE] -->
- <string name="media_projection_dialog_service_title">Start recording or casting?</string>
-
+ <!-- Media projection without Partial Screenshare -->
<!-- Media projection permission dialog warning title. [CHAR LIMIT=NONE] -->
<string name="media_projection_dialog_title">Start recording or casting with <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g>?</string>
+ <!-- Media projection permission dialog warning text. [CHAR LIMIT=NONE] -->
+ <string name="media_projection_dialog_warning"><xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.</string>
+ <!-- Media projection permission dialog warning title for system services. [CHAR LIMIT=NONE] -->
+ <string name="media_projection_sys_service_dialog_title">Start recording or casting?</string>
+ <!-- Media projection permission dialog warning text for system services. [CHAR LIMIT=NONE] -->
+ <string name="media_projection_sys_service_dialog_warning">The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.</string>
- <!-- Media projection permission dialog title. [CHAR LIMIT=NONE] -->
- <string name="media_projection_permission_dialog_title">Allow <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g> to share or record?</string>
-
- <!-- Media projection permission dropdown option for capturing the whole screen. [CHAR LIMIT=30] -->
- <string name="media_projection_permission_dialog_option_entire_screen">Entire screen</string>
-
- <!-- Media projection permission dropdown option for capturing single app. [CHAR LIMIT=30] -->
- <string name="media_projection_permission_dialog_option_single_app">A single app</string>
-
- <!-- Media projection permission warning for capturing the whole screen. [CHAR LIMIT=350] -->
- <string name="media_projection_permission_dialog_warning_entire_screen">When you\'re sharing, recording, or casting, <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages, or other sensitive information.</string>
-
- <!-- Media projection permission warning for capturing an app. [CHAR LIMIT=350] -->
- <string name="media_projection_permission_dialog_warning_single_app">When you\'re sharing, recording, or casting an app, <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g> has access to anything shown or played on that app. So be careful with passwords, payment details, messages, or other sensitive information.</string>
-
- <!-- Media projection permission button to continue with app selection or recording [CHAR LIMIT=60] -->
- <string name="media_projection_permission_dialog_continue">Continue</string>
-
+ <!-- Permission dropdown option for sharing or recording the whole screen. [CHAR LIMIT=30] -->
+ <string name="screen_share_permission_dialog_option_entire_screen">Entire screen</string>
+ <!-- Permission dropdown option for sharing or recording single app. [CHAR LIMIT=30] -->
+ <string name="screen_share_permission_dialog_option_single_app">A single app</string>
<!-- Title of the dialog that allows to select an app to share or record [CHAR LIMIT=NONE] -->
- <string name="media_projection_permission_app_selector_title">Share or record an app</string>
+ <string name="screen_share_permission_app_selector_title">Share or record an app</string>
- <!-- Media projection permission dialog title when there is no app name (e.g. it could be a system service when casting). [CHAR LIMIT=100] -->
- <string name="media_projection_permission_dialog_system_service_title">Allow this app to share or record?</string>
+ <!-- Media projection that launched from 1P/3P apps -->
+ <!-- 1P/3P app media projection permission dialog title. [CHAR LIMIT=NONE] -->
+ <string name="media_projection_entry_app_permission_dialog_title">Start recording or casting with <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g>?</string>
+ <!-- 1P/3P app media projection permission warning for capturing the whole screen. [CHAR LIMIT=350] -->
+ <string name="media_projection_entry_app_permission_dialog_warning_entire_screen">When you’re sharing, recording, or casting, <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <!-- 1P/3P app media projection permission warning for capturing an app. [CHAR LIMIT=350] -->
+ <string name="media_projection_entry_app_permission_dialog_warning_single_app">When you’re sharing, recording, or casting an app, <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g> has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <!-- 1P/3P apps media projection permission button to continue with app selection or recording [CHAR LIMIT=60] -->
+ <string name="media_projection_entry_app_permission_dialog_continue">Start</string>
- <!-- Media projection permission warning for capturing the whole screen when a system service requests it (e.g. when casting). [CHAR LIMIT=350] -->
- <string name="media_projection_permission_dialog_system_service_warning_entire_screen">When you\'re sharing, recording, or casting, this app has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages, or other sensitive information.</string>
+ <!-- Casting that launched by SysUI (i.e. when there is no app name) -->
+ <!-- System casting media projection permission dialog title. [CHAR LIMIT=100] -->
+ <string name="media_projection_entry_cast_permission_dialog_title">Start casting?</string>
+ <!-- System casting media projection permission warning for capturing the whole screen when SysUI casting requests it. [CHAR LIMIT=350] -->
+ <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen">When you’re casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <!-- System casting media projection permission warning for capturing a single app when SysUI casting requests it. [CHAR LIMIT=350] -->
+ <string name="media_projection_entry_cast_permission_dialog_warning_single_app">When you’re casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <!-- System casting media projection permission button to continue for SysUI casting. [CHAR LIMIT=60] -->
+ <string name="media_projection_entry_cast_permission_dialog_continue">Start casting</string>
- <!-- Media projection permission warning for capturing a single app when a system service requests it (e.g. when casting). [CHAR LIMIT=350] -->
- <string name="media_projection_permission_dialog_system_service_warning_single_app">When you\'re sharing, recording, or casting an app, this app has access to anything shown or played on that app. So be careful with passwords, payment details, messages, or other sensitive information.</string>
+ <!-- Other sharing (not recording nor casting) that launched by SysUI (currently not in use) -->
+ <!-- System sharing media projection permission dialog title. [CHAR LIMIT=100] -->
+ <string name="media_projection_entry_generic_permission_dialog_title">Start sharing?</string>
+ <!-- System sharing media projection permission warning for capturing the whole screen. [CHAR LIMIT=350] -->
+ <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen">When you’re sharing, recording, or casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <!-- System sharing media projection permission warning for capturing a single app. [CHAR LIMIT=350] -->
+ <string name="media_projection_entry_generic_permission_dialog_warning_single_app">When you’re sharing, recording, or casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <!-- System sharing media projection permission button to continue. [CHAR LIMIT=60] -->
+ <string name="media_projection_entry_generic_permission_dialog_continue">Start</string>
<!-- Title for the dialog that is shown when screen capturing is disabled by enterprise policy. [CHAR LIMIT=100] -->
<string name="screen_capturing_disabled_by_policy_dialog_title">Blocked by your IT admin</string>
@@ -1255,7 +1257,10 @@
<string name="monitoring_description_managed_profile_network_logging">Your admin has turned on network logging, which monitors traffic in your work profile but not in your personal profile.</string>
<!-- Monitoring dialog: Description of an active VPN. [CHAR LIMIT=NONE]-->
- <string name="monitoring_description_named_vpn">This device is connected to the internet through <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g>. Your network activity, including emails and browsing data, is visible to your IT admin.</string>
+ <string name="monitoring_description_named_vpn">This device is connected to the internet through <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g>. Your network activity, including emails and browsing data, is visible to the VPN provider.</string>
+
+ <!-- Monitoring dialog: Description of an active VPN on a managed device. [CHAR LIMIT=NONE]-->
+ <string name="monitoring_description_managed_device_named_vpn">This device is connected to the internet through <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g>. Your network activity, including emails and browsing data, is visible to your IT admin.</string>
<!-- Monitoring dialog: Description of two active VPNs. [CHAR LIMIT=NONE]-->
<string name="monitoring_description_two_named_vpns">This device is connected to the internet through <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g> and <xliff:g id="vpn_app" example="Bar VPN App">%2$s</xliff:g>. Your network activity, including emails and browsing data, is visible to your IT admin.</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java
index 209d5e8..43df08d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Monitor.java
@@ -32,8 +32,10 @@
import javax.inject.Inject;
/**
- * {@link Monitor} takes in a set of conditions, monitors whether all of them have
- * been fulfilled, and informs any registered listeners.
+ * {@link Monitor} allows {@link Subscription}s to a set of conditions and monitors whether all of
+ * them have been fulfilled.
+ * <p>
+ * This class should be used as a singleton, to prevent duplicate monitoring of the same conditions.
*/
public class Monitor {
private final String mTag = getClass().getSimpleName();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java
index 3d05542..4f73fc4 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java
@@ -109,7 +109,7 @@
/** Load all plugins matching this instance's action. */
public void loadAll() {
if (DEBUG) Log.d(TAG, "startListening");
- mBgExecutor.execute(this::queryAll);
+ mBgExecutor.execute(() -> queryAll());
}
/** Unload all plugins managed by this instance. */
@@ -255,17 +255,18 @@
intent.setPackage(pkgName);
}
List<ResolveInfo> result = mPm.queryIntentServices(intent, 0);
- if (DEBUG) Log.d(TAG, "Found " + result.size() + " plugins");
+ if (DEBUG) {
+ Log.d(TAG, "Found " + result.size() + " plugins");
+ for (ResolveInfo info : result) {
+ ComponentName name = new ComponentName(info.serviceInfo.packageName,
+ info.serviceInfo.name);
+ Log.d(TAG, " " + name);
+ }
+ }
+
if (result.size() > 1 && !mAllowMultiple) {
// TODO: Show warning.
Log.w(TAG, "Multiple plugins found for " + mAction);
- if (DEBUG) {
- for (ResolveInfo info : result) {
- ComponentName name = new ComponentName(info.serviceInfo.packageName,
- info.serviceInfo.name);
- Log.w(TAG, " " + name);
- }
- }
return;
}
for (ResolveInfo info : result) {
@@ -307,7 +308,7 @@
// TODO: Only create the plugin before version check if we need it for
// legacy version check.
if (DEBUG) {
- Log.d(TAG, "createPlugin");
+ Log.d(TAG, "createPlugin: " + component);
}
try {
return mPluginInstanceFactory.create(
@@ -317,7 +318,7 @@
reportInvalidVersion(component, component.getClassName(), e);
}
} catch (Throwable e) {
- Log.w(TAG, "Couldn't load plugin: " + packageName, e);
+ Log.w(TAG, "Couldn't load plugin: " + component, e);
return null;
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java
index 1b0dacc..8dcd2aa 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java
@@ -206,7 +206,7 @@
t.close();
info.releaseAllSurfaces();
if (finishRunnable == null) return;
- onAnimationCancelled(false /* isKeyguardOccluded */);
+ onAnimationCancelled();
finishRunnable.run();
}
};
diff --git a/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt b/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt
index f59bf8e..62f4f22 100644
--- a/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt
+++ b/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt
@@ -28,6 +28,7 @@
import android.view.View
import com.android.settingslib.Utils
import com.android.systemui.animation.Interpolators
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.TITLE
/** Displays security messages for the keyguard bouncer. */
open class BouncerKeyguardMessageArea(context: Context?, attrs: AttributeSet?) :
@@ -56,8 +57,7 @@
}
override fun onThemeChanged() {
- val array: TypedArray =
- mContext.obtainStyledAttributes(intArrayOf(android.R.attr.textColorPrimary))
+ val array: TypedArray = mContext.obtainStyledAttributes(intArrayOf(TITLE))
val newTextColors: ColorStateList = ColorStateList.valueOf(array.getColor(0, Color.RED))
array.recycle()
mDefaultColorState = newTextColors
@@ -65,7 +65,7 @@
}
override fun reloadColor() {
- mDefaultColorState = Utils.getColorAttr(context, android.R.attr.textColorPrimary)
+ mDefaultColorState = Utils.getColorAttr(context, TITLE)
super.reloadColor()
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index ba5a8c9..b88d85c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -54,6 +54,7 @@
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.graphics.drawable.LayerDrawable;
import android.os.UserManager;
import android.provider.Settings;
@@ -333,6 +334,11 @@
mSpringAnimation = new SpringAnimation(this, DynamicAnimation.TRANSLATION_Y);
mViewConfiguration = ViewConfiguration.get(context);
mDoubleTapDetector = new GestureDetector(context, new DoubleTapListener());
+
+ // Add additional top padding.
+ setPadding(getPaddingLeft(), getPaddingTop() + getResources().getDimensionPixelSize(
+ R.dimen.keyguard_security_container_padding_top), getPaddingRight(),
+ getPaddingBottom());
}
void onResume(SecurityMode securityMode, boolean faceAuthEnabled) {
@@ -780,6 +786,8 @@
void reloadColors() {
mViewMode.reloadColors();
+ setBackgroundColor(Utils.getColorAttrDefaultColor(getContext(),
+ com.android.internal.R.attr.materialColorSurface));
}
/** Handles density or font scale changes. */
@@ -1022,11 +1030,15 @@
mUserSwitcherController.removeUserSwitchCallback(mUserSwitchCallback);
}
- private Drawable findUserIcon(int userId) {
+ private Drawable findLargeUserIcon(int userId) {
Bitmap userIcon = UserManager.get(mView.getContext()).getUserIcon(userId);
if (userIcon != null) {
- return CircleFramedDrawable.getInstance(mView.getContext(),
- userIcon);
+ int iconSize =
+ mResources.getDimensionPixelSize(R.dimen.bouncer_user_switcher_icon_size);
+ return CircleFramedDrawable.getInstance(
+ mView.getContext(),
+ Icon.scaleDownIfNecessary(userIcon, iconSize, iconSize)
+ );
}
return UserIcons.getDefaultUserIcon(mResources, userId, false);
@@ -1085,7 +1097,7 @@
return;
}
final String currentUserName = mUserSwitcherController.getCurrentUserName();
- Drawable userIcon = findUserIcon(currentUser.info.id);
+ Drawable userIcon = findLargeUserIcon(currentUser.info.id);
((ImageView) mView.findViewById(R.id.user_icon)).setImageDrawable(userIcon);
mUserSwitcher.setText(currentUserName);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt
index b4bfca1..3fc39af 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt
@@ -20,7 +20,9 @@
import android.util.AttributeSet
import android.widget.ImageView
import androidx.core.graphics.drawable.DrawableCompat
+import com.android.settingslib.Utils
import com.android.systemui.R
+import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.EMERGENCY_BUTTON
abstract class KeyguardSimInputView(context: Context, attrs: AttributeSet) :
KeyguardPinBasedInputView(context, attrs) {
@@ -42,10 +44,7 @@
override fun reloadColors() {
super.reloadColors()
- val customAttrs = intArrayOf(android.R.attr.textColorSecondary)
- val a = context.obtainStyledAttributes(customAttrs)
- val imageColor = a.getColor(0, 0)
- a.recycle()
+ val imageColor = Utils.getColorAttrDefaultColor(context, EMERGENCY_BUTTON)
simImageView?.let {
val wrappedDrawable = DrawableCompat.wrap(it.drawable)
DrawableCompat.setTint(wrappedDrawable, imageColor)
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index edfcb8d..0826f8a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -363,8 +363,6 @@
} else {
View clockView = clockContainerView.getChildAt(0);
- transition.excludeTarget(clockView, /* exclude= */ true);
-
TransitionSet set = new TransitionSet();
set.addTransition(transition);
@@ -389,8 +387,9 @@
@VisibleForTesting
static class SplitShadeTransitionAdapter extends Transition {
- private static final String PROP_BOUNDS = "splitShadeTransitionAdapter:bounds";
- private static final String[] TRANSITION_PROPERTIES = { PROP_BOUNDS };
+ private static final String PROP_BOUNDS_LEFT = "splitShadeTransitionAdapter:boundsLeft";
+ private static final String PROP_X_IN_WINDOW = "splitShadeTransitionAdapter:xInWindow";
+ private static final String[] TRANSITION_PROPERTIES = { PROP_BOUNDS_LEFT, PROP_X_IN_WINDOW};
private final KeyguardClockSwitchController mController;
@@ -400,12 +399,10 @@
}
private void captureValues(TransitionValues transitionValues) {
- Rect boundsRect = new Rect();
- boundsRect.left = transitionValues.view.getLeft();
- boundsRect.top = transitionValues.view.getTop();
- boundsRect.right = transitionValues.view.getRight();
- boundsRect.bottom = transitionValues.view.getBottom();
- transitionValues.values.put(PROP_BOUNDS, boundsRect);
+ transitionValues.values.put(PROP_BOUNDS_LEFT, transitionValues.view.getLeft());
+ int[] locationInWindowTmp = new int[2];
+ transitionValues.view.getLocationInWindow(locationInWindowTmp);
+ transitionValues.values.put(PROP_X_IN_WINDOW, locationInWindowTmp[0]);
}
@Override
@@ -427,8 +424,12 @@
}
ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
- Rect from = (Rect) startValues.values.get(PROP_BOUNDS);
- Rect to = (Rect) endValues.values.get(PROP_BOUNDS);
+ int fromLeft = (int) startValues.values.get(PROP_BOUNDS_LEFT);
+ int fromWindowX = (int) startValues.values.get(PROP_X_IN_WINDOW);
+ int toWindowX = (int) endValues.values.get(PROP_X_IN_WINDOW);
+ // Using windowX, to determine direction, instead of left, as in RTL the difference of
+ // toLeft - fromLeft is always positive, even when moving left.
+ int direction = toWindowX - fromWindowX > 0 ? 1 : -1;
anim.addUpdateListener(animation -> {
ClockController clock = mController.getClock();
@@ -437,7 +438,7 @@
}
clock.getLargeClock().getAnimations()
- .onPositionUpdated(from, to, animation.getAnimatedFraction());
+ .onPositionUpdated(fromLeft, direction, animation.getAnimatedFraction());
});
return anim;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 2c669bb..9573913 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -396,6 +396,7 @@
private int mFaceRunningState = BIOMETRIC_STATE_STOPPED;
private boolean mIsDreaming;
private boolean mLogoutEnabled;
+ private boolean mIsFaceEnrolled;
private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private int mPostureState = DEVICE_POSTURE_UNKNOWN;
private FingerprintInteractiveToAuthProvider mFingerprintInteractiveToAuthProvider;
@@ -2572,6 +2573,16 @@
}
}
+ private void updateFaceEnrolled(int userId) {
+ final Boolean isFaceEnrolled = isFaceSupported()
+ && mBiometricEnabledForUser.get(userId)
+ && mAuthController.isFaceAuthEnrolled(userId);
+ if (mIsFaceEnrolled != isFaceEnrolled) {
+ mLogger.logFaceEnrolledUpdated(mIsFaceEnrolled, isFaceEnrolled);
+ }
+ mIsFaceEnrolled = isFaceEnrolled;
+ }
+
private boolean isFaceSupported() {
return mFaceManager != null && !mFaceSensorProperties.isEmpty();
}
@@ -2611,17 +2622,10 @@
}
/**
- * @return true if there's at least one face enrolled for the given user
- */
- private boolean isFaceEnrolled(int userId) {
- return mAuthController.isFaceAuthEnrolled(userId);
- }
-
- /**
- * @return true if there's at least one face enrolled for the current user
+ * @return true if there's at least one face enrolled
*/
public boolean isFaceEnrolled() {
- return isFaceEnrolled(getCurrentUser());
+ return mIsFaceEnrolled;
}
private final UserTracker.Callback mUserChangedCallback = new UserTracker.Callback() {
@@ -3280,13 +3284,14 @@
@SuppressLint("MissingPermission")
@VisibleForTesting
boolean isUnlockWithFingerprintPossible(int userId) {
- boolean newFpPossible = isFingerprintSupported()
- && !isFingerprintDisabled(userId) && mAuthController.isFingerprintEnrolled(userId);
- Boolean oldFpPossible = mIsUnlockWithFingerprintPossible.getOrDefault(userId, false);
- if (oldFpPossible != newFpPossible) {
- mLogger.logFpPossibleUpdated(userId, oldFpPossible, newFpPossible);
+ // TODO (b/242022358), make this rely on onEnrollmentChanged event and update it only once.
+ boolean newFpEnrolled = isFingerprintSupported()
+ && !isFingerprintDisabled(userId) && mFpm.hasEnrolledTemplates(userId);
+ Boolean oldFpEnrolled = mIsUnlockWithFingerprintPossible.getOrDefault(userId, false);
+ if (oldFpEnrolled != newFpEnrolled) {
+ mLogger.logFpEnrolledUpdated(userId, oldFpEnrolled, newFpEnrolled);
}
- mIsUnlockWithFingerprintPossible.put(userId, newFpPossible);
+ mIsUnlockWithFingerprintPossible.put(userId, newFpEnrolled);
return mIsUnlockWithFingerprintPossible.get(userId);
}
@@ -3301,13 +3306,24 @@
/**
* @deprecated This is being migrated to use modern architecture.
*/
- @VisibleForTesting
@Deprecated
- public boolean isUnlockWithFacePossible(int userId) {
+ private boolean isUnlockWithFacePossible(int userId) {
if (isFaceAuthInteractorEnabled()) {
return getFaceAuthInteractor().canFaceAuthRun();
}
- return isFaceSupported() && isFaceEnrolled(userId) && !isFaceDisabled(userId);
+ return isFaceAuthEnabledForUser(userId) && !isFaceDisabled(userId);
+ }
+
+ /**
+ * If face hardware is available, user has enrolled and enabled auth via setting.
+ *
+ * @deprecated This is being migrated to use modern architecture.
+ */
+ @Deprecated
+ public boolean isFaceAuthEnabledForUser(int userId) {
+ // TODO (b/242022358), make this rely on onEnrollmentChanged event and update it only once.
+ updateFaceEnrolled(userId);
+ return mIsFaceEnrolled;
}
private void stopListeningForFingerprint() {
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
index ad66909..c6c7113 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
@@ -15,12 +15,19 @@
*/
package com.android.keyguard;
+import static com.android.settingslib.Utils.getColorAttrDefaultColor;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BACKGROUND;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BACKGROUND_PRESSED;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BUTTON;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_PRESSED;
import static com.android.systemui.util.ColorUtilKt.getPrivateAttrColorIfUnset;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
@@ -112,20 +119,18 @@
int[] customAttrs = {android.R.attr.colorControlNormal};
ContextThemeWrapper ctw = new ContextThemeWrapper(context, mStyle);
- TypedArray a = ctw.obtainStyledAttributes(customAttrs);
+ @SuppressLint("ResourceType") TypedArray a = ctw.obtainStyledAttributes(customAttrs);
mNormalBackgroundColor = getPrivateAttrColorIfUnset(ctw, a, 0, 0,
- com.android.internal.R.attr.colorSurface);
+ NUM_PAD_BACKGROUND);
a.recycle();
- mBackground.setColor(mNormalBackgroundColor);
- mPressedBackgroundColor = context.getColor(android.R.color.system_accent1_200);
+ mPressedBackgroundColor = getColorAttrDefaultColor(context, NUM_PAD_BACKGROUND_PRESSED);
+ mTextColorPressed = getColorAttrDefaultColor(context, NUM_PAD_PRESSED);
+
+ mBackground.setColor(mNormalBackgroundColor);
mTextColorPrimary = isNumPadKey
- ? com.android.settingslib.Utils
- .getColorAttrDefaultColor(context, android.R.attr.textColorPrimary)
- : com.android.settingslib.Utils
- .getColorAttrDefaultColor(context, android.R.attr.textColorPrimaryInverse);
- mTextColorPressed = com.android.settingslib.Utils
- .getColorAttrDefaultColor(context, com.android.internal.R.attr.textColorOnAccent);
+ ? getColorAttrDefaultColor(context, NUM_PAD_KEY)
+ : getColorAttrDefaultColor(context, NUM_PAD_BUTTON);
createAnimators();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
index 11c329e..6ae80a6 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
@@ -15,10 +15,12 @@
*/
package com.android.keyguard;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_BUTTON;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY;
+
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
-import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.VectorDrawable;
@@ -27,6 +29,7 @@
import androidx.annotation.Nullable;
+import com.android.settingslib.Utils;
import com.android.systemui.R;
/**
@@ -95,12 +98,8 @@
public void reloadColors() {
if (mAnimator != null) mAnimator.reloadColors(getContext());
- int textColorResId = mIsTransparentMode ? android.R.attr.textColorPrimary
- : android.R.attr.textColorPrimaryInverse;
- int[] customAttrs = {textColorResId};
- TypedArray a = getContext().obtainStyledAttributes(customAttrs);
- int imageColor = a.getColor(0, 0);
- a.recycle();
+ int textColorResId = mIsTransparentMode ? NUM_PAD_KEY : NUM_PAD_BUTTON;
+ int imageColor = Utils.getColorAttrDefaultColor(getContext(), textColorResId);
((VectorDrawable) getDrawable()).setTintList(ColorStateList.valueOf(imageColor));
}
@@ -119,7 +118,7 @@
public void setTransparentMode(boolean isTransparentMode) {
mIsTransparentMode = isTransparentMode;
if (isTransparentMode) {
- setBackgroundColor(android.R.color.transparent);
+ setBackgroundColor(getResources().getColor(android.R.color.transparent));
} else {
setBackground(getContext().getDrawable(R.drawable.num_pad_key_background));
}
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
index 7c7680a..e22fc30 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
@@ -15,6 +15,8 @@
*/
package com.android.keyguard;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.NUM_PAD_KEY;
+
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
@@ -150,7 +152,7 @@
* Reload colors from resources.
**/
public void reloadColors() {
- int textColor = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary)
+ int textColor = Utils.getColorAttr(getContext(), NUM_PAD_KEY)
.getDefaultColor();
int klondikeColor = Utils.getColorAttr(getContext(), android.R.attr.textColorSecondary)
.getDefaultColor();
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
index fc5c254..32f06dc 100644
--- a/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
@@ -16,6 +16,8 @@
package com.android.keyguard;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.PIN_SHAPES;
+
import android.content.Context;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
@@ -37,7 +39,7 @@
private int mPinLength;
private int mDotDiameter;
- private int mColor = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary)
+ private int mColor = Utils.getColorAttr(getContext(), PIN_SHAPES)
.getDefaultColor();
private int mPosition = 0;
private static final int DEFAULT_PIN_LENGTH = 6;
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
index 14810d9..4aeab97 100644
--- a/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeNonHintingView.java
@@ -16,6 +16,8 @@
package com.android.keyguard;
+import static com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.ColorId.PIN_SHAPES;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
@@ -45,8 +47,7 @@
*/
public class PinShapeNonHintingView extends LinearLayout implements PinShapeInput {
- private int mColor = Utils.getColorAttr(getContext(),
- android.R.attr.textColorPrimary).getDefaultColor();
+ private int mColor = Utils.getColorAttr(getContext(), PIN_SHAPES).getDefaultColor();
private int mPosition = 0;
private final PinShapeAdapter mPinShapeAdapter;
private ValueAnimator mValueAnimator = ValueAnimator.ofFloat(1f, 0f);
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index fe40145..1661806 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -630,7 +630,7 @@
)
}
- fun logFpPossibleUpdated(userId: Int, oldValue: Boolean, newValue: Boolean) {
+ fun logFpEnrolledUpdated(userId: Int, oldValue: Boolean, newValue: Boolean) {
logBuffer.log(
TAG,
DEBUG,
@@ -639,7 +639,7 @@
bool1 = oldValue
bool2 = newValue
},
- { "Fp possible state changed for userId: $int1 old: $bool1, new: $bool2" }
+ { "Fp enrolled state changed for userId: $int1 old: $bool1, new: $bool2" }
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/OWNERS b/packages/SystemUI/src/com/android/systemui/accessibility/OWNERS
new file mode 100644
index 0000000..1f66c91
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 44215
+
+include /core/java/android/view/accessibility/OWNERS
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index f3c71da..4158390 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -45,6 +45,8 @@
import com.android.internal.R;
import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity;
+import com.android.internal.accessibility.util.AccessibilityUtils;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ScreenshotHelper;
import com.android.systemui.CoreStartable;
import com.android.systemui.dagger.SysUISingleton;
@@ -520,8 +522,11 @@
SCREENSHOT_ACCESSIBILITY_ACTIONS, new Handler(Looper.getMainLooper()), null);
}
- private void handleHeadsetHook() {
- sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HEADSETHOOK);
+ @VisibleForTesting
+ void handleHeadsetHook() {
+ if (!AccessibilityUtils.interceptHeadsetHookForActiveCall(mContext)) {
+ sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HEADSETHOOK);
+ }
}
private void handleAccessibilityButton() {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
index 7bfd84e..155c26d 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
@@ -463,13 +463,17 @@
if ((configDiff & ActivityInfo.CONFIG_UI_MODE) != 0
|| (configDiff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0
|| (configDiff & ActivityInfo.CONFIG_FONT_SCALE) != 0
+ || (configDiff & ActivityInfo.CONFIG_LOCALE) != 0
|| (configDiff & ActivityInfo.CONFIG_DENSITY) != 0) {
// We listen to following config changes to trigger layout inflation:
// CONFIG_UI_MODE: theme change
// CONFIG_ASSETS_PATHS: wallpaper change
// CONFIG_FONT_SCALE: font size change
+ // CONFIG_LOCALE: language change
// CONFIG_DENSITY: display size change
+ mParams.accessibilityTitle = getAccessibilityWindowTitle(mContext);
+
boolean showSettingPanelAfterThemeChange = mIsVisible;
hideSettingPanel(/* resetPosition= */ false);
inflateView();
@@ -490,11 +494,6 @@
+ mDraggableWindowBounds.top;
return;
}
-
- if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) {
- updateAccessibilityWindowTitle();
- return;
- }
}
private void onWindowInsetChanged() {
@@ -515,13 +514,6 @@
}
}
- private void updateAccessibilityWindowTitle() {
- mParams.accessibilityTitle = getAccessibilityWindowTitle(mContext);
- if (mIsVisible) {
- mWindowManager.updateViewLayout(mSettingView, mParams);
- }
- }
-
public void editMagnifierSizeMode(boolean enable) {
setEditMagnifierSizeMode(enable);
updateSelectedButton(MagnificationSize.NONE);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
index 3b50bbc..935de02 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
@@ -464,7 +464,12 @@
// Fade out the icon if we are animating an activity launch over the lockscreen and the
// activity didn't request the UDFPS.
if (isLaunchingActivity && !udfpsRequested) {
- alpha = (alpha * (1.0f - activityLaunchProgress)).toInt()
+ val udfpsActivityLaunchAlphaMultiplier =
+ 1f -
+ (activityLaunchProgress *
+ (ActivityLaunchAnimator.TIMINGS.totalDuration / 83))
+ .coerceIn(0f, 1f)
+ alpha = (alpha * udfpsActivityLaunchAlphaMultiplier).toInt()
}
// Fade out alpha when a dialog is shown
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
index 67d2f30..f0b9f67 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
@@ -17,6 +17,8 @@
package com.android.systemui.biometrics.dagger
import com.android.settingslib.udfps.UdfpsUtils
+import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository
+import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepositoryImpl
import com.android.systemui.biometrics.data.repository.PromptRepository
import com.android.systemui.biometrics.data.repository.PromptRepositoryImpl
import com.android.systemui.biometrics.domain.interactor.CredentialInteractor
@@ -41,6 +43,11 @@
@Binds
@SysUISingleton
+ fun fingerprintRepository(impl: FingerprintPropertyRepositoryImpl):
+ FingerprintPropertyRepository
+
+ @Binds
+ @SysUISingleton
fun providesCredentialInteractor(impl: CredentialInteractorImpl): CredentialInteractor
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FingerprintPropertyRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FingerprintPropertyRepository.kt
new file mode 100644
index 0000000..33fb36c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FingerprintPropertyRepository.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.data.repository
+
+import android.hardware.biometrics.SensorLocationInternal
+import android.hardware.fingerprint.FingerprintManager
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
+import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback
+import com.android.systemui.biometrics.shared.model.FingerprintSensorType
+import com.android.systemui.biometrics.shared.model.SensorStrength
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.shareIn
+
+/**
+ * A repository for the global state of FingerprintProperty.
+ *
+ * There is never more than one instance of the FingerprintProperty at any given time.
+ */
+interface FingerprintPropertyRepository {
+
+ /**
+ * If the repository is initialized or not. Other properties are defaults until this is true.
+ */
+ val isInitialized: Flow<Boolean>
+
+ /** The id of fingerprint sensor. */
+ val sensorId: StateFlow<Int>
+
+ /** The security strength of sensor (convenience, weak, strong). */
+ val strength: StateFlow<SensorStrength>
+
+ /** The types of fingerprint sensor (rear, ultrasonic, optical, etc.). */
+ val sensorType: StateFlow<FingerprintSensorType>
+
+ /** The primary sensor location relative to the default display. */
+ val sensorLocation: StateFlow<SensorLocationInternal>
+
+ // TODO(b/251476085): don't implement until we need it, but expose alternative locations as
+ // a map of display id -> location or similar.
+ /** The sensor location relative to each physical display. */
+ // val sensorLocations<Map<String, SensorLocationInternal>>
+}
+
+@SysUISingleton
+class FingerprintPropertyRepositoryImpl
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ private val fingerprintManager: FingerprintManager
+) : FingerprintPropertyRepository {
+
+ override val isInitialized: Flow<Boolean> =
+ conflatedCallbackFlow {
+ val callback =
+ object : IFingerprintAuthenticatorsRegisteredCallback.Stub() {
+ override fun onAllAuthenticatorsRegistered(
+ sensors: List<FingerprintSensorPropertiesInternal>
+ ) {
+ if (sensors.isNotEmpty()) {
+ setProperties(sensors[0])
+ trySendWithFailureLogging(true, TAG, "initialize properties")
+ }
+ }
+ }
+ fingerprintManager.addAuthenticatorsRegisteredCallback(callback)
+ trySendWithFailureLogging(false, TAG, "initial value defaulting to false")
+ awaitClose {}
+ }
+ .shareIn(scope = applicationScope, started = SharingStarted.Eagerly, replay = 1)
+
+ private val _sensorId: MutableStateFlow<Int> = MutableStateFlow(-1)
+ override val sensorId: StateFlow<Int> = _sensorId.asStateFlow()
+
+ private val _strength: MutableStateFlow<SensorStrength> =
+ MutableStateFlow(SensorStrength.CONVENIENCE)
+ override val strength = _strength.asStateFlow()
+
+ private val _sensorType: MutableStateFlow<FingerprintSensorType> =
+ MutableStateFlow(FingerprintSensorType.UNKNOWN)
+ override val sensorType = _sensorType.asStateFlow()
+
+ private val _sensorLocation: MutableStateFlow<SensorLocationInternal> =
+ MutableStateFlow(SensorLocationInternal.DEFAULT)
+ override val sensorLocation = _sensorLocation.asStateFlow()
+
+ private fun setProperties(prop: FingerprintSensorPropertiesInternal) {
+ _sensorId.value = prop.sensorId
+ _strength.value = sensorStrengthIntToObject(prop.sensorStrength)
+ _sensorType.value = sensorTypeIntToObject(prop.sensorType)
+ _sensorLocation.value = prop.location
+ }
+
+ companion object {
+ private const val TAG = "FingerprintPropertyRepositoryImpl"
+ }
+}
+
+private fun sensorStrengthIntToObject(value: Int): SensorStrength {
+ return when (value) {
+ 0 -> SensorStrength.CONVENIENCE
+ 1 -> SensorStrength.WEAK
+ 2 -> SensorStrength.STRONG
+ else -> throw IllegalArgumentException("Invalid SensorStrength value: $value")
+ }
+}
+
+private fun sensorTypeIntToObject(value: Int): FingerprintSensorType {
+ return when (value) {
+ 0 -> FingerprintSensorType.UNKNOWN
+ 1 -> FingerprintSensorType.REAR
+ 2 -> FingerprintSensorType.UDFPS_ULTRASONIC
+ 3 -> FingerprintSensorType.UDFPS_OPTICAL
+ 4 -> FingerprintSensorType.POWER_BUTTON
+ 5 -> FingerprintSensorType.HOME_BUTTON
+ else -> throw IllegalArgumentException("Invalid SensorType value: $value")
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/FingerprintSensorType.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/FingerprintSensorType.kt
new file mode 100644
index 0000000..df5cefd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/FingerprintSensorType.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.shared.model
+
+import android.hardware.fingerprint.FingerprintSensorProperties
+
+/** Fingerprint sensor types. Represents [FingerprintSensorProperties.SensorType]. */
+enum class FingerprintSensorType {
+ UNKNOWN,
+ REAR,
+ UDFPS_ULTRASONIC,
+ UDFPS_OPTICAL,
+ POWER_BUTTON,
+ HOME_BUTTON,
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt
new file mode 100644
index 0000000..2982d0b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.shared.model
+
+import android.hardware.biometrics.SensorProperties
+
+/** Fingerprint sensor security strength. Represents [SensorProperties.Strength]. */
+enum class SensorStrength {
+ CONVENIENCE,
+ WEAK,
+ STRONG,
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt
index bcc0575..ede62ac 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt
@@ -65,7 +65,7 @@
super.onLayout(changed, left, top, right, bottom)
val inputLeftBound: Int
- val inputTopBound: Int
+ var inputTopBound: Int
var headerRightBound = right
var headerTopBounds = top
val subTitleBottom: Int = if (subtitleView.isGone) titleView.bottom else subtitleView.bottom
@@ -75,14 +75,23 @@
inputLeftBound = (right - left) / 2
headerRightBound = inputLeftBound
headerTopBounds -= iconView.bottom.coerceAtMost(bottomInset)
+
+ if (descriptionView.bottom > bottomInset) {
+ credentialHeader.layout(left, headerTopBounds, headerRightBound, bottom)
+ }
} else {
inputTopBound = descBottom + (bottom - descBottom - credentialInput.height) / 2
inputLeftBound = (right - left - credentialInput.width) / 2
+
+ if (bottom - inputTopBound < credentialInput.height) {
+ inputTopBound = bottom - credentialInput.height
+ }
+
+ if (descriptionView.bottom > inputTopBound) {
+ credentialHeader.layout(left, headerTopBounds, headerRightBound, inputTopBound)
+ }
}
- if (descriptionView.bottom > bottomInset) {
- credentialHeader.layout(left, headerTopBounds, headerRightBound, bottom)
- }
credentialInput.layout(inputLeftBound, inputTopBound, right, bottom)
}
diff --git a/packages/SystemUI/src/com/android/systemui/complication/ComplicationTypesUpdater.java b/packages/SystemUI/src/com/android/systemui/complication/ComplicationTypesUpdater.java
index 016891d..a334c1e 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/ComplicationTypesUpdater.java
+++ b/packages/SystemUI/src/com/android/systemui/complication/ComplicationTypesUpdater.java
@@ -16,8 +16,6 @@
package com.android.systemui.complication;
-import static com.android.systemui.dreams.dagger.DreamModule.DREAM_PRETEXT_MONITOR;
-
import android.database.ContentObserver;
import android.os.UserHandle;
import android.provider.Settings;
@@ -25,6 +23,7 @@
import com.android.settingslib.dream.DreamBackend;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dagger.qualifiers.SystemUser;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.shared.condition.Monitor;
import com.android.systemui.util.condition.ConditionalCoreStartable;
@@ -33,7 +32,6 @@
import java.util.concurrent.Executor;
import javax.inject.Inject;
-import javax.inject.Named;
/**
* {@link ComplicationTypesUpdater} observes the state of available complication types set by the
@@ -53,7 +51,7 @@
@Main Executor executor,
SecureSettings secureSettings,
DreamOverlayStateController dreamOverlayStateController,
- @Named(DREAM_PRETEXT_MONITOR) Monitor monitor) {
+ @SystemUser Monitor monitor) {
super(monitor);
mDreamBackend = dreamBackend;
mExecutor = executor;
diff --git a/packages/SystemUI/src/com/android/systemui/complication/DreamClockTimeComplication.java b/packages/SystemUI/src/com/android/systemui/complication/DreamClockTimeComplication.java
index 5020480..9c3448b 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/DreamClockTimeComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/complication/DreamClockTimeComplication.java
@@ -18,11 +18,11 @@
import static com.android.systemui.complication.dagger.DreamClockTimeComplicationModule.DREAM_CLOCK_TIME_COMPLICATION_VIEW;
import static com.android.systemui.complication.dagger.RegisteredComplicationsModule.DREAM_CLOCK_TIME_COMPLICATION_LAYOUT_PARAMS;
-import static com.android.systemui.dreams.dagger.DreamModule.DREAM_PRETEXT_MONITOR;
import android.view.View;
import com.android.systemui.CoreStartable;
+import com.android.systemui.dagger.qualifiers.SystemUser;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.shared.condition.Monitor;
import com.android.systemui.util.condition.ConditionalCoreStartable;
@@ -74,7 +74,7 @@
public Registrant(
DreamOverlayStateController dreamOverlayStateController,
DreamClockTimeComplication dreamClockTimeComplication,
- @Named(DREAM_PRETEXT_MONITOR) Monitor monitor) {
+ @SystemUser Monitor monitor) {
super(monitor);
mDreamOverlayStateController = dreamOverlayStateController;
mComplication = dreamClockTimeComplication;
diff --git a/packages/SystemUI/src/com/android/systemui/complication/DreamHomeControlsComplication.java b/packages/SystemUI/src/com/android/systemui/complication/DreamHomeControlsComplication.java
index 8f192de..f973aee 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/DreamHomeControlsComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/complication/DreamHomeControlsComplication.java
@@ -21,7 +21,6 @@
import static com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE;
import static com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK;
import static com.android.systemui.controls.dagger.ControlsComponent.Visibility.UNAVAILABLE;
-import static com.android.systemui.dreams.dagger.DreamModule.DREAM_PRETEXT_MONITOR;
import android.content.Context;
import android.content.Intent;
@@ -40,6 +39,7 @@
import com.android.systemui.controls.management.ControlsListingController;
import com.android.systemui.controls.ui.ControlsActivity;
import com.android.systemui.controls.ui.ControlsUiController;
+import com.android.systemui.dagger.qualifiers.SystemUser;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.shared.condition.Monitor;
@@ -108,7 +108,7 @@
public Registrant(DreamHomeControlsComplication complication,
DreamOverlayStateController dreamOverlayStateController,
ControlsComponent controlsComponent,
- @Named(DREAM_PRETEXT_MONITOR) Monitor monitor) {
+ @SystemUser Monitor monitor) {
super(monitor);
mComplication = complication;
mControlsComponent = controlsComponent;
diff --git a/packages/SystemUI/src/com/android/systemui/complication/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/complication/SmartSpaceComplication.java
index 2f5ef6d..b98794e 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/SmartSpaceComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/complication/SmartSpaceComplication.java
@@ -17,7 +17,6 @@
package com.android.systemui.complication;
import static com.android.systemui.complication.dagger.RegisteredComplicationsModule.DREAM_SMARTSPACE_LAYOUT_PARAMS;
-import static com.android.systemui.dreams.dagger.DreamModule.DREAM_PRETEXT_MONITOR;
import android.content.Context;
import android.os.Parcelable;
@@ -26,6 +25,7 @@
import android.widget.FrameLayout;
import com.android.systemui.CoreStartable;
+import com.android.systemui.dagger.qualifiers.SystemUser;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
import com.android.systemui.flags.FeatureFlags;
@@ -88,7 +88,7 @@
DreamOverlayStateController dreamOverlayStateController,
SmartSpaceComplication smartSpaceComplication,
DreamSmartspaceController smartSpaceController,
- @Named(DREAM_PRETEXT_MONITOR) Monitor monitor,
+ @SystemUser Monitor monitor,
FeatureFlags featureFlags) {
super(monitor);
mDreamOverlayStateController = dreamOverlayStateController;
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
index 3d6d335..18bd467 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -41,7 +41,8 @@
private val context: Context,
@Background private val backgroundExecutor: DelayableExecutor,
private val lazyController: Lazy<ControlsController>,
- userTracker: UserTracker
+ private val packageUpdateMonitorFactory: PackageUpdateMonitor.Factory,
+ userTracker: UserTracker,
) : ControlsBindingController {
companion object {
@@ -93,7 +94,8 @@
backgroundExecutor,
actionCallbackService,
currentUser,
- component
+ component,
+ packageUpdateMonitorFactory
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index 217f4d8..cb2476c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -16,6 +16,7 @@
package com.android.systemui.controls.controller
+import android.annotation.WorkerThread
import android.content.ComponentName
import android.content.Context
import android.content.Intent
@@ -23,7 +24,6 @@
import android.os.Binder
import android.os.Bundle
import android.os.IBinder
-import android.os.RemoteException
import android.os.UserHandle
import android.service.controls.ControlsProviderService
import android.service.controls.ControlsProviderService.CALLBACK_BUNDLE
@@ -38,6 +38,7 @@
import com.android.internal.annotations.GuardedBy
import com.android.systemui.util.concurrency.DelayableExecutor
import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicBoolean
/**
* Manager for the lifecycle of the connection to a given [ControlsProviderService].
@@ -45,6 +46,9 @@
* This class handles binding and unbinding and requests to the service. The class will queue
* requests until the service is connected and dispatch them then.
*
+ * If the provider app is updated, and we are currently bound to it, it will try to rebind after
+ * update is completed.
+ *
* @property context A SystemUI context for binding to the services
* @property executor A delayable executor for posting timeouts
* @property actionCallbackService a callback interface to hand the remote service for sending
@@ -59,22 +63,22 @@
private val executor: DelayableExecutor,
private val actionCallbackService: IControlsActionCallback.Stub,
val user: UserHandle,
- val componentName: ComponentName
-) : IBinder.DeathRecipient {
+ val componentName: ComponentName,
+ packageUpdateMonitorFactory: PackageUpdateMonitor.Factory,
+) {
val token: IBinder = Binder()
private var requiresBound = false
@GuardedBy("queuedServiceMethods")
private val queuedServiceMethods: MutableSet<ServiceMethod> = ArraySet()
private var wrapper: ServiceWrapper? = null
- private var bindTryCount = 0
private val TAG = javaClass.simpleName
private var onLoadCanceller: Runnable? = null
+ private var lastForPanel = false
+
companion object {
- private const val BIND_RETRY_DELAY = 1000L // ms
private const val LOAD_TIMEOUT_SECONDS = 20L // seconds
- private const val MAX_BIND_RETRIES = 5
private const val DEBUG = true
private val BIND_FLAGS = Context.BIND_AUTO_CREATE or Context.BIND_FOREGROUND_SERVICE or
Context.BIND_NOT_PERCEPTIBLE
@@ -91,60 +95,56 @@
})
}
- private fun bindService(bind: Boolean, forPanel: Boolean = false) {
- executor.execute {
- requiresBound = bind
- if (bind) {
- if (bindTryCount != MAX_BIND_RETRIES && wrapper == null) {
- if (DEBUG) {
- Log.d(TAG, "Binding service $intent")
- }
- bindTryCount++
- try {
- val flags = if (forPanel) BIND_FLAGS_PANEL else BIND_FLAGS
- val bound = context
- .bindServiceAsUser(intent, serviceConnection, flags, user)
- if (!bound) {
- context.unbindService(serviceConnection)
- }
- } catch (e: SecurityException) {
- Log.e(TAG, "Failed to bind to service", e)
- }
- }
- } else {
- if (DEBUG) {
- Log.d(TAG, "Unbinding service $intent")
- }
- bindTryCount = 0
- wrapper?.run {
- context.unbindService(serviceConnection)
- }
- wrapper = null
+ private val packageUpdateMonitor = packageUpdateMonitorFactory.create(
+ user,
+ componentName.packageName,
+ ) {
+ if (requiresBound) {
+ // Let's unbind just in case. onBindingDied should have been called and unbound before.
+ executor.execute {
+ unbindAndCleanup("package updated")
+ bindService(true, lastForPanel)
}
}
}
+ private fun bindService(bind: Boolean, forPanel: Boolean = false) {
+ executor.execute {
+ bindServiceBackground(bind, forPanel)
+ }
+ }
+
private val serviceConnection = object : ServiceConnection {
+
+ val connected = AtomicBoolean(false)
+
override fun onServiceConnected(name: ComponentName, service: IBinder) {
if (DEBUG) Log.d(TAG, "onServiceConnected $name")
- bindTryCount = 0
wrapper = ServiceWrapper(IControlsProvider.Stub.asInterface(service))
- try {
- service.linkToDeath(this@ControlsProviderLifecycleManager, 0)
- } catch (_: RemoteException) {}
+ packageUpdateMonitor.startMonitoring()
handlePendingServiceMethods()
}
override fun onServiceDisconnected(name: ComponentName?) {
if (DEBUG) Log.d(TAG, "onServiceDisconnected $name")
wrapper = null
- bindService(false)
+ // No need to call unbind. We may get a new `onServiceConnected`
}
override fun onNullBinding(name: ComponentName?) {
if (DEBUG) Log.d(TAG, "onNullBinding $name")
wrapper = null
- context.unbindService(this)
+ executor.execute {
+ unbindAndCleanup("null binding")
+ }
+ }
+
+ override fun onBindingDied(name: ComponentName?) {
+ super.onBindingDied(name)
+ if (DEBUG) Log.d(TAG, "onBindingDied $name")
+ executor.execute {
+ unbindAndCleanup("binder died")
+ }
}
}
@@ -159,14 +159,55 @@
}
}
- override fun binderDied() {
- if (wrapper == null) return
- wrapper = null
- if (requiresBound) {
- if (DEBUG) {
- Log.d(TAG, "binderDied")
+ @WorkerThread
+ private fun bindServiceBackground(bind: Boolean, forPanel: Boolean = true) {
+ requiresBound = bind
+ if (bind) {
+ if (wrapper == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Binding service $intent")
+ }
+ try {
+ lastForPanel = forPanel
+ val flags = if (forPanel) BIND_FLAGS_PANEL else BIND_FLAGS
+ var bound = false
+ if (serviceConnection.connected.compareAndSet(false, true)) {
+ bound = context
+ .bindServiceAsUser(intent, serviceConnection, flags, user)
+ }
+ if (!bound) {
+ Log.d(TAG, "Couldn't bind to $intent")
+ doUnbind()
+ }
+ } catch (e: SecurityException) {
+ Log.e(TAG, "Failed to bind to service", e)
+ // Couldn't even bind. Let's reset the connected value
+ serviceConnection.connected.set(false)
+ }
}
- // Try rebinding some time later
+ } else {
+ unbindAndCleanup("unbind requested")
+ packageUpdateMonitor.stopMonitoring()
+ }
+ }
+
+ @WorkerThread
+ private fun unbindAndCleanup(reason: String) {
+ if (DEBUG) {
+ Log.d(TAG, "Unbinding service $intent. Reason: $reason")
+ }
+ wrapper = null
+ try {
+ doUnbind()
+ } catch (e: IllegalArgumentException) {
+ Log.e(TAG, "Failed to unbind service", e)
+ }
+ }
+
+ @WorkerThread
+ private fun doUnbind() {
+ if (serviceConnection.connected.compareAndSet(true, false)) {
+ context.unbindService(serviceConnection)
}
}
@@ -313,7 +354,7 @@
fun run() {
if (!callWrapper()) {
queueServiceMethod(this)
- binderDied()
+ executor.execute { unbindAndCleanup("couldn't call through binder") }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/PackageUpdateMonitor.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/PackageUpdateMonitor.kt
new file mode 100644
index 0000000..1973b62
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/PackageUpdateMonitor.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.controls.controller
+
+import android.content.Context
+import android.os.Handler
+import android.os.UserHandle
+import com.android.internal.content.PackageMonitor
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import java.util.concurrent.atomic.AtomicBoolean
+
+/** [PackageMonitor] that tracks when [packageName] has finished updating for user [user]. */
+class PackageUpdateMonitor
+@AssistedInject
+constructor(
+ @Assisted private val user: UserHandle,
+ @Assisted private val packageName: String,
+ @Assisted private val callback: Runnable,
+ @Background private val bgHandler: Handler,
+ @Application private val context: Context,
+) : PackageMonitor() {
+
+ private val monitoring = AtomicBoolean(false)
+
+ @AssistedFactory
+ fun interface Factory {
+ /**
+ * Create a [PackageUpdateMonitor] for a given [user] and [packageName]. It will run
+ * [callback] every time the package finishes updating.
+ */
+ fun create(user: UserHandle, packageName: String, callback: Runnable): PackageUpdateMonitor
+ }
+
+ /** Start monitoring for package updates. No-op if already monitoring. */
+ fun startMonitoring() {
+ if (monitoring.compareAndSet(/* expected */ false, /* new */ true)) {
+ register(context, user, false, bgHandler)
+ }
+ }
+
+ /** Stop monitoring for package updates. No-op if not monitoring. */
+ fun stopMonitoring() {
+ if (monitoring.compareAndSet(/* expected */ true, /* new */ false)) {
+ unregister()
+ }
+ }
+
+ /**
+ * If the package and the user match the ones for this [PackageUpdateMonitor], it will run
+ * [callback].
+ */
+ override fun onPackageUpdateFinished(packageName: String?, uid: Int) {
+ super.onPackageUpdateFinished(packageName, uid)
+ if (packageName == this.packageName && UserHandle.getUserHandleForUid(uid) == user) {
+ callback.run()
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
index 2c717f5..45cb13b 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
@@ -16,11 +16,11 @@
package com.android.systemui.controls.controller
-import android.service.controls.actions.ControlAction
import android.service.controls.IControlsActionCallback
import android.service.controls.IControlsProvider
import android.service.controls.IControlsSubscriber
import android.service.controls.IControlsSubscription
+import android.service.controls.actions.ControlAction
import android.service.controls.actions.ControlActionWrapper
import android.util.Log
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
index 5d608c3..7cbd1f5 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
@@ -16,9 +16,11 @@
package com.android.systemui.controls.ui
+import android.app.Activity
import android.app.ActivityOptions
import android.app.ActivityTaskManager
import android.app.ActivityTaskManager.INVALID_TASK_ID
+import android.app.ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
import android.app.Dialog
import android.app.PendingIntent
import android.content.ComponentName
@@ -96,7 +98,9 @@
activityContext,
0 /* enterResId */,
0 /* exitResId */
- )
+ ).setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
+ options.isPendingIntentBackgroundActivityLaunchAllowedByPermission = true
+
taskView.startActivity(
pendingIntent,
fillInIntent,
@@ -214,6 +218,12 @@
if (!isShowing()) return
taskView.release()
+ val isActivityFinishing =
+ (activityContext as? Activity)?.let { it.isFinishing || it.isDestroyed }
+ if (isActivityFinishing == true) {
+ // Don't dismiss the dialog if the activity is finishing, it will get removed
+ return
+ }
super.dismiss()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index dff2c0e..8e6e0dd 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -42,6 +42,7 @@
import com.android.systemui.complication.dagger.ComplicationComponent;
import com.android.systemui.controls.dagger.ControlsModule;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dagger.qualifiers.SystemUser;
import com.android.systemui.demomode.dagger.DemoModeModule;
import com.android.systemui.doze.dagger.DozeComponent;
import com.android.systemui.dreams.dagger.DreamModule;
@@ -60,6 +61,7 @@
import com.android.systemui.plugins.BcSmartspaceConfigPlugin;
import com.android.systemui.plugins.BcSmartspaceDataPlugin;
import com.android.systemui.privacy.PrivacyModule;
+import com.android.systemui.process.condition.SystemProcessCondition;
import com.android.systemui.qrcodescanner.dagger.QRCodeScannerModule;
import com.android.systemui.qs.FgsManagerController;
import com.android.systemui.qs.FgsManagerControllerImpl;
@@ -74,6 +76,7 @@
import com.android.systemui.shade.ShadeModule;
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.shade.transition.LargeScreenShadeInterpolatorImpl;
+import com.android.systemui.shared.condition.Monitor;
import com.android.systemui.smartspace.dagger.SmartspaceModule;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -126,6 +129,7 @@
import dagger.Module;
import dagger.Provides;
+import java.util.Collections;
import java.util.Optional;
import java.util.concurrent.Executor;
@@ -232,6 +236,17 @@
return state;
}
+ /**
+ * Provides the monitor for SystemUI that requires the process running as the system user.
+ */
+ @SysUISingleton
+ @Provides
+ @SystemUser
+ static Monitor provideSystemUserMonitor(@Main Executor executor,
+ SystemProcessCondition systemProcessCondition) {
+ return new Monitor(executor, Collections.singleton(systemProcessCondition));
+ }
+
@BindsOptionalOf
abstract CommandQueue optionalCommandQueue();
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/SystemUser.kt b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/SystemUser.kt
new file mode 100644
index 0000000..6878a52
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/SystemUser.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.dagger.qualifiers
+
+import javax.inject.Qualifier
+
+@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class SystemUser
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/AssistantAttentionMonitor.java b/packages/SystemUI/src/com/android/systemui/dreams/AssistantAttentionMonitor.java
index 49d7f78..822cfb8 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/AssistantAttentionMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/AssistantAttentionMonitor.java
@@ -19,6 +19,7 @@
import android.util.Log;
import com.android.systemui.CoreStartable;
+import com.android.systemui.dagger.qualifiers.SystemUser;
import com.android.systemui.dreams.callbacks.AssistantAttentionCallback;
import com.android.systemui.dreams.conditions.AssistantAttentionCondition;
import com.android.systemui.shared.condition.Monitor;
@@ -38,7 +39,7 @@
@Inject
public AssistantAttentionMonitor(
- Monitor monitor,
+ @SystemUser Monitor monitor,
AssistantAttentionCondition assistantAttentionCondition,
AssistantAttentionCallback callback) {
mConditionMonitor = monitor;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt
new file mode 100644
index 0000000..eb79290
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams
+
+import com.android.systemui.log.dagger.DreamLog
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import javax.inject.Inject
+
+/** Logs dream-related stuff to a {@link LogBuffer}. */
+class DreamLogger @Inject constructor(@DreamLog private val buffer: LogBuffer) {
+ /** Logs a debug message to the buffer. */
+ fun d(tag: String, message: String) {
+ buffer.log(tag, LogLevel.DEBUG, { str1 = message }, { message })
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamMonitor.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamMonitor.java
index 7f567aa..e9ebd3b 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamMonitor.java
@@ -16,11 +16,10 @@
package com.android.systemui.dreams;
-import static com.android.systemui.dreams.dagger.DreamModule.DREAM_PRETEXT_MONITOR;
-
import android.util.Log;
import com.android.systemui.CoreStartable;
+import com.android.systemui.dagger.qualifiers.SystemUser;
import com.android.systemui.dreams.callbacks.DreamStatusBarStateCallback;
import com.android.systemui.dreams.conditions.DreamCondition;
import com.android.systemui.flags.RestartDozeListener;
@@ -28,7 +27,6 @@
import com.android.systemui.util.condition.ConditionalCoreStartable;
import javax.inject.Inject;
-import javax.inject.Named;
/**
* A {@link CoreStartable} to retain a monitor for tracking dreaming.
@@ -42,13 +40,11 @@
private final DreamStatusBarStateCallback mCallback;
private RestartDozeListener mRestartDozeListener;
-
@Inject
- public DreamMonitor(Monitor monitor, DreamCondition dreamCondition,
- @Named(DREAM_PRETEXT_MONITOR) Monitor pretextMonitor,
+ public DreamMonitor(@SystemUser Monitor monitor, DreamCondition dreamCondition,
DreamStatusBarStateCallback callback,
RestartDozeListener restartDozeListener) {
- super(pretextMonitor);
+ super(monitor);
mConditionMonitor = monitor;
mDreamCondition = dreamCondition;
mCallback = callback;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index 5b56c04..df46e07 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -21,6 +21,7 @@
import android.animation.ValueAnimator
import android.view.View
import android.view.animation.Interpolator
+import androidx.core.animation.doOnCancel
import androidx.core.animation.doOnEnd
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
@@ -65,7 +66,11 @@
private val mDreamInTranslationYDistance: Int,
@Named(DreamOverlayModule.DREAM_IN_TRANSLATION_Y_DURATION)
private val mDreamInTranslationYDurationMs: Long,
+ private val mLogger: DreamLogger,
) {
+ companion object {
+ private const val TAG = "DreamOverlayAnimationsController"
+ }
private var mAnimator: Animator? = null
private lateinit var view: View
@@ -169,8 +174,11 @@
doOnEnd {
mAnimator = null
mOverlayStateController.setEntryAnimationsFinished(true)
+ mLogger.d(TAG, "Dream overlay entry animations finished.")
}
+ doOnCancel { mLogger.d(TAG, "Dream overlay entry animations canceled.") }
start()
+ mLogger.d(TAG, "Dream overlay entry animations started.")
}
}
@@ -232,8 +240,11 @@
doOnEnd {
mAnimator = null
mOverlayStateController.setExitAnimationsRunning(false)
+ mLogger.d(TAG, "Dream overlay exit animations finished.")
}
+ doOnCancel { mLogger.d(TAG, "Dream overlay exit animations canceled.") }
start()
+ mLogger.d(TAG, "Dream overlay exit animations started.")
}
mOverlayStateController.setExitAnimationsRunning(true)
return mAnimator as AnimatorSet
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayRegistrant.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayRegistrant.java
index a2dcdf5..80e68cf 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayRegistrant.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayRegistrant.java
@@ -17,7 +17,6 @@
package com.android.systemui.dreams;
import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_SERVICE_COMPONENT;
-import static com.android.systemui.dreams.dagger.DreamModule.DREAM_PRETEXT_MONITOR;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -35,6 +34,7 @@
import android.util.Log;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dagger.qualifiers.SystemUser;
import com.android.systemui.shared.condition.Monitor;
import com.android.systemui.util.condition.ConditionalCoreStartable;
@@ -105,7 +105,7 @@
@Inject
public DreamOverlayRegistrant(Context context, @Main Resources resources,
@Named(DREAM_OVERLAY_SERVICE_COMPONENT) ComponentName dreamOverlayServiceComponent,
- @Named(DREAM_PRETEXT_MONITOR) Monitor monitor) {
+ @SystemUser Monitor monitor) {
super(monitor);
mContext = context;
mResources = resources;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
index 1271645d..c61b4775 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -31,22 +31,14 @@
import com.android.systemui.dreams.DreamOverlayService;
import com.android.systemui.dreams.complication.dagger.ComplicationComponent;
import com.android.systemui.dreams.touch.scrim.dagger.ScrimModule;
-import com.android.systemui.process.condition.SystemProcessCondition;
-import com.android.systemui.shared.condition.Condition;
-import com.android.systemui.shared.condition.Monitor;
-import dagger.Binds;
import dagger.Module;
import dagger.Provides;
-import dagger.multibindings.IntoSet;
import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.Executor;
import javax.inject.Named;
-
/**
* Dagger Module providing Dream-related functionality.
*/
@@ -65,11 +57,8 @@
String DREAM_OVERLAY_ENABLED = "dream_overlay_enabled";
String DREAM_SUPPORTED = "dream_supported";
- String DREAM_PRETEXT_CONDITIONS = "dream_pretext_conditions";
- String DREAM_PRETEXT_MONITOR = "dream_prtext_monitor";
String DREAM_OVERLAY_WINDOW_TITLE = "dream_overlay_window_title";
-
/**
* Provides the dream component
*/
@@ -129,21 +118,6 @@
}
/** */
- @Binds
- @IntoSet
- @Named(DREAM_PRETEXT_CONDITIONS)
- Condition bindSystemProcessCondition(SystemProcessCondition condition);
-
- /** */
- @Provides
- @Named(DREAM_PRETEXT_MONITOR)
- static Monitor providesDockerPretextMonitor(
- @Main Executor executor,
- @Named(DREAM_PRETEXT_CONDITIONS) Set<Condition> pretextConditions) {
- return new Monitor(executor, pretextConditions);
- }
-
- /** */
@Provides
@Named(DREAM_OVERLAY_WINDOW_TITLE)
static String providesDreamOverlayWindowTitle(@Main Resources resources) {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index cc7fa27..af7387b 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -71,8 +71,6 @@
val NOTIFICATION_MEMORY_LOGGING_ENABLED =
unreleasedFlag(119, "notification_memory_logging_enabled")
- @JvmField val USE_ROUNDNESS_SOURCETYPES = releasedFlag(116, "use_roundness_sourcetype")
-
@JvmField
val SIMPLIFIED_APPEAR_FRACTION =
releasedFlag(259395680, "simplified_appear_fraction")
@@ -84,7 +82,8 @@
// TODO(b/278873737): Tracking Bug
@JvmField
val LOAD_NOTIFICATIONS_BEFORE_THE_USER_SWITCH_IS_COMPLETE =
- unreleasedFlag(278873737, "load_notifications_before_the_user_switch_is_complete")
+ unreleasedFlag(278873737, "load_notifications_before_the_user_switch_is_complete",
+ teamfood = true)
// TODO(b/277338665): Tracking Bug
@JvmField
@@ -119,7 +118,7 @@
// TODO(b/275694445): Tracking Bug
@JvmField
- val LOCKSCREEN_WITHOUT_SECURE_LOCK_WHEN_DREAMING = releasedFlag(208,
+ val LOCKSCREEN_WITHOUT_SECURE_LOCK_WHEN_DREAMING = unreleasedFlag(208,
"lockscreen_without_secure_lock_when_dreaming")
/**
@@ -226,6 +225,17 @@
val LOCK_SCREEN_LONG_PRESS_DIRECT_TO_WPP =
unreleasedFlag(232, "lock_screen_long_press_directly_opens_wallpaper_picker")
+ /** Whether to run the new udfps keyguard refactor code. */
+ // TODO(b/279440316): Tracking bug.
+ @JvmField
+ val REFACTOR_UDFPS_KEYGUARD_VIEWS = unreleasedFlag(233, "refactor_udfps_keyguard_views")
+
+ /** Provide new auth messages on the bouncer. */
+ // TODO(b/277961132): Tracking bug.
+ @JvmField
+ val REVAMPED_BOUNCER_MESSAGES =
+ unreleasedFlag(234, "revamped_bouncer_messages")
+
// 300 - power menu
// TODO(b/254512600): Tracking Bug
@JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite")
@@ -615,10 +625,12 @@
val APP_PANELS_REMOVE_APPS_ALLOWED =
unreleasedFlag(2003, "app_panels_remove_apps_allowed", teamfood = true)
- // 2200 - udfps
+ // 2200 - biometrics (udfps, sfps, BiometricPrompt, etc.)
// TODO(b/259264861): Tracking Bug
@JvmField val UDFPS_NEW_TOUCH_DETECTION = releasedFlag(2200, "udfps_new_touch_detection")
@JvmField val UDFPS_ELLIPSE_DETECTION = releasedFlag(2201, "udfps_ellipse_detection")
+ // TODO(b/278622168): Tracking Bug
+ @JvmField val BIOMETRIC_BP_STRONG = unreleasedFlag(2202, "biometric_bp_strong")
// 2300 - stylus
@JvmField val TRACK_STYLUS_EVER_USED = releasedFlag(2300, "track_stylus_ever_used")
@@ -682,10 +694,11 @@
// TODO(b/272805037): Tracking Bug
@JvmField
- val ADVANCED_VPN_ENABLED = unreleasedFlag(2800, name = "AdvancedVpn__enable_feature",
- namespace = "vpn", teamfood = true)
+ val ADVANCED_VPN_ENABLED = releasedFlag(2800, name = "AdvancedVpn__enable_feature",
+ namespace = "vpn")
// TODO(b/278761837): Tracking Bug
@JvmField
- val USE_NEW_ACTIVITY_STARTER = unreleasedFlag(2801, name = "use_new_activity_starter")
+ val USE_NEW_ACTIVITY_STARTER = unreleasedFlag(2801, name = "use_new_activity_starter",
+ teamfood = true)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 107e685..8b6bd24 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -243,7 +243,7 @@
Slog.e(TAG, "Called mergeAnimation, but finish callback is missing");
return;
}
- runner.onAnimationCancelled(false /* isKeyguardOccluded */);
+ runner.onAnimationCancelled();
currentFinishCB.onTransitionFinished(null /* wct */, null /* t */);
} catch (RemoteException e) {
// nothing, we'll just let it finish on its own I guess.
@@ -418,7 +418,7 @@
}
@Override // Binder interface
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
mKeyguardViewMediator.cancelKeyguardExitAnimation();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 93ddfba..1a126d7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -959,20 +959,15 @@
@Nullable private ValueAnimator mOccludeByDreamAnimator;
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
mContext.getMainExecutor().execute(() -> {
if (mOccludeByDreamAnimator != null) {
mOccludeByDreamAnimator.cancel();
}
});
- // The value of isKeyguardOccluded here may come from mergeAnimation, which
- // isn't reliable. In all cases, after running or cancelling this animation,
- // keyguard should be occluded.
+
+ Log.d(TAG, "OccludeByDreamAnimator#onAnimationCancelled. Set occluded = true");
setOccluded(true /* isOccluded */, false /* animate */);
- if (DEBUG) {
- Log.d(TAG, "Occlude by Dream animation cancelled. Occluded state is now: "
- + mOccluded);
- }
}
@Override
@@ -984,6 +979,7 @@
// Usually we rely on animation completion to synchronize occluded status,
// but there was no animation to play, so just update it now.
setOccluded(true /* isOccluded */, false /* animate */);
+ finishedCallback.onAnimationFinished();
}
}
@@ -991,11 +987,8 @@
RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
if (apps == null || apps.length == 0 || apps[0] == null) {
- if (DEBUG) {
- Log.d(TAG, "No apps provided to the OccludeByDream runner; "
- + "skipping occluding animation.");
- }
- finishedCallback.onAnimationFinished();
+ Log.d(TAG, "No apps provided to the OccludeByDream runner; "
+ + "skipping occluding animation.");
return false;
}
@@ -1005,7 +998,6 @@
if (!isDream) {
Log.w(TAG, "The occluding app isn't Dream; "
+ "finishing up. Please check that the config is correct.");
- finishedCallback.onAnimationFinished();
return false;
}
@@ -1071,17 +1063,14 @@
private final Matrix mUnoccludeMatrix = new Matrix();
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
mContext.getMainExecutor().execute(() -> {
if (mUnoccludeAnimator != null) {
mUnoccludeAnimator.cancel();
}
});
- setOccluded(isKeyguardOccluded /* isOccluded */, false /* animate */);
- Log.d(TAG, "Unocclude animation cancelled. Occluded state is now: "
- + mOccluded);
-
+ Log.d(TAG, "Unocclude animation cancelled.");
mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_OCCLUSION);
}
@@ -3404,9 +3393,9 @@
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException {
+ public void onAnimationCancelled() throws RemoteException {
if (mRunner != null) {
- mRunner.onAnimationCancelled(isKeyguardOccluded);
+ mRunner.onAnimationCancelled();
}
}
@@ -3452,13 +3441,9 @@
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException {
- super.onAnimationCancelled(isKeyguardOccluded);
-
- Log.d(TAG, "Occlude animation cancelled by WM. "
- + "Setting occluded state to: " + isKeyguardOccluded);
- setOccluded(isKeyguardOccluded /* occluded */, false /* animate */);
-
+ public void onAnimationCancelled() throws RemoteException {
+ super.onAnimationCancelled();
+ Log.d(TAG, "Occlude animation cancelled by WM.");
mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_OCCLUSION);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
index 9b94cdb..148d425 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
@@ -41,17 +41,6 @@
var receivedDownTouch = false
val isVisible: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
- private val keyguardStateControllerCallback: KeyguardStateController.Callback =
- object : KeyguardStateController.Callback {
- override fun onUnlockedChanged() {
- maybeHide()
- }
- }
-
- init {
- keyguardStateController.addCallback(keyguardStateControllerCallback)
- }
-
/**
* Sets the correct bouncer states to show the alternate bouncer if it can show.
*
@@ -102,11 +91,18 @@
return (systemClock.uptimeMillis() - bouncerRepository.lastAlternateBouncerVisibleTime) >
MIN_VISIBILITY_DURATION_UNTIL_TOUCHES_DISMISS_ALTERNATE_BOUNCER_MS
}
-
- private fun maybeHide() {
+ /**
+ * Should only be called through StatusBarKeyguardViewManager which propagates the source of
+ * truth to other concerned controllers. Will hide the alternate bouncer if it's no longer
+ * allowed to show.
+ *
+ * @return true if the alternate bouncer was newly hidden, else false.
+ */
+ fun maybeHide(): Boolean {
if (isVisibleState() && !canShowAlternateBouncerForFingerprint()) {
- hide()
+ return hide()
}
+ return false
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt
index 3b3ec39..c45faf0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/constants/KeyguardBouncerConstants.kt
@@ -32,4 +32,15 @@
* PIN hinting is enabled
*/
const val DEFAULT_PIN_LENGTH = 6
+
+ object ColorId {
+ const val TITLE = com.android.internal.R.attr.materialColorOnSurface
+ const val PIN_SHAPES = com.android.internal.R.attr.materialColorOnSurfaceVariant
+ const val NUM_PAD_BACKGROUND = com.android.internal.R.attr.materialColorSurfaceContainerHigh
+ const val NUM_PAD_BACKGROUND_PRESSED = com.android.internal.R.attr.materialColorPrimaryFixed
+ const val NUM_PAD_PRESSED = com.android.internal.R.attr.materialColorOnPrimaryFixed
+ const val NUM_PAD_KEY = com.android.internal.R.attr.materialColorOnSurface
+ const val NUM_PAD_BUTTON = com.android.internal.R.attr.materialColorOnSecondaryFixed
+ const val EMERGENCY_BUTTON = com.android.internal.R.attr.materialColorTertiaryFixed
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/DreamLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/DreamLog.kt
new file mode 100644
index 0000000..cb9913ab
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/DreamLog.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log.dagger
+
+import javax.inject.Qualifier
+
+/** A [com.android.systemui.log.LogBuffer] for dream-related logging. */
+@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class DreamLog
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 077ee02..658f6a0 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -440,4 +440,14 @@
public static LogBuffer provideKeyguardLogBuffer(LogBufferFactory factory) {
return factory.create("KeyguardLog", 250);
}
+
+ /**
+ * Provides a {@link LogBuffer} for dream-related logs.
+ */
+ @Provides
+ @SysUISingleton
+ @DreamLog
+ public static LogBuffer provideDreamLogBuffer(LogBufferFactory factory) {
+ return factory.create("DreamLog", 250);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/LogProxy.kt b/packages/SystemUI/src/com/android/systemui/log/table/LogProxy.kt
new file mode 100644
index 0000000..53886aa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/table/LogProxy.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log.table
+
+import android.util.Log
+import javax.inject.Inject
+
+/** Dagger-friendly interface so we can inject a fake [android.util.Log] in tests */
+interface LogProxy {
+ /** verbose log */
+ fun v(tag: String, message: String)
+
+ /** debug log */
+ fun d(tag: String, message: String)
+
+ /** info log */
+ fun i(tag: String, message: String)
+
+ /** warning log */
+ fun w(tag: String, message: String)
+
+ /** error log */
+ fun e(tag: String, message: String)
+
+ /** wtf log */
+ fun wtf(tag: String, message: String)
+}
+
+class LogProxyDefault @Inject constructor() : LogProxy {
+ override fun v(tag: String, message: String) {
+ Log.v(tag, message)
+ }
+
+ override fun d(tag: String, message: String) {
+ Log.d(tag, message)
+ }
+
+ override fun i(tag: String, message: String) {
+ Log.i(tag, message)
+ }
+
+ override fun w(tag: String, message: String) {
+ Log.w(tag, message)
+ }
+
+ override fun e(tag: String, message: String) {
+ Log.e(tag, message)
+ }
+
+ override fun wtf(tag: String, message: String) {
+ Log.wtf(tag, message)
+ }
+}
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 faaa205..9d883cc 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -19,10 +19,17 @@
import android.os.Trace
import com.android.systemui.Dumpable
import com.android.systemui.common.buffer.RingBuffer
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.plugins.log.LogcatEchoTracker
import com.android.systemui.util.time.SystemClock
import java.io.PrintWriter
import java.text.SimpleDateFormat
import java.util.Locale
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.launch
/**
* A logger that logs changes in table format.
@@ -73,12 +80,18 @@
maxSize: Int,
private val name: String,
private val systemClock: SystemClock,
+ private val logcatEchoTracker: LogcatEchoTracker,
+ @Background private val bgDispatcher: CoroutineDispatcher,
+ private val coroutineScope: CoroutineScope,
+ private val localLogcat: LogProxy = LogProxyDefault(),
) : Dumpable {
init {
if (maxSize <= 0) {
throw IllegalArgumentException("maxSize must be > 0")
}
}
+ // For local logcat, send messages across this channel so the background job can process them
+ private val logMessageChannel = Channel<TableChange>(capacity = 10)
private val buffer = RingBuffer(maxSize) { TableChange() }
@@ -105,6 +118,16 @@
tableLogBuffer = this,
)
+ /** Start this log buffer logging in the background */
+ internal fun init() {
+ coroutineScope.launch(bgDispatcher) {
+ while (!logMessageChannel.isClosedForReceive) {
+ val log = logMessageChannel.receive()
+ echoToDesiredEndpoints(log)
+ }
+ }
+ }
+
/**
* Log the differences between [prevVal] and [newVal].
*
@@ -189,6 +212,7 @@
Trace.beginSection("TableLogBuffer#logChange(string)")
val change = obtain(timestamp, prefix, columnName, isInitial)
change.set(value)
+ tryAddMessage(change)
Trace.endSection()
}
@@ -202,6 +226,7 @@
Trace.beginSection("TableLogBuffer#logChange(boolean)")
val change = obtain(timestamp, prefix, columnName, isInitial)
change.set(value)
+ tryAddMessage(change)
Trace.endSection()
}
@@ -215,9 +240,14 @@
Trace.beginSection("TableLogBuffer#logChange(int)")
val change = obtain(timestamp, prefix, columnName, isInitial)
change.set(value)
+ tryAddMessage(change)
Trace.endSection()
}
+ private fun tryAddMessage(change: TableChange) {
+ logMessageChannel.trySend(change)
+ }
+
// TODO(b/259454430): Add additional change types here.
@Synchronized
@@ -258,6 +288,17 @@
Trace.endSection()
}
+ private fun echoToDesiredEndpoints(change: TableChange) {
+ if (
+ logcatEchoTracker.isBufferLoggable(bufferName = name, LogLevel.DEBUG) ||
+ logcatEchoTracker.isTagLoggable(change.columnName, LogLevel.DEBUG)
+ ) {
+ if (change.hasData()) {
+ localLogcat.d(name, change.logcatRepresentation())
+ }
+ }
+ }
+
@Synchronized
override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.println(HEADER_PREFIX + name)
@@ -284,6 +325,12 @@
pw.println()
}
+ /** Transforms an individual [TableChange] into a String for logcat */
+ private fun TableChange.logcatRepresentation(): String {
+ val formattedTimestamp = TABLE_LOG_DATE_FORMAT.format(timestamp)
+ return "$formattedTimestamp$SEPARATOR${getName()}$SEPARATOR${getVal()}"
+ }
+
/**
* A private implementation of [TableRowLogger].
*
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
index 06668d3..42e742d 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
@@ -17,10 +17,15 @@
package com.android.systemui.log.table
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dump.DumpManager
import com.android.systemui.log.LogBufferHelper.Companion.adjustMaxSize
+import com.android.systemui.plugins.log.LogcatEchoTracker
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
@SysUISingleton
class TableLogBufferFactory
@@ -28,6 +33,9 @@
constructor(
private val dumpManager: DumpManager,
private val systemClock: SystemClock,
+ private val logcatEchoTracker: LogcatEchoTracker,
+ @Background private val bgDispatcher: CoroutineDispatcher,
+ @Application private val coroutineScope: CoroutineScope,
) {
private val existingBuffers = mutableMapOf<String, TableLogBuffer>()
@@ -44,8 +52,17 @@
name: String,
maxSize: Int,
): TableLogBuffer {
- val tableBuffer = TableLogBuffer(adjustMaxSize(maxSize), name, systemClock)
+ val tableBuffer =
+ TableLogBuffer(
+ adjustMaxSize(maxSize),
+ name,
+ systemClock,
+ logcatEchoTracker,
+ bgDispatcher,
+ coroutineScope,
+ )
dumpManager.registerNormalDumpable(name, tableBuffer)
+ tableBuffer.init()
return tableBuffer
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
index 0860c20..aec7b5f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
@@ -259,7 +259,7 @@
putExtra(Intent.EXTRA_INTENT, queryIntent)
// Update the title of the chooser
- val title = resources.getString(R.string.media_projection_permission_app_selector_title)
+ val title = resources.getString(R.string.screen_share_permission_app_selector_title)
putExtra(Intent.EXTRA_TITLE, title)
// Select host app's profile tab by default
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index e217e36..28adfbb 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -157,8 +157,8 @@
CharSequence dialogTitle = null;
String appName = null;
if (Utils.isHeadlessRemoteDisplayProvider(packageManager, mPackageName)) {
- dialogText = getString(R.string.media_projection_dialog_service_text);
- dialogTitle = getString(R.string.media_projection_dialog_service_title);
+ dialogText = getString(R.string.media_projection_sys_service_dialog_warning);
+ dialogTitle = getString(R.string.media_projection_sys_service_dialog_title);
} else {
String label = aInfo.loadLabel(packageManager).toString();
@@ -188,7 +188,7 @@
paint, MAX_APP_NAME_SIZE_PX, TextUtils.TruncateAt.END).toString();
appName = BidiFormatter.getInstance().unicodeWrap(unsanitizedAppName);
- String actionText = getString(R.string.media_projection_dialog_text, appName);
+ String actionText = getString(R.string.media_projection_dialog_warning, appName);
SpannableString message = new SpannableString(actionText);
int appNameIndex = actionText.indexOf(appName);
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index 2a8168b..05e04a1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -88,18 +88,9 @@
private final IBinder mToken;
private final Ringtone mRingtone;
- public Client(IBinder token, Uri uri, UserHandle user, AudioAttributes aa) {
- this(token, uri, user, aa, null);
- }
-
- Client(IBinder token, Uri uri, UserHandle user, AudioAttributes aa,
- @Nullable VolumeShaper.Configuration volumeShaperConfig) {
+ Client(IBinder token, Ringtone ringtone) {
mToken = token;
-
- mRingtone = new Ringtone(getContextForUser(user), false);
- mRingtone.setAudioAttributesField(aa);
- mRingtone.setUri(uri, volumeShaperConfig);
- mRingtone.createLocalMediaPlayer();
+ mRingtone = ringtone;
}
@Override
@@ -129,11 +120,28 @@
Client client;
synchronized (mClients) {
client = mClients.get(token);
- if (client == null) {
- final UserHandle user = Binder.getCallingUserHandle();
- client = new Client(token, uri, user, aa, volumeShaperConfig);
- token.linkToDeath(client, 0);
- mClients.put(token, client);
+ }
+ // Don't hold the lock while constructing the ringtone, since it can be slow. The caller
+ // shouldn't call play on the same ringtone from 2 threads, so this shouldn't race and
+ // waste the build.
+ if (client == null) {
+ final UserHandle user = Binder.getCallingUserHandle();
+ Ringtone ringtone = new Ringtone(getContextForUser(user), false);
+ ringtone.setAudioAttributesField(aa);
+ ringtone.setUri(uri, volumeShaperConfig);
+ ringtone.createLocalMediaPlayer();
+ synchronized (mClients) {
+ client = mClients.get(token);
+ if (client == null) {
+ client = new Client(token, ringtone);
+ token.linkToDeath(client, 0);
+ mClients.put(token, client);
+ ringtone = null; // "owned" by the client now.
+ }
+ }
+ // Clean up ringtone if it was abandoned (a client already existed).
+ if (ringtone != null) {
+ ringtone.stop();
}
}
client.mRingtone.setLooping(looping);
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
index 120704c..3fc3ad6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
@@ -154,6 +154,7 @@
get() = controller?.sessionToken
private var started = false
private var playbackType = PLAYBACK_TYPE_UNKNOWN
+ private var playbackVolumeControlId: String? = null
private var current: MediaDeviceData? = null
set(value) {
val sameWithoutIcon = value != null && value.equalsWithoutIcon(field)
@@ -181,6 +182,7 @@
localMediaManager.startScan()
muteAwaitConnectionManager?.startListening()
playbackType = controller?.playbackInfo?.playbackType ?: PLAYBACK_TYPE_UNKNOWN
+ playbackVolumeControlId = controller?.playbackInfo?.volumeControlId
controller?.registerCallback(this)
updateCurrent()
started = true
@@ -209,6 +211,8 @@
println(" current device is ${current?.name}")
val type = controller?.playbackInfo?.playbackType
println(" PlaybackType=$type (1 for local, 2 for remote) cached=$playbackType")
+ val volumeControlId = controller?.playbackInfo?.volumeControlId
+ println(" volumeControlId=$volumeControlId cached= $playbackVolumeControlId")
println(" routingSession=$routingSession")
println(" selectedRoutes=$selectedRoutes")
}
@@ -217,10 +221,15 @@
@WorkerThread
override fun onAudioInfoChanged(info: MediaController.PlaybackInfo?) {
val newPlaybackType = info?.playbackType ?: PLAYBACK_TYPE_UNKNOWN
- if (newPlaybackType == playbackType) {
+ val newPlaybackVolumeControlId = info?.volumeControlId
+ if (
+ newPlaybackType == playbackType &&
+ newPlaybackVolumeControlId == playbackVolumeControlId
+ ) {
return
}
playbackType = newPlaybackType
+ playbackVolumeControlId = newPlaybackVolumeControlId
updateCurrent()
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
index 0aa4349..1e9a466 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
@@ -67,6 +67,7 @@
import com.android.systemui.util.time.SystemClock
import com.android.systemui.util.traceSection
import java.io.PrintWriter
+import java.util.Locale
import java.util.TreeMap
import javax.inject.Inject
import javax.inject.Provider
@@ -166,6 +167,8 @@
}
}
+ private var carouselLocale: Locale? = null
+
/** Whether the media card currently has the "expanded" layout */
@VisibleForTesting
var currentlyExpanded = true
@@ -218,6 +221,15 @@
updatePlayers(recreateMedia = false)
inflateSettingsButton()
}
+
+ override fun onLocaleListChanged() {
+ // Update players only if system primary language changes.
+ if (carouselLocale != context.resources.configuration.locales.get(0)) {
+ carouselLocale = context.resources.configuration.locales.get(0)
+ updatePlayers(recreateMedia = true)
+ inflateSettingsButton()
+ }
+ }
}
private val keyguardUpdateMonitorCallback =
@@ -262,6 +274,7 @@
this::logSmartspaceImpression,
logger
)
+ carouselLocale = context.resources.configuration.locales.get(0)
isRtl = context.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL
inflateSettingsButton()
mediaContent = mediaCarousel.requireViewById(R.id.media_carousel)
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 9ebc8e4..8e014c6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -126,10 +126,11 @@
private final LocalBluetoothManager mLocalBluetoothManager;
private final ActivityStarter mActivityStarter;
private final DialogLaunchAnimator mDialogLaunchAnimator;
- private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
private final CommonNotifCollection mNotifCollection;
private final Object mMediaDevicesLock = new Object();
@VisibleForTesting
+ final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
+ @VisibleForTesting
final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
final List<MediaDevice> mCachedMediaDevices = new CopyOnWriteArrayList<>();
private final List<MediaItem> mMediaItemList = new CopyOnWriteArrayList<>();
@@ -713,7 +714,7 @@
dividerItems.forEach((key, item) -> {
finalMediaItems.add(key, item);
});
- finalMediaItems.add(new MediaItem());
+ attachConnectNewDeviceItemIfNeeded(finalMediaItems);
mMediaItemList.clear();
mMediaItemList.addAll(finalMediaItems);
}
@@ -749,7 +750,7 @@
finalMediaItems.add(new MediaItem(device));
}
}
- finalMediaItems.add(new MediaItem());
+ attachConnectNewDeviceItemIfNeeded(finalMediaItems);
mMediaItemList.clear();
mMediaItemList.addAll(finalMediaItems);
}
@@ -760,6 +761,13 @@
new MediaItem(title, MediaItem.MediaItemType.TYPE_GROUP_DIVIDER));
}
+ private void attachConnectNewDeviceItemIfNeeded(List<MediaItem> mediaItems) {
+ // Attach "Connect a device" item only when current output is not remote and not a group
+ if (!isCurrentConnectedDeviceRemote() && getSelectedMediaDevice().size() == 1) {
+ mediaItems.add(new MediaItem());
+ }
+ }
+
private void attachRangeInfo(List<MediaDevice> devices) {
for (MediaDevice mediaDevice : devices) {
if (mNearbyDeviceInfoMap.containsKey(mediaDevice.getId())) {
@@ -1251,7 +1259,8 @@
return null;
}
- private final MediaController.Callback mCb = new MediaController.Callback() {
+ @VisibleForTesting
+ final MediaController.Callback mCb = new MediaController.Callback() {
@Override
public void onMetadataChanged(MediaMetadata metadata) {
mCallback.onMediaChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
index 96e9756..91bb7898 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
@@ -60,15 +60,21 @@
private const val MIN_DURATION_COMMITTED_ANIMATION = 80L
private const val MIN_DURATION_COMMITTED_AFTER_FLING_ANIMATION = 120L
private const val MIN_DURATION_INACTIVE_BEFORE_FLUNG_ANIMATION = 50L
-private const val MIN_DURATION_INACTIVE_BEFORE_ACTIVE_ANIMATION = 80L
+private const val MIN_DURATION_INACTIVE_BEFORE_ACTIVE_ANIMATION = 160F
+private const val MIN_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION = 10F
+internal const val MAX_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION = 100F
private const val MIN_DURATION_FLING_ANIMATION = 160L
private const val MIN_DURATION_ENTRY_TO_ACTIVE_CONSIDERED_AS_FLING = 100L
private const val MIN_DURATION_INACTIVE_TO_ACTIVE_CONSIDERED_AS_FLING = 400L
private const val POP_ON_FLING_DELAY = 60L
-private const val POP_ON_FLING_SCALE = 2f
-private const val POP_ON_COMMITTED_SCALE = 3f
+private const val POP_ON_FLING_VELOCITY = 2f
+private const val POP_ON_COMMITTED_VELOCITY = 3f
+private const val POP_ON_ACTIVE_MAX_VELOCITY = 2.5f
+private const val POP_ON_ACTIVE_MIN_VELOCITY = 4.5f
+private const val POP_ON_INACTIVE_MAX_VELOCITY = -1.05f
+private const val POP_ON_INACTIVE_MIN_VELOCITY = -1.5f
internal val VIBRATE_ACTIVATED_EFFECT =
VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)
@@ -156,13 +162,22 @@
private var gestureEntryTime = 0L
private var gestureInactiveTime = 0L
- private var gesturePastActiveThresholdWhileInactiveTime = 0L
private val elapsedTimeSinceInactive
get() = SystemClock.uptimeMillis() - gestureInactiveTime
private val elapsedTimeSinceEntry
get() = SystemClock.uptimeMillis() - gestureEntryTime
+
+ private var pastThresholdWhileEntryOrInactiveTime = 0L
+ private var entryToActiveDelay = 0F
+ private val entryToActiveDelayCalculation = {
+ convertVelocityToAnimationFactor(
+ valueOnFastVelocity = MIN_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION,
+ valueOnSlowVelocity = MAX_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION,
+ )
+ }
+
// Whether the current gesture has moved a sufficiently large amount,
// so that we can unambiguously start showing the ENTRY animation
private var hasPassedDragSlop = false
@@ -306,7 +321,9 @@
MotionEvent.ACTION_UP -> {
when (currentState) {
GestureState.ENTRY -> {
- if (isFlungAwayFromEdge(endX = event.x)) {
+ if (isFlungAwayFromEdge(endX = event.x) ||
+ previousXTranslation > params.staticTriggerThreshold
+ ) {
updateArrowState(GestureState.ACTIVE)
updateArrowState(GestureState.FLUNG)
} else {
@@ -394,12 +411,29 @@
}
private fun updateArrowStateOnMove(yTranslation: Float, xTranslation: Float) {
-
val isWithinYActivationThreshold = xTranslation * 2 >= yTranslation
-
+ val isPastStaticThreshold = xTranslation > params.staticTriggerThreshold
when (currentState) {
GestureState.ENTRY -> {
- if (xTranslation > params.staticTriggerThreshold) {
+ if (isPastThresholdToActive(
+ isPastThreshold = isPastStaticThreshold,
+ dynamicDelay = entryToActiveDelayCalculation
+ )
+ ) {
+ updateArrowState(GestureState.ACTIVE)
+ }
+ }
+ GestureState.INACTIVE -> {
+ val isPastDynamicReactivationThreshold =
+ totalTouchDeltaInactive >= params.reactivationTriggerThreshold
+
+ if (isPastThresholdToActive(
+ isPastThreshold = isPastStaticThreshold &&
+ isPastDynamicReactivationThreshold &&
+ isWithinYActivationThreshold,
+ delay = MIN_DURATION_INACTIVE_BEFORE_ACTIVE_ANIMATION
+ )
+ ) {
updateArrowState(GestureState.ACTIVE)
}
}
@@ -408,43 +442,12 @@
totalTouchDeltaActive <= params.deactivationTriggerThreshold
val isMinDurationElapsed =
elapsedTimeSinceEntry > MIN_DURATION_ACTIVE_BEFORE_INACTIVE_ANIMATION
-
- if (isMinDurationElapsed && (!isWithinYActivationThreshold ||
- isPastDynamicDeactivationThreshold)
- ) {
+ val isPastAllThresholds =
+ !isWithinYActivationThreshold || isPastDynamicDeactivationThreshold
+ if (isPastAllThresholds && isMinDurationElapsed) {
updateArrowState(GestureState.INACTIVE)
}
}
- GestureState.INACTIVE -> {
- val isPastStaticThreshold =
- xTranslation > params.staticTriggerThreshold
- val isPastDynamicReactivationThreshold =
- totalTouchDeltaInactive >= params.reactivationTriggerThreshold
- val isPastAllThresholds = isPastStaticThreshold &&
- isPastDynamicReactivationThreshold &&
- isWithinYActivationThreshold
- val isPastAllThresholdsForFirstTime = isPastAllThresholds &&
- gesturePastActiveThresholdWhileInactiveTime == 0L
-
- gesturePastActiveThresholdWhileInactiveTime = when {
- isPastAllThresholdsForFirstTime -> SystemClock.uptimeMillis()
- isPastAllThresholds -> gesturePastActiveThresholdWhileInactiveTime
- else -> 0L
- }
-
- val elapsedTimePastAllThresholds =
- SystemClock.uptimeMillis() - gesturePastActiveThresholdWhileInactiveTime
-
- val isPastMinimumInactiveToActiveDuration =
- elapsedTimePastAllThresholds > MIN_DURATION_INACTIVE_BEFORE_ACTIVE_ANIMATION
-
- if (isPastAllThresholds && isPastMinimumInactiveToActiveDuration) {
- // The minimum duration adds the 'edge stickiness'
- // factor before pulling it off edge
- updateArrowState(GestureState.ACTIVE)
- }
- }
-
else -> {}
}
}
@@ -672,6 +675,28 @@
return flingDistance > minFlingDistance && isPastFlingVelocityThreshold
}
+ private fun isPastThresholdToActive(
+ isPastThreshold: Boolean,
+ delay: Float? = null,
+ dynamicDelay: () -> Float = { delay ?: 0F }
+ ): Boolean {
+ val resetValue = 0L
+ val isPastThresholdForFirstTime = pastThresholdWhileEntryOrInactiveTime == resetValue
+
+ if (!isPastThreshold) {
+ pastThresholdWhileEntryOrInactiveTime = resetValue
+ return false
+ }
+
+ if (isPastThresholdForFirstTime) {
+ pastThresholdWhileEntryOrInactiveTime = SystemClock.uptimeMillis()
+ entryToActiveDelay = dynamicDelay()
+ }
+ val timePastThreshold = SystemClock.uptimeMillis() - pastThresholdWhileEntryOrInactiveTime
+
+ return timePastThreshold > entryToActiveDelay
+ }
+
private fun playWithBackgroundWidthAnimation(
onEnd: DelayedOnAnimationEndListener,
delay: Long = 0L
@@ -886,33 +911,16 @@
}
GestureState.ACTIVE -> {
previousXTranslationOnActiveOffset = previousXTranslation
-
updateRestingArrowDimens()
-
vibratorHelper.cancel()
mainHandler.postDelayed(10L) {
vibratorHelper.vibrate(VIBRATE_ACTIVATED_EFFECT)
}
-
- val minimumPop = 2f
- val maximumPop = 4.5f
-
- when (previousState) {
- GestureState.ENTRY -> {
- val startingVelocity = convertVelocityToSpringStartingVelocity(
- valueOnFastVelocity = minimumPop,
- valueOnSlowVelocity = maximumPop,
- fastVelocityBound = 1f,
- slowVelocityBound = 0.5f,
- )
- mView.popOffEdge(startingVelocity)
- }
- GestureState.INACTIVE -> {
- mView.popOffEdge(maximumPop)
- }
-
- else -> {}
- }
+ val startingVelocity = convertVelocityToAnimationFactor(
+ valueOnFastVelocity = POP_ON_ACTIVE_MAX_VELOCITY,
+ valueOnSlowVelocity = POP_ON_ACTIVE_MIN_VELOCITY,
+ )
+ mView.popOffEdge(startingVelocity)
}
GestureState.INACTIVE -> {
@@ -925,9 +933,9 @@
// so that gesture progress in this state is consistent regardless of entry
totalTouchDeltaInactive = params.deactivationTriggerThreshold
- val startingVelocity = convertVelocityToSpringStartingVelocity(
- valueOnFastVelocity = -1.05f,
- valueOnSlowVelocity = -1.50f
+ val startingVelocity = convertVelocityToAnimationFactor(
+ valueOnFastVelocity = POP_ON_INACTIVE_MAX_VELOCITY,
+ valueOnSlowVelocity = POP_ON_INACTIVE_MIN_VELOCITY
)
mView.popOffEdge(startingVelocity)
@@ -935,7 +943,9 @@
updateRestingArrowDimens()
}
GestureState.FLUNG -> {
- mainHandler.postDelayed(POP_ON_FLING_DELAY) { mView.popScale(POP_ON_FLING_SCALE) }
+ mainHandler.postDelayed(POP_ON_FLING_DELAY) {
+ mView.popScale(POP_ON_FLING_VELOCITY)
+ }
updateRestingArrowDimens()
mainHandler.postDelayed(onEndSetCommittedStateListener.runnable,
MIN_DURATION_FLING_ANIMATION)
@@ -951,7 +961,7 @@
mainHandler.postDelayed(onEndSetGoneStateListener.runnable,
MIN_DURATION_COMMITTED_AFTER_FLING_ANIMATION)
} else {
- mView.popScale(POP_ON_COMMITTED_SCALE)
+ mView.popScale(POP_ON_COMMITTED_VELOCITY)
mainHandler.postDelayed(onAlphaEndSetGoneStateListener.runnable,
MIN_DURATION_COMMITTED_ANIMATION)
}
@@ -968,11 +978,11 @@
}
}
- private fun convertVelocityToSpringStartingVelocity(
+ private fun convertVelocityToAnimationFactor(
valueOnFastVelocity: Float,
valueOnSlowVelocity: Float,
- fastVelocityBound: Float = 3f,
- slowVelocityBound: Float = 0f,
+ fastVelocityBound: Float = 1f,
+ slowVelocityBound: Float = 0.5f,
): Float {
val factor = velocityTracker?.run {
computeCurrentVelocity(PX_PER_MS)
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 41e3e6d..9a1efc3 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -15,6 +15,8 @@
*/
package com.android.systemui.navigationbar.gestural;
+import static android.view.InputDevice.SOURCE_MOUSE;
+import static android.view.InputDevice.SOURCE_TOUCHPAD;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION;
import static com.android.systemui.classifier.Classifier.BACK_GESTURE;
@@ -937,10 +939,12 @@
mMLResults = 0;
mLogGesture = false;
mInRejectedExclusion = false;
- boolean isWithinInsets = isWithinInsets((int) ev.getX(), (int) ev.getY());
// Trackpad back gestures don't have zones, so we don't need to check if the down event
- // is within insets.
+ // is within insets. Also we don't allow back for button press from the trackpad, and
+ // yet we do with a mouse.
+ boolean isWithinInsets = isWithinInsets((int) ev.getX(), (int) ev.getY());
mAllowGesture = !mDisabledForQuickstep && mIsBackGestureAllowed
+ && !isButtonPressFromTrackpad(ev)
&& (isTrackpadMultiFingerSwipe || isWithinInsets)
&& !mGestureBlockingActivityRunning
&& !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
@@ -1047,6 +1051,11 @@
mProtoTracer.scheduleFrameUpdate();
}
+ private boolean isButtonPressFromTrackpad(MotionEvent ev) {
+ int sources = InputManager.getInstance().getInputDevice(ev.getDeviceId()).getSources();
+ return (sources & (SOURCE_MOUSE | SOURCE_TOUCHPAD)) == sources && ev.getButtonState() != 0;
+ }
+
private void dispatchToBackAnimation(MotionEvent event) {
if (mBackAnimation != null) {
mVelocityTracker.addMovement(event);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
index 876c74a..182ece7 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
@@ -153,7 +153,7 @@
horizontalTranslation = getDimen(R.dimen.navigation_edge_entry_margin),
scale = getDimenFloat(R.dimen.navigation_edge_entry_scale),
scalePivotX = getDimen(R.dimen.navigation_edge_pre_threshold_background_width),
- horizontalTranslationSpring = createSpring(500f, 0.76f),
+ horizontalTranslationSpring = createSpring(800f, 0.76f),
verticalTranslationSpring = createSpring(30000f, 1f),
scaleSpring = createSpring(120f, 0.8f),
arrowDimens = ArrowDimens(
@@ -205,8 +205,8 @@
activeIndicator = BackIndicatorDimens(
horizontalTranslation = getDimen(R.dimen.navigation_edge_active_margin),
scale = getDimenFloat(R.dimen.navigation_edge_active_scale),
- horizontalTranslationSpring = createSpring(1000f, 0.7f),
- scaleSpring = createSpring(450f, 0.39f),
+ horizontalTranslationSpring = createSpring(1000f, 0.8f),
+ scaleSpring = createSpring(325f, 0.55f),
scalePivotX = getDimen(R.dimen.navigation_edge_active_background_width),
arrowDimens = ArrowDimens(
length = getDimen(R.dimen.navigation_edge_active_arrow_length),
@@ -253,7 +253,7 @@
getDimen(R.dimen.navigation_edge_pre_threshold_edge_corners),
farCornerRadius =
getDimen(R.dimen.navigation_edge_pre_threshold_far_corners),
- widthSpring = createSpring(400f, 0.65f),
+ widthSpring = createSpring(650f, 1f),
heightSpring = createSpring(1500f, 0.45f),
farCornerRadiusSpring = createSpring(300f, 1f),
edgeCornerRadiusSpring = createSpring(250f, 0.5f),
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index 8aec0c6..d4052f5 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -42,7 +42,6 @@
import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
import com.android.systemui.notetask.NoteTaskRoleManagerExt.createNoteShortcutInfoAsUser
import com.android.systemui.notetask.NoteTaskRoleManagerExt.getDefaultRoleHolderAsUser
-import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity
import com.android.systemui.settings.UserTracker
import com.android.systemui.shared.system.ActivityManagerKt.isInForeground
@@ -231,8 +230,6 @@
* Widget Picker to all users.
*/
fun setNoteTaskShortcutEnabled(value: Boolean, user: UserHandle) {
- val componentName = ComponentName(context, CreateNoteTaskShortcutActivity::class.java)
-
val enabledState =
if (value) {
PackageManager.COMPONENT_ENABLED_STATE_ENABLED
@@ -249,8 +246,9 @@
} else {
context.createContextAsUser(user, /* flags= */ 0)
}
+
userContext.packageManager.setComponentEnabledSetting(
- componentName,
+ SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT,
enabledState,
PackageManager.DONT_KILL_APP,
)
@@ -298,6 +296,19 @@
companion object {
val TAG = NoteTaskController::class.simpleName.orEmpty()
+ /**
+ * IMPORTANT! The shortcut package name and class should be synchronized with Settings:
+ * [com.android.settings.notetask.shortcut.CreateNoteTaskShortcutActivity].
+ *
+ * Changing the package name or class is a breaking change.
+ */
+ @VisibleForTesting
+ val SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT =
+ ComponentName(
+ "com.android.settings",
+ "com.android.settings.notetask.shortcut.CreateNoteTaskShortcutActivity",
+ )
+
const val SHORTCUT_ID = "note_task_shortcut_id"
/**
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
index a166393..2c62ffd 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
@@ -24,7 +24,6 @@
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceModule
-import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity
import dagger.Binds
@@ -46,9 +45,6 @@
@[Binds IntoMap ClassKey(LaunchNoteTaskManagedProfileProxyActivity::class)]
fun LaunchNoteTaskManagedProfileProxyActivity.bindNoteTaskLauncherProxyActivity(): Activity
- @[Binds IntoMap ClassKey(CreateNoteTaskShortcutActivity::class)]
- fun CreateNoteTaskShortcutActivity.bindNoteTaskShortcutActivity(): Activity
-
companion object {
@[Provides NoteTaskEnabledKey]
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
deleted file mode 100644
index 0cfb0a5..0000000
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:OptIn(InternalNoteTaskApi::class)
-
-package com.android.systemui.notetask.shortcut
-
-import android.app.Activity
-import android.app.role.RoleManager
-import android.content.pm.ShortcutManager
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import com.android.systemui.notetask.InternalNoteTaskApi
-import com.android.systemui.notetask.NoteTaskRoleManagerExt.createNoteShortcutInfoAsUser
-import javax.inject.Inject
-
-/**
- * Activity responsible for create a shortcut for notes action. If the shortcut is enabled, a new
- * shortcut will appear in the widget picker. If the shortcut is selected, the Activity here will be
- * launched, creating a new shortcut for [CreateNoteTaskShortcutActivity], and will finish.
- *
- * @see <a
- * href="https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#custom-pinned">Creating
- * a custom shortcut activity</a>
- */
-class CreateNoteTaskShortcutActivity
-@Inject
-constructor(
- private val roleManager: RoleManager,
- private val shortcutManager: ShortcutManager,
-) : ComponentActivity() {
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- val shortcutInfo = roleManager.createNoteShortcutInfoAsUser(context = this, user)
- val shortcutIntent = shortcutManager.createShortcutResultIntent(shortcutInfo)
- setResult(Activity.RESULT_OK, shortcutIntent)
-
- finish()
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt b/packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
index 6f645b5..995c6a4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
@@ -26,7 +26,9 @@
import javax.inject.Inject
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.shade.ShadeModule.Companion.SHADE_HEADER
import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import javax.inject.Named
interface ChipVisibilityListener {
fun onChipVisibilityRefreshed(visible: Boolean)
@@ -45,10 +47,10 @@
class HeaderPrivacyIconsController @Inject constructor(
private val privacyItemController: PrivacyItemController,
private val uiEventLogger: UiEventLogger,
- private val privacyChip: OngoingPrivacyChip,
+ @Named(SHADE_HEADER) private val privacyChip: OngoingPrivacyChip,
private val privacyDialogController: PrivacyDialogController,
private val privacyLogger: PrivacyLogger,
- private val iconContainer: StatusIconContainer,
+ @Named(SHADE_HEADER) private val iconContainer: StatusIconContainer,
private val permissionManager: PermissionManager,
@Background private val backgroundExecutor: Executor,
@Main private val uiExecutor: Executor,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java
index 0bce1f7..b70b94b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java
@@ -719,7 +719,8 @@
String name = vpnName != null ? vpnName : vpnNameWorkProfile;
String namedVp = mDpm.getResources().getString(
QS_DIALOG_MANAGEMENT_NAMED_VPN,
- () -> mContext.getString(R.string.monitoring_description_named_vpn, name),
+ () -> mContext.getString(
+ R.string.monitoring_description_managed_device_named_vpn, name),
name);
message.append(namedVp);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 4a31998..b806683 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -385,6 +385,11 @@
super.onInitializeAccessibilityNodeInfo(info)
// Clear selected state so it is not announce by talkback.
info.isSelected = false
+ info.text = if (TextUtils.isEmpty(secondaryLabel.text)) {
+ "${label.text}"
+ } else {
+ "${label.text}, ${secondaryLabel.text}"
+ }
if (lastDisabledByPolicy) {
info.addAction(
AccessibilityNodeInfo.AccessibilityAction(
@@ -402,12 +407,6 @@
accessibilityClass
}
if (Switch::class.java.name == accessibilityClass) {
- val label = resources.getString(
- if (tileState) R.string.switch_bar_on else R.string.switch_bar_off)
- // Set the text here for tests in
- // android.platform.test.scenario.sysui.quicksettings. Can be removed when
- // UiObject2 has a new getStateDescription() API and tests are updated.
- info.text = label
info.isChecked = tileState
info.isCheckable = true
if (isLongClickable) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
index f16f0dc..ffe5489 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -458,13 +458,28 @@
getTileSpec(), mLastTileState, arg == null ? "null" : arg.toString());
if (arg instanceof CellularCallbackInfo) {
mLastTileState = LAST_STATE_CELLULAR;
- handleUpdateCellularState(state, arg);
+ CellularCallbackInfo cb = (CellularCallbackInfo) arg;
+ CellularCallbackInfo cellularInfo = new CellularCallbackInfo();
+ synchronized (cb) {
+ cb.copyTo(cellularInfo);
+ }
+ handleUpdateCellularState(state, cellularInfo);
} else if (arg instanceof WifiCallbackInfo) {
mLastTileState = LAST_STATE_WIFI;
- handleUpdateWifiState(state, arg);
+ WifiCallbackInfo cb = (WifiCallbackInfo) arg;
+ WifiCallbackInfo wifiInfo = new WifiCallbackInfo();
+ synchronized (cb) {
+ cb.copyTo(wifiInfo);
+ }
+ handleUpdateWifiState(state, wifiInfo);
} else if (arg instanceof EthernetCallbackInfo) {
mLastTileState = LAST_STATE_ETHERNET;
- handleUpdateEthernetState(state, arg);
+ EthernetCallbackInfo cb = (EthernetCallbackInfo) arg;
+ EthernetCallbackInfo ethernetInfo = new EthernetCallbackInfo();
+ synchronized (cb) {
+ cb.copyTo(ethernetInfo);
+ }
+ handleUpdateEthernetState(state, ethernetInfo);
} else {
// handleUpdateState will be triggered when user expands the QuickSetting panel with
// arg = null, in this case the last updated CellularCallbackInfo or WifiCallbackInfo
@@ -476,11 +491,11 @@
}
handleUpdateCellularState(state, cellularInfo);
} else if (mLastTileState == LAST_STATE_WIFI) {
- WifiCallbackInfo mifiInfo = new WifiCallbackInfo();
+ WifiCallbackInfo wifiInfo = new WifiCallbackInfo();
synchronized (mSignalCallback.mWifiInfo) {
- mSignalCallback.mWifiInfo.copyTo(mifiInfo);
+ mSignalCallback.mWifiInfo.copyTo(wifiInfo);
}
- handleUpdateWifiState(state, mifiInfo);
+ handleUpdateWifiState(state, wifiInfo);
} else if (mLastTileState == LAST_STATE_ETHERNET) {
EthernetCallbackInfo ethernetInfo = new EthernetCallbackInfo();
synchronized (mSignalCallback.mEthernetInfo) {
@@ -667,11 +682,16 @@
}
@Override
+ @NonNull
public Drawable getDrawable(Context context) {
SignalDrawable d = new SignalDrawable(context);
d.setLevel(getState());
return d;
}
+ @Override
+ public String toString() {
+ return String.format("SignalIcon[mState=0x%08x]", mState);
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/BaseScreenSharePermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/BaseScreenSharePermissionDialog.kt
index f63bf07..b340043 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/BaseScreenSharePermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/BaseScreenSharePermissionDialog.kt
@@ -57,8 +57,8 @@
setContentView(R.layout.screen_share_dialog)
dialogTitle = findViewById(R.id.screen_share_dialog_title)
warning = findViewById(R.id.text_warning)
- startButton = findViewById(R.id.button_start)
- cancelButton = findViewById(R.id.button_cancel)
+ startButton = findViewById(android.R.id.button1)
+ cancelButton = findViewById(android.R.id.button2)
updateIcon()
initScreenShareOptions()
createOptionsView(getOptionsViewLayoutId())
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/MediaProjectionPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/MediaProjectionPermissionDialog.kt
index 201557c..f4f5f66 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/MediaProjectionPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/MediaProjectionPermissionDialog.kt
@@ -28,12 +28,14 @@
) : BaseScreenSharePermissionDialog(context, createOptionList(appName), appName) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ // TODO(b/270018943): Handle the case of System sharing (not recording nor casting)
if (appName == null) {
- setDialogTitle(R.string.media_projection_permission_dialog_system_service_title)
+ setDialogTitle(R.string.media_projection_entry_cast_permission_dialog_title)
+ setStartButtonText(R.string.media_projection_entry_cast_permission_dialog_continue)
} else {
- setDialogTitle(R.string.media_projection_permission_dialog_title)
+ setDialogTitle(R.string.media_projection_entry_app_permission_dialog_title)
+ setStartButtonText(R.string.media_projection_entry_app_permission_dialog_continue)
}
- setStartButtonText(R.string.media_projection_permission_dialog_continue)
setStartButtonOnClickListener {
// Note that it is important to run this callback before dismissing, so that the
// callback can disable the dialog exit animation if it wants to.
@@ -50,26 +52,26 @@
private fun createOptionList(appName: String?): List<ScreenShareOption> {
val singleAppWarningText =
if (appName == null) {
- R.string.media_projection_permission_dialog_system_service_warning_single_app
+ R.string.media_projection_entry_cast_permission_dialog_warning_single_app
} else {
- R.string.media_projection_permission_dialog_warning_single_app
+ R.string.media_projection_entry_app_permission_dialog_warning_single_app
}
val entireScreenWarningText =
if (appName == null) {
- R.string.media_projection_permission_dialog_system_service_warning_entire_screen
+ R.string.media_projection_entry_cast_permission_dialog_warning_entire_screen
} else {
- R.string.media_projection_permission_dialog_warning_entire_screen
+ R.string.media_projection_entry_app_permission_dialog_warning_entire_screen
}
return listOf(
ScreenShareOption(
mode = ENTIRE_SCREEN,
- spinnerText = R.string.media_projection_permission_dialog_option_entire_screen,
+ spinnerText = R.string.screen_share_permission_dialog_option_entire_screen,
warningText = entireScreenWarningText
),
ScreenShareOption(
mode = SINGLE_APP,
- spinnerText = R.string.media_projection_permission_dialog_option_single_app,
+ spinnerText = R.string.screen_share_permission_dialog_option_single_app,
warningText = singleAppWarningText
)
)
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index 4349bd7..69008cc 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -262,7 +262,7 @@
Resources res = getResources();
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
- getString(R.string.screenrecord_name),
+ getString(R.string.screenrecord_title),
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(getString(R.string.screenrecord_channel_description));
channel.enableVibration(true);
@@ -270,7 +270,7 @@
Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
- res.getString(R.string.screenrecord_name));
+ res.getString(R.string.screenrecord_title));
String notificationTitle = res.getString(R.string.screenrecord_start_error);
Notification.Builder builder = new Notification.Builder(this, CHANNEL_ID)
@@ -290,7 +290,7 @@
Resources res = getResources();
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
- getString(R.string.screenrecord_name),
+ getString(R.string.screenrecord_title),
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(getString(R.string.screenrecord_channel_description));
channel.enableVibration(true);
@@ -298,7 +298,7 @@
Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
- res.getString(R.string.screenrecord_name));
+ res.getString(R.string.screenrecord_title));
String notificationTitle = mAudioSource == ScreenRecordingAudioSource.NONE
? res.getString(R.string.screenrecord_ongoing_screen_only)
@@ -335,7 +335,7 @@
Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
- res.getString(R.string.screenrecord_name));
+ res.getString(R.string.screenrecord_title));
Notification.Builder builder = new Notification.Builder(getApplicationContext(), CHANNEL_ID)
.setContentTitle(notificationTitle)
@@ -365,7 +365,7 @@
Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
- getResources().getString(R.string.screenrecord_name));
+ getResources().getString(R.string.screenrecord_title));
Notification.Builder builder = new Notification.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_screenrecord)
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
index efa45a4..2a21aaa 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
@@ -100,7 +100,7 @@
window.addPrivateFlags(WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS);
window.setGravity(Gravity.CENTER);
- setTitle(R.string.screenrecord_name);
+ setTitle(R.string.screenrecord_title);
setContentView(R.layout.screen_record_dialog);
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
index 30509e2..bfaf3d0 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
@@ -62,8 +62,8 @@
private lateinit var options: Spinner
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setDialogTitle(R.string.screenrecord_start_label)
- setStartButtonText(R.string.screenrecord_start_recording)
+ setDialogTitle(R.string.screenrecord_permission_dialog_title)
+ setStartButtonText(R.string.screenrecord_permission_dialog_continue)
setStartButtonOnClickListener { v: View? ->
onStartRecordingClicked?.run()
if (selectedScreenShareOption.mode == ENTIRE_SCREEN) {
@@ -186,13 +186,13 @@
return listOf(
ScreenShareOption(
ENTIRE_SCREEN,
- R.string.screenrecord_option_entire_screen,
- R.string.screenrecord_warning_entire_screen
+ R.string.screen_share_permission_dialog_option_entire_screen,
+ R.string.screenrecord_permission_dialog_warning_entire_screen
),
ScreenShareOption(
SINGLE_APP,
- R.string.screenrecord_option_single_app,
- R.string.screenrecord_warning_single_app
+ R.string.screen_share_permission_dialog_option_single_app,
+ R.string.screenrecord_permission_dialog_warning_single_app
)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
index aa8e2c0..187019a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
@@ -154,5 +154,5 @@
}
}
- override fun onAnimationCancelled(isKeyguardOccluded: Boolean) {}
+ override fun onAnimationCancelled() {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index c9d1da38..77a65b2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -150,7 +150,7 @@
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
index b3d31f2..7e0f504 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
@@ -19,12 +19,12 @@
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintSet
import com.android.systemui.R
-import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent
+import com.android.systemui.dagger.SysUISingleton
/**
* Standard implementation of [CombinedShadeHeadersConstraintManager].
*/
-@CentralSurfacesComponent.CentralSurfacesScope
+@SysUISingleton
object CombinedShadeHeadersConstraintManagerImpl : CombinedShadeHeadersConstraintManager {
override fun privacyChipVisibilityConstraints(visible: Boolean): ConstraintsChanges {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index bfed664..92c9a80 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -70,6 +70,7 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.shade.data.repository.ShadeRepository;
import com.android.systemui.shade.transition.ShadeTransitionController;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
@@ -90,6 +91,7 @@
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
+import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.LargeScreenUtils;
@@ -136,8 +138,10 @@
private final LockscreenGestureLogger mLockscreenGestureLogger;
private final ShadeLogger mShadeLog;
private final KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor;
+ private final CastController mCastController;
private final FeatureFlags mFeatureFlags;
private final InteractionJankMonitor mInteractionJankMonitor;
+ private final ShadeRepository mShadeRepository;
private final FalsingManager mFalsingManager;
private final AccessibilityManager mAccessibilityManager;
private final MetricsLogger mMetricsLogger;
@@ -324,7 +328,9 @@
FeatureFlags featureFlags,
InteractionJankMonitor interactionJankMonitor,
ShadeLogger shadeLog,
- KeyguardFaceAuthInteractor keyguardFaceAuthInteractor
+ KeyguardFaceAuthInteractor keyguardFaceAuthInteractor,
+ ShadeRepository shadeRepository,
+ CastController castController
) {
mPanelViewControllerLazy = panelViewControllerLazy;
mPanelView = panelView;
@@ -365,8 +371,10 @@
mMetricsLogger = metricsLogger;
mShadeLog = shadeLog;
mKeyguardFaceAuthInteractor = keyguardFaceAuthInteractor;
+ mCastController = castController;
mFeatureFlags = featureFlags;
mInteractionJankMonitor = interactionJankMonitor;
+ mShadeRepository = shadeRepository;
mLockscreenShadeTransitionController.addCallback(new LockscreenShadeTransitionCallback());
}
@@ -1005,6 +1013,7 @@
mDepthController.setQsPanelExpansion(qsExpansionFraction);
mStatusBarKeyguardViewManager.setQsExpansion(qsExpansionFraction);
+ mShadeRepository.setQsExpansion(qsExpansionFraction);
// TODO (b/265193930): remove dependency on NPVC
float shadeExpandedFraction = mBarState == KEYGUARD
@@ -1190,7 +1199,9 @@
mLastClipBounds.set(left, top, right, bottom);
if (mIsFullWidth) {
clipStatusView = qsVisible;
- float screenCornerRadius = mRecordingController.isRecording() ? 0 : mScreenCornerRadius;
+ float screenCornerRadius =
+ mRecordingController.isRecording() || mCastController.hasConnectedCastDevice()
+ ? 0 : mScreenCornerRadius;
radius = (int) MathUtils.lerp(screenCornerRadius, mScrimCornerRadius,
Math.min(top / (float) mScrimCornerRadius, 1f));
mScrimController.setNotificationBottomRadius(radius);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
index f4b1cc5..20313c3 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
@@ -17,6 +17,8 @@
package com.android.systemui.shade
import android.annotation.IntDef
+import android.os.Trace
+import android.os.Trace.TRACE_TAG_APP as TRACE_TAG
import android.util.Log
import androidx.annotation.FloatRange
import com.android.systemui.dagger.SysUISingleton
@@ -153,6 +155,14 @@
if (fullyClosed) " fullyClosed" else ""
)
+ if (Trace.isTagEnabled(TRACE_TAG)) {
+ Trace.traceCounter(TRACE_TAG, "panel_expansion", (fraction * 100).toInt())
+ if (state != oldState) {
+ Trace.asyncTraceForTrackEnd(TRACE_TAG, TRACK_NAME, 0)
+ Trace.asyncTraceForTrackBegin(TRACE_TAG, TRACK_NAME, state.panelStateToString(), 0)
+ }
+ }
+
val expansionChangeEvent =
ShadeExpansionChangeEvent(fraction, expanded, tracking, dragDownPxAmount)
expansionListeners.forEach { it.onPanelExpansionChanged(expansionChangeEvent) }
@@ -211,6 +221,10 @@
if (!DEBUG) return
Log.v(TAG, msg)
}
+
+ companion object {
+ private const val TRACK_NAME = "ShadeExpansionState"
+ }
}
/** Enum for the current state of the panel. */
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index f0815e9..86ae4ec 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -41,6 +41,7 @@
import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
+import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.demomode.DemoMode
import com.android.systemui.demomode.DemoModeController
import com.android.systemui.dump.DumpManager
@@ -52,14 +53,13 @@
import com.android.systemui.shade.ShadeHeaderController.Companion.LARGE_SCREEN_HEADER_TRANSITION_ID
import com.android.systemui.shade.ShadeHeaderController.Companion.QQS_HEADER_CONSTRAINT
import com.android.systemui.shade.ShadeHeaderController.Companion.QS_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeModule.Companion.SHADE_HEADER
import com.android.systemui.shade.carrier.ShadeCarrierGroup
import com.android.systemui.shade.carrier.ShadeCarrierGroupController
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.phone.StatusBarIconController
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.StatusIconContainer
-import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
-import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SHADE_HEADER
import com.android.systemui.statusbar.policy.Clock
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.NextAlarmController
@@ -79,7 +79,7 @@
* * [LARGE_SCREEN_HEADER_TRANSITION_ID]: [LARGE_SCREEN_HEADER_CONSTRAINT] for all other
* configurations
*/
-@CentralSurfacesScope
+@SysUISingleton
class ShadeHeaderController
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
index 9cd8c54..b7551cf 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
@@ -16,21 +16,36 @@
package com.android.systemui.shade
+import android.content.ContentResolver
+import android.os.Handler
import android.view.LayoutInflater
+import android.view.ViewStub
+import androidx.constraintlayout.motion.widget.MotionLayout
import com.android.keyguard.LockIconView
import com.android.systemui.CoreStartable
import com.android.systemui.R
+import com.android.systemui.battery.BatteryMeterView
+import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.biometrics.AuthRippleController
import com.android.systemui.biometrics.AuthRippleView
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.privacy.OngoingPrivacyChip
+import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
+import com.android.systemui.statusbar.phone.StatusIconContainer
import com.android.systemui.statusbar.phone.TapAgainView
+import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.tuner.TunerService
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
+import javax.inject.Named
/** Module for classes related to the notification shade. */
@Module
@@ -42,6 +57,8 @@
abstract fun bindAuthRippleController(controller: AuthRippleController): CoreStartable
companion object {
+ const val SHADE_HEADER = "large_screen_shade_header"
+
@Provides
@SysUISingleton
// TODO(b/277762009): Do something similar to
@@ -109,5 +126,75 @@
): TapAgainView {
return notificationPanelView.findViewById(R.id.shade_falsing_tap_again)
}
+
+ // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
+ @Provides
+ @SysUISingleton
+ @Named(SHADE_HEADER)
+ fun providesShadeHeaderView(
+ notificationShadeWindowView: NotificationShadeWindowView,
+ ): MotionLayout {
+ val stub = notificationShadeWindowView.findViewById<ViewStub>(R.id.qs_header_stub)
+ val layoutId = R.layout.combined_qs_header
+ stub.layoutResource = layoutId
+ return stub.inflate() as MotionLayout
+ }
+
+ @Provides
+ @SysUISingleton
+ fun providesCombinedShadeHeadersConstraintManager(): CombinedShadeHeadersConstraintManager {
+ return CombinedShadeHeadersConstraintManagerImpl
+ }
+
+ // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
+ @Provides
+ @SysUISingleton
+ @Named(SHADE_HEADER)
+ fun providesBatteryMeterView(@Named(SHADE_HEADER) view: MotionLayout): BatteryMeterView {
+ return view.findViewById(R.id.batteryRemainingIcon)
+ }
+
+ @Provides
+ @SysUISingleton
+ @Named(SHADE_HEADER)
+ fun providesBatteryMeterViewController(
+ @Named(SHADE_HEADER) batteryMeterView: BatteryMeterView,
+ userTracker: UserTracker,
+ configurationController: ConfigurationController,
+ tunerService: TunerService,
+ @Main mainHandler: Handler,
+ contentResolver: ContentResolver,
+ featureFlags: FeatureFlags,
+ batteryController: BatteryController,
+ ): BatteryMeterViewController {
+ return BatteryMeterViewController(
+ batteryMeterView,
+ userTracker,
+ configurationController,
+ tunerService,
+ mainHandler,
+ contentResolver,
+ featureFlags,
+ batteryController,
+ )
+ }
+
+ @Provides
+ @SysUISingleton
+ @Named(SHADE_HEADER)
+ fun providesOngoingPrivacyChip(
+ @Named(SHADE_HEADER) header: MotionLayout,
+ ): OngoingPrivacyChip {
+ return header.findViewById(R.id.privacy_chip)
+ }
+
+ @Provides
+ @SysUISingleton
+ @Named(SHADE_HEADER)
+ fun providesStatusIconContainer(
+ @Named(SHADE_HEADER) header: MotionLayout,
+ ): StatusIconContainer {
+ return header.findViewById(R.id.statusIcons)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
index bf7a2be..44c8e48 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
@@ -25,11 +25,23 @@
import javax.inject.Inject
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
interface ShadeRepository {
/** ShadeModel information regarding shade expansion events */
val shadeModel: Flow<ShadeModel>
+
+ /** Amount qs has expanded. Quick Settings can be expanded without the full shade expansion. */
+ val qsExpansion: StateFlow<Float>
+
+ /** Amount shade has expanded with regard to the UDFPS location */
+ val udfpsTransitionToFullShadeProgress: StateFlow<Float>
+
+ fun setQsExpansion(qsExpansion: Float)
+ fun setUdfpsTransitionToFullShadeProgress(progress: Float)
}
/** Business logic for shade interactions */
@@ -62,6 +74,20 @@
}
.distinctUntilChanged()
+ private val _qsExpansion = MutableStateFlow(0f)
+ override val qsExpansion: StateFlow<Float> = _qsExpansion.asStateFlow()
+
+ private var _udfpsTransitionToFullShadeProgress = MutableStateFlow(0f)
+ override val udfpsTransitionToFullShadeProgress: StateFlow<Float> =
+ _udfpsTransitionToFullShadeProgress.asStateFlow()
+ override fun setQsExpansion(qsExpansion: Float) {
+ _qsExpansion.value = qsExpansion
+ }
+
+ override fun setUdfpsTransitionToFullShadeProgress(progress: Float) {
+ _udfpsTransitionToFullShadeProgress.value = progress
+ }
+
companion object {
private const val TAG = "ShadeRepository"
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LegacyNotificationShelfControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/LegacyNotificationShelfControllerImpl.java
index 4ef2063..dcd9dc3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LegacyNotificationShelfControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LegacyNotificationShelfControllerImpl.java
@@ -52,7 +52,6 @@
mActivatableNotificationViewController = activatableNotificationViewController;
mKeyguardBypassController = keyguardBypassController;
mStatusBarStateController = statusBarStateController;
- mView.useRoundnessSourceTypes(featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES));
mView.setSensitiveRevealAnimEndabled(featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM));
mOnAttachStateChangeListener = new View.OnAttachStateChangeListener() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index c5f64b0..7f016f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -32,6 +32,7 @@
import com.android.systemui.plugins.qs.QS
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.ShadeViewController
+import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
@@ -74,6 +75,7 @@
falsingManager: FalsingManager,
dumpManager: DumpManager,
qsTransitionControllerFactory: LockscreenShadeQsTransitionController.Factory,
+ private val shadeRepository: ShadeRepository,
) : Dumpable {
private var pulseHeight: Float = 0f
@get:VisibleForTesting
@@ -449,6 +451,7 @@
}
val udfpsProgress = MathUtils.saturate(dragDownAmount / udfpsTransitionDistance)
+ shadeRepository.setUdfpsTransitionToFullShadeProgress(udfpsProgress)
udfpsKeyguardViewController?.setTransitionToFullShadeProgress(udfpsProgress)
val statusBarProgress = MathUtils.saturate(dragDownAmount / statusBarTransitionDistance)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 7eb63da..49c7950 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -44,7 +44,6 @@
import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
-import com.android.systemui.statusbar.notification.LegacySourceType;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -128,13 +127,6 @@
setClipToPadding(false);
mShelfIcons.setIsStaticLayout(false);
requestRoundness(/* top = */ 1f, /* bottom = */ 1f, BASE_VALUE, /* animate = */ false);
-
- if (!mUseRoundnessSourceTypes) {
- // Setting this to first in section to get the clipping to the top roundness correct.
- // This value determines the way we are clipping to the top roundness of the overall
- // shade
- setFirstInSection(true);
- }
updateResources();
}
@@ -569,17 +561,8 @@
* mAmbientState.getExpansionFraction();
final float cornerAnimationTop = shelfStart - cornerAnimationDistance;
- final SourceType sourceType;
- if (mUseRoundnessSourceTypes) {
- sourceType = SHELF_SCROLL;
- } else {
- sourceType = LegacySourceType.OnScroll;
- }
-
final float topValue;
- if (!mUseRoundnessSourceTypes && anv.isFirstInSection()) {
- topValue = 1f;
- } else if (viewStart >= cornerAnimationTop) {
+ if (viewStart >= cornerAnimationTop) {
// Round top corners within animation bounds
topValue = MathUtils.saturate(
(viewStart - cornerAnimationTop) / cornerAnimationDistance);
@@ -588,12 +571,10 @@
// Reset top and bottom corners outside of animation bounds.
topValue = 0f;
}
- anv.requestTopRoundness(topValue, sourceType, /* animate = */ false);
+ anv.requestTopRoundness(topValue, SHELF_SCROLL, /* animate = */ false);
final float bottomValue;
- if (!mUseRoundnessSourceTypes && anv.isLastInSection()) {
- bottomValue = 1f;
- } else if (viewEnd >= cornerAnimationTop) {
+ if (viewEnd >= cornerAnimationTop) {
// Round bottom corners within animation bounds
bottomValue = MathUtils.saturate(
(viewEnd - cornerAnimationTop) / cornerAnimationDistance);
@@ -602,7 +583,7 @@
// Reset top and bottom corners outside of animation bounds.
bottomValue = 0f;
}
- anv.requestBottomRoundness(bottomValue, sourceType, /* animate = */ false);
+ anv.requestBottomRoundness(bottomValue, SHELF_SCROLL, /* animate = */ false);
}
private boolean isViewAffectedBySwipe(ExpandableView expandableView) {
@@ -1100,15 +1081,6 @@
child.requestRoundnessReset(SHELF_SCROLL);
}
- /**
- * This method resets the OnScroll roundness of a view to 0f
- * <p>
- * Note: This should be the only class that handles roundness {@code SourceType.OnScroll}
- */
- public static void resetLegacyOnScrollRoundness(ExpandableView expandableView) {
- expandableView.requestRoundnessReset(LegacySourceType.OnScroll);
- }
-
@Override
public void dump(PrintWriter pwOriginal, String[] args) {
IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index 976924a..821a172 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -87,13 +87,8 @@
bypassController.isPulseExpanding = value
if (changed) {
if (value) {
- val topEntry = headsUpManager.topEntry
- topEntry?.let {
- roundnessManager.setTrackingHeadsUp(it.row)
- }
lockscreenShadeTransitionController.onPulseExpansionStarted()
} else {
- roundnessManager.setTrackingHeadsUp(null)
if (!leavingLockscreen) {
bypassController.maybePerformPendingUnlock()
pulseExpandAbortListener?.run()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
index 76ff97d..212f2c215 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
@@ -448,10 +448,3 @@
}
}
}
-
-@Deprecated("Use SourceType.from() instead", ReplaceWith("SourceType.from()"))
-enum class LegacySourceType : SourceType {
- DefaultValue,
- OnDismissAnimation,
- OnScroll,
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 766ad88..66d4c3a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -110,7 +110,6 @@
protected Point mTargetPoint;
private boolean mDismissed;
private boolean mRefocusOnDismiss;
- protected boolean mUseRoundnessSourceTypes;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -709,18 +708,10 @@
mTouchHandler = touchHandler;
}
- /**
- * Enable the support for rounded corner based on the SourceType
- * @param enabled true if is supported
- */
- public void useRoundnessSourceTypes(boolean enabled) {
- mUseRoundnessSourceTypes = enabled;
- }
-
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- if (mUseRoundnessSourceTypes && !mOnDetachResetRoundness.isEmpty()) {
+ if (!mOnDetachResetRoundness.isEmpty()) {
for (SourceType sourceType : mOnDetachResetRoundness) {
requestRoundnessReset(sourceType);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index e468a59..5978133 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -87,7 +87,6 @@
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
import com.android.systemui.statusbar.notification.FeedbackIcon;
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
-import com.android.systemui.statusbar.notification.LegacySourceType;
import com.android.systemui.statusbar.notification.NotificationFadeAware;
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController;
import com.android.systemui.statusbar.notification.NotificationUtils;
@@ -866,9 +865,6 @@
}
onAttachedChildrenCountChanged();
row.setIsChildInGroup(false, null);
- if (!mUseRoundnessSourceTypes) {
- row.requestBottomRoundness(0.0f, LegacySourceType.DefaultValue, /* animate = */ false);
- }
}
/**
@@ -884,10 +880,6 @@
if (child.keepInParentForDismissAnimation()) {
mChildrenContainer.removeNotification(child);
child.setIsChildInGroup(false, null);
- if (!mUseRoundnessSourceTypes) {
- LegacySourceType sourceType = LegacySourceType.DefaultValue;
- child.requestBottomRoundness(0f, sourceType, /* animate = */ false);
- }
child.setKeepInParentForDismissAnimation(false);
logKeepInParentChildDetached(child);
childCountChanged = true;
@@ -942,9 +934,7 @@
mNotificationParent.updateBackgroundForGroupState();
}
updateBackgroundClipping();
- if (mUseRoundnessSourceTypes) {
- updateBaseRoundness();
- }
+ updateBaseRoundness();
}
@Override
@@ -1054,15 +1044,13 @@
if (isAboveShelf() != wasAboveShelf) {
mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
}
- if (mUseRoundnessSourceTypes) {
- if (pinned) {
- // Should be animated if someone explicitly set it to 0 and the row is shown.
- boolean animated = mAnimatePinnedRoundness && isShown();
- requestRoundness(/* top = */ 1f, /* bottom = */ 1f, PINNED, animated);
- } else {
- requestRoundnessReset(PINNED);
- mAnimatePinnedRoundness = true;
- }
+ if (pinned) {
+ // Should be animated if someone explicitly set it to 0 and the row is shown.
+ boolean animated = mAnimatePinnedRoundness && isShown();
+ requestRoundness(/* top = */ 1f, /* bottom = */ 1f, PINNED, animated);
+ } else {
+ requestRoundnessReset(PINNED);
+ mAnimatePinnedRoundness = true;
}
}
@@ -1879,7 +1867,6 @@
mChildrenContainer.setIsLowPriority(mIsLowPriority);
mChildrenContainer.setContainingNotification(ExpandableNotificationRow.this);
mChildrenContainer.onNotificationUpdated();
- mChildrenContainer.useRoundnessSourceTypes(mUseRoundnessSourceTypes);
mTranslateableViews.add(mChildrenContainer);
});
@@ -2308,24 +2295,6 @@
mBackgroundNormal.setExpandAnimationSize(params.getWidth(), actualHeight);
}
- @Override
- public float getTopRoundness() {
- if (!mUseRoundnessSourceTypes && mExpandAnimationRunning) {
- return mTopRoundnessDuringLaunchAnimation;
- }
-
- return super.getTopRoundness();
- }
-
- @Override
- public float getBottomRoundness() {
- if (!mUseRoundnessSourceTypes && mExpandAnimationRunning) {
- return mBottomRoundnessDuringLaunchAnimation;
- }
-
- return super.getBottomRoundness();
- }
-
public void setExpandAnimationRunning(boolean expandAnimationRunning) {
if (expandAnimationRunning) {
setAboveShelf(true);
@@ -3481,18 +3450,11 @@
private void applyChildrenRoundness() {
if (mIsSummaryWithChildren) {
- if (mUseRoundnessSourceTypes) {
- mChildrenContainer.requestRoundness(
- /* top = */ getTopRoundness(),
- /* bottom = */ getBottomRoundness(),
- /* sourceType = */ FROM_PARENT,
- /* animate = */ false);
- } else {
- mChildrenContainer.requestBottomRoundness(
- getBottomRoundness(),
- LegacySourceType.DefaultValue,
- /* animate = */ false);
- }
+ mChildrenContainer.requestRoundness(
+ /* top = */ getTopRoundness(),
+ /* bottom = */ getBottomRoundness(),
+ /* sourceType = */ FROM_PARENT,
+ /* animate = */ false);
}
}
@@ -3709,24 +3671,10 @@
}
}
- /**
- * Enable the support for rounded corner based on the SourceType
- * @param enabled true if is supported
- */
- @Override
- public void useRoundnessSourceTypes(boolean enabled) {
- super.useRoundnessSourceTypes(enabled);
- if (mChildrenContainer != null) {
- mChildrenContainer.useRoundnessSourceTypes(mUseRoundnessSourceTypes);
- }
- }
-
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- if (mUseRoundnessSourceTypes) {
- updateBaseRoundness();
- }
+ updateBaseRoundness();
}
/** Set whether this notification may show a snooze action. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index 9bf05cb..1acc9f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -261,8 +261,6 @@
mStatusBarStateController.removeCallback(mStatusBarStateListener);
}
});
- mView.useRoundnessSourceTypes(
- mFeatureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES));
}
private final StatusBarStateController.StateListener mStatusBarStateListener =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 9a777ea..2c59c2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -72,7 +72,6 @@
private View mFeedbackIcon;
private boolean mIsLowPriority;
private boolean mTransformLowPriorityTitle;
- private boolean mUseRoundnessSourceTypes;
private RoundnessChangedListener mRoundnessChangedListener;
protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
@@ -122,7 +121,7 @@
@Override
public void applyRoundnessAndInvalidate() {
- if (mUseRoundnessSourceTypes && mRoundnessChangedListener != null) {
+ if (mRoundnessChangedListener != null) {
// We cannot apply the rounded corner to this View, so our parents (in drawChild()) will
// clip our canvas. So we should invalidate our parent.
mRoundnessChangedListener.applyRoundnessAndInvalidate();
@@ -377,15 +376,6 @@
}
/**
- * Enable the support for rounded corner based on the SourceType
- *
- * @param enabled true if is supported
- */
- public void useRoundnessSourceTypes(boolean enabled) {
- mUseRoundnessSourceTypes = enabled;
- }
-
- /**
* Interface that handle the Roundness changes
*/
public interface RoundnessChangedListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt
index 99c6ddb..12956ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt
@@ -81,7 +81,6 @@
ActivatableNotificationViewBinder.bind(viewModel, shelf, falsingManager)
shelf.apply {
setRefactorFlagEnabled(true)
- useRoundnessSourceTypes(featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES))
setSensitiveRevealAnimEndabled(featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM))
// TODO(278765923): Replace with eventual NotificationIconContainerViewBinder#bind()
notificationIconAreaController.setShelfIcons(shelfIcons)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 160a230..d18757d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -45,9 +45,7 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.NotificationGroupingUtil;
-import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.FeedbackIcon;
-import com.android.systemui.statusbar.notification.LegacySourceType;
import com.android.systemui.statusbar.notification.NotificationFadeAware;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.Roundable;
@@ -133,7 +131,6 @@
private int mUntruncatedChildCount;
private boolean mContainingNotificationIsFaded = false;
private RoundableState mRoundableState;
- private boolean mUseRoundnessSourceTypes;
public NotificationChildrenContainer(Context context) {
this(context, null);
@@ -328,13 +325,6 @@
row.setContentTransformationAmount(0, false /* isLastChild */);
row.setNotificationFaded(mContainingNotificationIsFaded);
- if (!mUseRoundnessSourceTypes) {
- // This is a workaround, the NotificationShelf should be the owner of `OnScroll`
- // roundness.
- // Here we should reset the `OnScroll` roundness only on top-level rows.
- NotificationShelf.resetLegacyOnScrollRoundness(row);
- }
-
// It doesn't make sense to keep old animations around, lets cancel them!
ExpandableViewState viewState = row.getViewState();
if (viewState != null) {
@@ -342,9 +332,7 @@
row.cancelAppearDrawing();
}
- if (mUseRoundnessSourceTypes) {
- applyRoundnessAndInvalidate();
- }
+ applyRoundnessAndInvalidate();
}
private void ensureRemovedFromTransientContainer(View v) {
@@ -379,10 +367,8 @@
mGroupingUtil.restoreChildNotification(row);
}
- if (mUseRoundnessSourceTypes) {
- row.requestRoundnessReset(FROM_PARENT, /* animate = */ false);
- applyRoundnessAndInvalidate();
- }
+ row.requestRoundnessReset(FROM_PARENT, /* animate = */ false);
+ applyRoundnessAndInvalidate();
}
/**
@@ -409,10 +395,7 @@
getContext(),
mNotificationHeader,
mContainingNotification);
- mNotificationHeaderWrapper.useRoundnessSourceTypes(mUseRoundnessSourceTypes);
- if (mUseRoundnessSourceTypes) {
- mNotificationHeaderWrapper.setOnRoundnessChangedListener(this::invalidate);
- }
+ mNotificationHeaderWrapper.setOnRoundnessChangedListener(this::invalidate);
addView(mNotificationHeader, 0);
invalidate();
} else {
@@ -450,12 +433,7 @@
getContext(),
mNotificationHeaderLowPriority,
mContainingNotification);
- mNotificationHeaderWrapperLowPriority.useRoundnessSourceTypes(
- mUseRoundnessSourceTypes
- );
- if (mUseRoundnessSourceTypes) {
- mNotificationHeaderWrapper.setOnRoundnessChangedListener(this::invalidate);
- }
+ mNotificationHeaderWrapper.setOnRoundnessChangedListener(this::invalidate);
addView(mNotificationHeaderLowPriority, 0);
invalidate();
} else {
@@ -891,7 +869,7 @@
isCanvasChanged = true;
canvas.save();
- if (mUseRoundnessSourceTypes && translation != 0f) {
+ if (translation != 0f) {
clipPath.offset(translation, 0f);
canvas.clipPath(clipPath);
clipPath.offset(-translation, 0f);
@@ -1444,40 +1422,30 @@
@Override
public void applyRoundnessAndInvalidate() {
boolean last = true;
- if (mUseRoundnessSourceTypes) {
- if (mNotificationHeaderWrapper != null) {
- mNotificationHeaderWrapper.requestTopRoundness(
- /* value = */ getTopRoundness(),
- /* sourceType = */ FROM_PARENT,
- /* animate = */ false
- );
- }
- if (mNotificationHeaderWrapperLowPriority != null) {
- mNotificationHeaderWrapperLowPriority.requestTopRoundness(
- /* value = */ getTopRoundness(),
- /* sourceType = */ FROM_PARENT,
- /* animate = */ false
- );
- }
+ if (mNotificationHeaderWrapper != null) {
+ mNotificationHeaderWrapper.requestTopRoundness(
+ /* value = */ getTopRoundness(),
+ /* sourceType = */ FROM_PARENT,
+ /* animate = */ false
+ );
+ }
+ if (mNotificationHeaderWrapperLowPriority != null) {
+ mNotificationHeaderWrapperLowPriority.requestTopRoundness(
+ /* value = */ getTopRoundness(),
+ /* sourceType = */ FROM_PARENT,
+ /* animate = */ false
+ );
}
for (int i = mAttachedChildren.size() - 1; i >= 0; i--) {
ExpandableNotificationRow child = mAttachedChildren.get(i);
if (child.getVisibility() == View.GONE) {
continue;
}
- if (mUseRoundnessSourceTypes) {
- child.requestRoundness(
- /* top = */ 0f,
- /* bottom = */ last ? getBottomRoundness() : 0f,
- /* sourceType = */ FROM_PARENT,
- /* animate = */ false);
- } else {
- child.requestRoundness(
- /* top = */ 0f,
- /* bottom = */ last ? getBottomRoundness() : 0f,
- LegacySourceType.DefaultValue,
- /* animate = */ isShown());
- }
+ child.requestRoundness(
+ /* top = */ 0f,
+ /* bottom = */ last ? getBottomRoundness() : 0f,
+ /* sourceType = */ FROM_PARENT,
+ /* animate = */ false);
last = false;
}
Roundable.super.applyRoundnessAndInvalidate();
@@ -1537,15 +1505,6 @@
return mNotificationHeaderWrapper;
}
- /**
- * Enable the support for rounded corner based on the SourceType
- *
- * @param enabled true if is supported
- */
- public void useRoundnessSourceTypes(boolean enabled) {
- mUseRoundnessSourceTypes = enabled;
- }
-
public String debugString() {
return TAG + " { "
+ "visibility: " + getVisibility()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
index fde8c4d..fa1843e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
@@ -16,24 +16,13 @@
package com.android.systemui.statusbar.notification.stack;
-import android.content.res.Resources;
-import android.util.MathUtils;
-
import androidx.annotation.NonNull;
import com.android.systemui.Dumpable;
-import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
-import com.android.systemui.statusbar.notification.LegacySourceType;
-import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
import com.android.systemui.statusbar.notification.Roundable;
import com.android.systemui.statusbar.notification.SourceType;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.logging.NotificationRoundnessLogger;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import java.io.PrintWriter;
@@ -50,64 +39,27 @@
private static final String TAG = "NotificationRoundnessManager";
private static final SourceType DISMISS_ANIMATION = SourceType.from("DismissAnimation");
- private final ExpandableView[] mFirstInSectionViews;
- private final ExpandableView[] mLastInSectionViews;
- private final ExpandableView[] mTmpFirstInSectionViews;
- private final ExpandableView[] mTmpLastInSectionViews;
- private final NotificationRoundnessLogger mNotifLogger;
private final DumpManager mDumpManager;
- private boolean mExpanded;
private HashSet<ExpandableView> mAnimatedChildren;
- private Runnable mRoundingChangedCallback;
- private ExpandableNotificationRow mTrackedHeadsUp;
- private float mAppearFraction;
private boolean mRoundForPulsingViews;
private boolean mIsClearAllInProgress;
private ExpandableView mSwipedView = null;
private Roundable mViewBeforeSwipedView = null;
private Roundable mViewAfterSwipedView = null;
- private boolean mUseRoundnessSourceTypes;
@Inject
- NotificationRoundnessManager(
- NotificationSectionsFeatureManager sectionsFeatureManager,
- NotificationRoundnessLogger notifLogger,
- DumpManager dumpManager,
- FeatureFlags featureFlags) {
- int numberOfSections = sectionsFeatureManager.getNumberOfBuckets();
- mFirstInSectionViews = new ExpandableView[numberOfSections];
- mLastInSectionViews = new ExpandableView[numberOfSections];
- mTmpFirstInSectionViews = new ExpandableView[numberOfSections];
- mTmpLastInSectionViews = new ExpandableView[numberOfSections];
- mNotifLogger = notifLogger;
+ NotificationRoundnessManager(DumpManager dumpManager) {
mDumpManager = dumpManager;
- mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
-
mDumpManager.registerDumpable(TAG, this);
}
@Override
public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
- pw.println("mFirstInSectionViews: length=" + mFirstInSectionViews.length);
- pw.println(dumpViews(mFirstInSectionViews));
- pw.println("mLastInSectionViews: length=" + mLastInSectionViews.length);
- pw.println(dumpViews(mFirstInSectionViews));
- if (mTrackedHeadsUp != null) {
- pw.println("trackedHeadsUp=" + mTrackedHeadsUp.getEntry());
- }
pw.println("roundForPulsingViews=" + mRoundForPulsingViews);
pw.println("isClearAllInProgress=" + mIsClearAllInProgress);
}
- public void updateView(ExpandableView view, boolean animate) {
- if (mUseRoundnessSourceTypes) return;
- boolean changed = updateViewWithoutCallback(view, animate);
- if (changed) {
- mRoundingChangedCallback.run();
- }
- }
-
public boolean isViewAffectedBySwipe(ExpandableView expandableView) {
return expandableView != null
&& (expandableView == mSwipedView
@@ -115,58 +67,6 @@
|| expandableView == mViewAfterSwipedView);
}
- boolean updateViewWithoutCallback(
- ExpandableView view,
- boolean animate) {
- if (mUseRoundnessSourceTypes) return false;
- if (view == null
- || view == mViewBeforeSwipedView
- || view == mViewAfterSwipedView) {
- return false;
- }
-
- final boolean isTopChanged = view.requestTopRoundness(
- getRoundnessDefaultValue(view, true /* top */),
- LegacySourceType.DefaultValue,
- animate);
-
- final boolean isBottomChanged = view.requestBottomRoundness(
- getRoundnessDefaultValue(view, /* top = */ false),
- LegacySourceType.DefaultValue,
- animate);
-
- final boolean isFirstInSection = isFirstInSection(view);
- final boolean isLastInSection = isLastInSection(view);
-
- view.setFirstInSection(isFirstInSection);
- view.setLastInSection(isLastInSection);
-
- mNotifLogger.onCornersUpdated(view, isFirstInSection,
- isLastInSection, isTopChanged, isBottomChanged);
-
- return (isFirstInSection || isLastInSection) && (isTopChanged || isBottomChanged);
- }
-
- private boolean isFirstInSection(ExpandableView view) {
- if (mUseRoundnessSourceTypes) return false;
- for (int i = 0; i < mFirstInSectionViews.length; i++) {
- if (view == mFirstInSectionViews[i]) {
- return true;
- }
- }
- return false;
- }
-
- private boolean isLastInSection(ExpandableView view) {
- if (mUseRoundnessSourceTypes) return false;
- for (int i = mLastInSectionViews.length - 1; i >= 0; i--) {
- if (view == mLastInSectionViews[i]) {
- return true;
- }
- }
- return false;
- }
-
void setViewsAffectedBySwipe(
Roundable viewBefore,
ExpandableView viewSwiped,
@@ -180,34 +80,27 @@
if (mSwipedView != null) oldViews.add(mSwipedView);
if (mViewAfterSwipedView != null) oldViews.add(mViewAfterSwipedView);
- final SourceType source;
- if (mUseRoundnessSourceTypes) {
- source = DISMISS_ANIMATION;
- } else {
- source = LegacySourceType.OnDismissAnimation;
- }
-
mViewBeforeSwipedView = viewBefore;
if (viewBefore != null) {
oldViews.remove(viewBefore);
- viewBefore.requestRoundness(/* top = */ 0f, /* bottom = */ 1f, source);
+ viewBefore.requestRoundness(/* top = */ 0f, /* bottom = */ 1f, DISMISS_ANIMATION);
}
mSwipedView = viewSwiped;
if (viewSwiped != null) {
oldViews.remove(viewSwiped);
- viewSwiped.requestRoundness(/* top = */ 1f, /* bottom = */ 1f, source);
+ viewSwiped.requestRoundness(/* top = */ 1f, /* bottom = */ 1f, DISMISS_ANIMATION);
}
mViewAfterSwipedView = viewAfter;
if (viewAfter != null) {
oldViews.remove(viewAfter);
- viewAfter.requestRoundness(/* top = */ 1f, /* bottom = */ 0f, source);
+ viewAfter.requestRoundness(/* top = */ 1f, /* bottom = */ 0f, DISMISS_ANIMATION);
}
// After setting the current Views, reset the views that are still present in the set.
for (Roundable oldView : oldViews) {
- oldView.requestRoundnessReset(source);
+ oldView.requestRoundnessReset(DISMISS_ANIMATION);
}
}
@@ -229,143 +122,6 @@
return mRoundForPulsingViews;
}
- private float getRoundnessDefaultValue(Roundable view, boolean top) {
- if (mUseRoundnessSourceTypes) return 0f;
-
- if (view == null) {
- return 0f;
- }
- if (view == mViewBeforeSwipedView
- || view == mSwipedView
- || view == mViewAfterSwipedView) {
- return 1f;
- }
- if (view instanceof ExpandableNotificationRow
- && ((ExpandableNotificationRow) view).canViewBeCleared()
- && mIsClearAllInProgress) {
- return 1.0f;
- }
- if (view instanceof ExpandableView) {
- ExpandableView expandableView = (ExpandableView) view;
- if ((expandableView.isPinned()
- || (expandableView.isHeadsUpAnimatingAway()) && !mExpanded)) {
- return 1.0f;
- }
- if (isFirstInSection(expandableView) && top) {
- return 1.0f;
- }
- if (isLastInSection(expandableView) && !top) {
- return 1.0f;
- }
-
- if (view == mTrackedHeadsUp) {
- // If we're pushing up on a headsup the appear fraction is < 0 and it needs to
- // still be rounded.
- return MathUtils.saturate(1.0f - mAppearFraction);
- }
- if (expandableView.showingPulsing() && mRoundForPulsingViews) {
- return 1.0f;
- }
- if (expandableView.isChildInGroup()) {
- return 0f;
- }
- final Resources resources = expandableView.getResources();
- return resources.getDimension(R.dimen.notification_corner_radius_small)
- / resources.getDimension(R.dimen.notification_corner_radius);
- }
- return 0f;
- }
-
- public void setExpanded(float expandedHeight, float appearFraction) {
- if (mUseRoundnessSourceTypes) return;
- mExpanded = expandedHeight != 0.0f;
- mAppearFraction = appearFraction;
- if (mTrackedHeadsUp != null) {
- updateView(mTrackedHeadsUp, false /* animate */);
- }
- }
-
- public void updateRoundedChildren(NotificationSection[] sections) {
- if (mUseRoundnessSourceTypes) return;
- boolean anyChanged = false;
- for (int i = 0; i < sections.length; i++) {
- mTmpFirstInSectionViews[i] = mFirstInSectionViews[i];
- mTmpLastInSectionViews[i] = mLastInSectionViews[i];
- mFirstInSectionViews[i] = sections[i].getFirstVisibleChild();
- mLastInSectionViews[i] = sections[i].getLastVisibleChild();
- }
- anyChanged |= handleRemovedOldViews(sections, mTmpFirstInSectionViews, true);
- anyChanged |= handleRemovedOldViews(sections, mTmpLastInSectionViews, false);
- anyChanged |= handleAddedNewViews(sections, mTmpFirstInSectionViews, true);
- anyChanged |= handleAddedNewViews(sections, mTmpLastInSectionViews, false);
- if (anyChanged) {
- mRoundingChangedCallback.run();
- }
-
- mNotifLogger.onSectionCornersUpdated(sections, anyChanged);
- }
-
- private boolean handleRemovedOldViews(
- NotificationSection[] sections,
- ExpandableView[] oldViews,
- boolean first) {
- if (mUseRoundnessSourceTypes) return false;
- boolean anyChanged = false;
- for (ExpandableView oldView : oldViews) {
- if (oldView != null) {
- boolean isStillPresent = false;
- boolean adjacentSectionChanged = false;
- for (NotificationSection section : sections) {
- ExpandableView newView =
- (first ? section.getFirstVisibleChild()
- : section.getLastVisibleChild());
- if (newView == oldView) {
- isStillPresent = true;
- if (oldView.isFirstInSection() != isFirstInSection(oldView)
- || oldView.isLastInSection() != isLastInSection(oldView)) {
- adjacentSectionChanged = true;
- }
- break;
- }
- }
- if (!isStillPresent || adjacentSectionChanged) {
- anyChanged = true;
- if (!oldView.isRemoved()) {
- updateViewWithoutCallback(oldView, oldView.isShown());
- }
- }
- }
- }
- return anyChanged;
- }
-
- private boolean handleAddedNewViews(
- NotificationSection[] sections,
- ExpandableView[] oldViews,
- boolean first) {
- if (mUseRoundnessSourceTypes) return false;
- boolean anyChanged = false;
- for (NotificationSection section : sections) {
- ExpandableView newView =
- (first ? section.getFirstVisibleChild() : section.getLastVisibleChild());
- if (newView != null) {
- boolean wasAlreadyPresent = false;
- for (ExpandableView oldView : oldViews) {
- if (oldView == newView) {
- wasAlreadyPresent = true;
- break;
- }
- }
- if (!wasAlreadyPresent) {
- anyChanged = true;
- updateViewWithoutCallback(newView,
- newView.isShown() && !mAnimatedChildren.contains(newView));
- }
- }
- }
- return anyChanged;
- }
-
public void setAnimatedChildren(HashSet<ExpandableView> animatedChildren) {
mAnimatedChildren = animatedChildren;
}
@@ -379,51 +135,7 @@
return mAnimatedChildren.contains(view);
}
- public void setOnRoundingChangedCallback(Runnable roundingChangedCallback) {
- mRoundingChangedCallback = roundingChangedCallback;
- }
-
- public void setTrackingHeadsUp(ExpandableNotificationRow row) {
- ExpandableNotificationRow previous = mTrackedHeadsUp;
- mTrackedHeadsUp = row;
- if (previous != null) {
- updateView(previous, true /* animate */);
- }
- }
-
public void setShouldRoundPulsingViews(boolean shouldRoundPulsingViews) {
mRoundForPulsingViews = shouldRoundPulsingViews;
}
-
- private String dumpViews(ExpandableView[] views) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < views.length; i++) {
- if (views[i] == null) continue;
-
- sb.append("\t")
- .append("[").append(i).append("] ")
- .append("isPinned=").append(views[i].isPinned()).append(" ")
- .append("isFirstInSection=").append(views[i].isFirstInSection()).append(" ")
- .append("isLastInSection=").append(views[i].isLastInSection()).append(" ");
-
- if (views[i] instanceof ExpandableNotificationRow) {
- sb.append("entry=");
- dumpEntry(((ExpandableNotificationRow) views[i]).getEntry(), sb);
- }
-
- sb.append("\n");
- }
- return sb.toString();
- }
-
- private void dumpEntry(NotificationEntry entry, StringBuilder sb) {
- sb.append("NotificationEntry{key=").append(entry.getKey()).append(" ");
-
- if (entry.getSection() != null) {
- sb.append(" section=")
- .append(entry.getSection().getLabel());
- }
-
- sb.append("}");
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
index 070b439..fd064ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
@@ -19,8 +19,6 @@
import android.util.Log
import android.view.View
import com.android.internal.annotations.VisibleForTesting
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.media.controls.ui.KeyguardMediaController
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
import com.android.systemui.statusbar.notification.SourceType
@@ -51,12 +49,9 @@
@IncomingHeader private val incomingHeaderController: SectionHeaderController,
@PeopleHeader private val peopleHeaderController: SectionHeaderController,
@AlertingHeader private val alertingHeaderController: SectionHeaderController,
- @SilentHeader private val silentHeaderController: SectionHeaderController,
- featureFlags: FeatureFlags
+ @SilentHeader private val silentHeaderController: SectionHeaderController
) : SectionProvider {
- private val useRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES)
-
private val configurationListener = object : ConfigurationController.ConfigurationListener {
override fun onLocaleListChanged() {
reinflateViews()
@@ -196,35 +191,33 @@
isSectionChanged || changed
}
- if (useRoundnessSourceTypes) {
- val newFirstChildren = sections.mapNotNull { it.firstVisibleChild }
- val newLastChildren = sections.mapNotNull { it.lastVisibleChild }
+ val newFirstChildren = sections.mapNotNull { it.firstVisibleChild }
+ val newLastChildren = sections.mapNotNull { it.lastVisibleChild }
- // Update the roundness of Views that weren't already in the first/last position
- newFirstChildren.forEach { firstChild ->
- val wasFirstChild = oldFirstChildren.remove(firstChild)
- if (!wasFirstChild) {
- val notAnimatedChild = !notificationRoundnessManager.isAnimatedChild(firstChild)
- val animated = firstChild.isShown && notAnimatedChild
- firstChild.requestTopRoundness(1f, SECTION, animated)
- }
+ // Update the roundness of Views that weren't already in the first/last position
+ newFirstChildren.forEach { firstChild ->
+ val wasFirstChild = oldFirstChildren.remove(firstChild)
+ if (!wasFirstChild) {
+ val notAnimatedChild = !notificationRoundnessManager.isAnimatedChild(firstChild)
+ val animated = firstChild.isShown && notAnimatedChild
+ firstChild.requestTopRoundness(1f, SECTION, animated)
}
- newLastChildren.forEach { lastChild ->
- val wasLastChild = oldLastChildren.remove(lastChild)
- if (!wasLastChild) {
- val notAnimatedChild = !notificationRoundnessManager.isAnimatedChild(lastChild)
- val animated = lastChild.isShown && notAnimatedChild
- lastChild.requestBottomRoundness(1f, SECTION, animated)
- }
+ }
+ newLastChildren.forEach { lastChild ->
+ val wasLastChild = oldLastChildren.remove(lastChild)
+ if (!wasLastChild) {
+ val notAnimatedChild = !notificationRoundnessManager.isAnimatedChild(lastChild)
+ val animated = lastChild.isShown && notAnimatedChild
+ lastChild.requestBottomRoundness(1f, SECTION, animated)
}
+ }
- // The Views left in the set are no longer in the first/last position
- oldFirstChildren.forEach { noMoreFirstChild ->
- noMoreFirstChild.requestTopRoundness(0f, SECTION)
- }
- oldLastChildren.forEach { noMoreLastChild ->
- noMoreLastChild.requestBottomRoundness(0f, SECTION)
- }
+ // The Views left in the set are no longer in the first/last position
+ oldFirstChildren.forEach { noMoreFirstChild ->
+ noMoreFirstChild.requestTopRoundness(0f, SECTION)
+ }
+ oldLastChildren.forEach { noMoreLastChild ->
+ noMoreLastChild.requestBottomRoundness(0f, SECTION)
}
if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 3bc2066..edff877 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -200,7 +200,6 @@
private Set<Integer> mDebugTextUsedYPositions;
private final boolean mDebugRemoveAnimation;
private final boolean mSimplifiedAppearFraction;
- private final boolean mUseRoundnessSourceTypes;
private final boolean mSensitiveRevealAnimEndabled;
private boolean mAnimatedInsets;
@@ -625,7 +624,6 @@
mDebugLines = featureFlags.isEnabled(Flags.NSSL_DEBUG_LINES);
mDebugRemoveAnimation = featureFlags.isEnabled(Flags.NSSL_DEBUG_REMOVE_ANIMATION);
mSimplifiedAppearFraction = featureFlags.isEnabled(Flags.SIMPLIFIED_APPEAR_FRACTION);
- mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
mSensitiveRevealAnimEndabled = featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM);
setAnimatedInsetsEnabled(featureFlags.isEnabled(Flags.ANIMATED_NOTIFICATION_SHADE_INSETS));
mSectionsManager = Dependency.get(NotificationSectionsManager.class);
@@ -3134,10 +3132,6 @@
mAnimateNextSectionBoundsChange = false;
}
mAmbientState.setLastVisibleBackgroundChild(lastChild);
- if (!mUseRoundnessSourceTypes) {
- // TODO: Refactor SectionManager and put the RoundnessManager there.
- mController.getNotificationRoundnessManager().updateRoundedChildren(mSections);
- }
mAnimateBottomOnLayout = false;
invalidate();
}
@@ -3584,9 +3578,7 @@
@ShadeViewRefactor(RefactorComponent.LAYOUT_ALGORITHM)
protected StackScrollAlgorithm createStackScrollAlgorithm(Context context) {
- StackScrollAlgorithm stackScrollAlgorithm = new StackScrollAlgorithm(context, this);
- stackScrollAlgorithm.useRoundnessSourceTypes(mUseRoundnessSourceTypes);
- return stackScrollAlgorithm;
+ return new StackScrollAlgorithm(context, this);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 4751fb6..7b046d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -61,7 +61,6 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.media.controls.ui.KeyguardMediaController;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
@@ -126,8 +125,6 @@
import com.android.systemui.util.Compile;
import com.android.systemui.util.settings.SecureSettings;
-import kotlin.Unit;
-
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -195,7 +192,6 @@
private int mBarState;
private HeadsUpAppearanceController mHeadsUpAppearanceController;
private final FeatureFlags mFeatureFlags;
- private final boolean mUseRoundnessSourceTypes;
private final NotificationTargetsHelper mNotificationTargetsHelper;
private final SecureSettings mSecureSettings;
private final NotificationDismissibilityProvider mDismissibilityProvider;
@@ -594,36 +590,12 @@
}
@Override
- public void onHeadsUpPinned(NotificationEntry entry) {
- if (!mUseRoundnessSourceTypes) {
- mNotificationRoundnessManager.updateView(
- entry.getRow(),
- /* animate = */ false);
- }
- }
-
- @Override
- public void onHeadsUpUnPinned(NotificationEntry entry) {
- if (!mUseRoundnessSourceTypes) {
- ExpandableNotificationRow row = entry.getRow();
- // update the roundedness posted, because we might be animating away the
- // headsup soon, so no need to set the roundedness to 0 and then back to 1.
- row.post(() -> mNotificationRoundnessManager.updateView(row,
- true /* animate */));
- }
- }
-
- @Override
public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
long numEntries = mHeadsUpManager.getAllEntries().count();
NotificationEntry topEntry = mHeadsUpManager.getTopEntry();
mView.setNumHeadsUp(numEntries);
mView.setTopHeadsUpEntry(topEntry);
generateHeadsUpAnimation(entry, isHeadsUp);
- if (!mUseRoundnessSourceTypes) {
- ExpandableNotificationRow row = entry.getRow();
- mNotificationRoundnessManager.updateView(row, true /* animate */);
- }
}
};
@@ -723,7 +695,6 @@
mShadeController = shadeController;
mNotifIconAreaController = notifIconAreaController;
mFeatureFlags = featureFlags;
- mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
mNotificationTargetsHelper = notificationTargetsHelper;
mSecureSettings = secureSettings;
mDismissibilityProvider = dismissibilityProvider;
@@ -791,11 +762,6 @@
mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener);
- if (!mUseRoundnessSourceTypes) {
- mNotificationRoundnessManager.setOnRoundingChangedCallback(mView::invalidate);
- mView.addOnExpandedHeightChangedListener(mNotificationRoundnessManager::setExpanded);
- }
-
mVisibilityLocationProviderDelegator.setDelegate(this::isInVisibleLocation);
mTunerService.addTunable(
@@ -822,7 +788,7 @@
mView.generateRemoveAnimation(mKeyguardMediaController.getSinglePaneContainer());
}
mView.requestChildrenUpdate();
- return Unit.INSTANCE;
+ return kotlin.Unit.INSTANCE;
});
// attach callback, and then call it to update mView immediately
@@ -961,7 +927,6 @@
public void setTrackingHeadsUp(ExpandableNotificationRow expandableNotificationRow) {
mView.setTrackingHeadsUp(expandableNotificationRow);
- mNotificationRoundnessManager.setTrackingHeadsUp(expandableNotificationRow);
}
public void wakeUpFromPulse() {
@@ -1779,9 +1744,6 @@
@Override
public void bindRow(ExpandableNotificationRow row) {
row.setHeadsUpAnimatingAwayListener(animatingAway -> {
- if (!mUseRoundnessSourceTypes) {
- mNotificationRoundnessManager.updateView(row, false);
- }
NotificationEntry entry = row.getEntry();
mHeadsUpAppearanceController.updateHeader(entry);
mHeadsUpAppearanceController.updateHeadsUpAndPulsingRoundness(entry);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index 91f53b6..993c3801 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -35,7 +35,6 @@
import com.android.systemui.SwipeHelper;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
@@ -69,7 +68,6 @@
private boolean mIsExpanded;
private boolean mPulsing;
private final NotificationRoundnessManager mNotificationRoundnessManager;
- private final boolean mUseRoundnessSourceTypes;
NotificationSwipeHelper(
Resources resources,
@@ -81,7 +79,6 @@
NotificationRoundnessManager notificationRoundnessManager) {
super(callback, resources, viewConfiguration, falsingManager, featureFlags);
mNotificationRoundnessManager = notificationRoundnessManager;
- mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
mMenuListener = menuListener;
mCallback = callback;
mFalsingCheck = () -> resetExposedMenuView(true /* animate */, true /* force */);
@@ -323,8 +320,7 @@
protected void prepareDismissAnimation(View view, Animator anim) {
super.prepareDismissAnimation(view, anim);
- if (mUseRoundnessSourceTypes
- && view instanceof ExpandableNotificationRow
+ if (view instanceof ExpandableNotificationRow
&& mNotificationRoundnessManager.isClearAllInProgress()) {
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
anim.addListener(new AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
index 8b6d6a4f..02662f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
@@ -4,7 +4,6 @@
import androidx.core.view.isVisible
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.statusbar.notification.Roundable
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
@@ -20,7 +19,6 @@
constructor(
featureFlags: FeatureFlags,
) {
- private val useRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES)
/**
* This method looks for views that can be rounded (and implement [Roundable]) during a
@@ -48,10 +46,6 @@
if (notificationParent != null && childrenContainer != null) {
// We are inside a notification group
- if (!useRoundnessSourceTypes) {
- return RoundableTargets(null, null, null)
- }
-
val visibleGroupChildren = childrenContainer.attachedChildren.filter { it.isVisible }
val indexOfParentSwipedView = visibleGroupChildren.indexOf(viewSwiped)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 3060473..92d767a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -34,7 +34,6 @@
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.NotificationShelf;
-import com.android.systemui.statusbar.notification.LegacySourceType;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -75,7 +74,6 @@
private float mQuickQsOffsetHeight;
private float mSmallCornerRadius;
private float mLargeCornerRadius;
- private boolean mUseRoundnessSourceTypes;
public StackScrollAlgorithm(
Context context,
@@ -836,12 +834,8 @@
row.isLastInSection() ? 1f : (mSmallCornerRadius / mLargeCornerRadius);
final float bottomValue = computeCornerRoundnessForPinnedHun(mHostView.getHeight(),
ambientState.getStackY(), getMaxAllowedChildHeight(row), originalCornerRadius);
- if (mUseRoundnessSourceTypes) {
- row.requestBottomRoundness(bottomValue, STACK_SCROLL_ALGO);
- row.addOnDetachResetRoundness(STACK_SCROLL_ALGO);
- } else {
- row.requestBottomRoundness(bottomValue, LegacySourceType.OnScroll);
- }
+ row.requestBottomRoundness(bottomValue, STACK_SCROLL_ALGO);
+ row.addOnDetachResetRoundness(STACK_SCROLL_ALGO);
}
@VisibleForTesting
@@ -979,14 +973,6 @@
this.mIsExpanded = isExpanded;
}
- /**
- * Enable the support for rounded corner based on the SourceType
- * @param enabled true if is supported
- */
- public void useRoundnessSourceTypes(boolean enabled) {
- mUseRoundnessSourceTypes = enabled;
- }
-
public static class StackScrollAlgorithmState {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index e705afc..f15dcc3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -27,8 +27,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.ViewClippingUtil;
import com.android.systemui.R;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.ShadeHeadsUpTracker;
@@ -78,7 +76,6 @@
private final DarkIconDispatcher mDarkIconDispatcher;
private final ShadeViewController mShadeViewController;
private final NotificationRoundnessManager mNotificationRoundnessManager;
- private final boolean mUseRoundnessSourceTypes;
private final Consumer<ExpandableNotificationRow>
mSetTrackingHeadsUp = this::setTrackingHeadsUp;
private final BiConsumer<Float, Float> mSetExpandedHeight = this::setAppearFraction;
@@ -120,14 +117,12 @@
NotificationStackScrollLayoutController stackScrollerController,
ShadeViewController shadeViewController,
NotificationRoundnessManager notificationRoundnessManager,
- FeatureFlags featureFlags,
HeadsUpStatusBarView headsUpStatusBarView,
Clock clockView,
@Named(OPERATOR_NAME_FRAME_VIEW) Optional<View> operatorNameViewOptional) {
super(headsUpStatusBarView);
mNotificationIconAreaController = notificationIconAreaController;
mNotificationRoundnessManager = notificationRoundnessManager;
- mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
mHeadsUpManager = headsUpManager;
// We may be mid-HUN-expansion when this controller is re-created (for example, if the user
@@ -408,21 +403,19 @@
* @param entry target notification
*/
public void updateHeadsUpAndPulsingRoundness(NotificationEntry entry) {
- if (mUseRoundnessSourceTypes) {
- ExpandableNotificationRow row = entry.getRow();
- boolean isTrackedChild = row == mTrackedChild;
- if (row.isPinned() || row.isHeadsUpAnimatingAway() || isTrackedChild) {
- float roundness = MathUtils.saturate(1f - mAppearFraction);
- row.requestRoundness(roundness, roundness, HEADS_UP);
+ ExpandableNotificationRow row = entry.getRow();
+ boolean isTrackedChild = row == mTrackedChild;
+ if (row.isPinned() || row.isHeadsUpAnimatingAway() || isTrackedChild) {
+ float roundness = MathUtils.saturate(1f - mAppearFraction);
+ row.requestRoundness(roundness, roundness, HEADS_UP);
+ } else {
+ row.requestRoundnessReset(HEADS_UP);
+ }
+ if (mNotificationRoundnessManager.shouldRoundNotificationPulsing()) {
+ if (row.showingPulsing()) {
+ row.requestRoundness(/* top = */ 1f, /* bottom = */ 1f, PULSING);
} else {
- row.requestRoundnessReset(HEADS_UP);
- }
- if (mNotificationRoundnessManager.shouldRoundNotificationPulsing()) {
- if (row.showingPulsing()) {
- row.requestRoundness(/* top = */ 1f, /* bottom = */ 1f, PULSING);
- } else {
- row.requestRoundnessReset(PULSING);
- }
+ row.requestRoundnessReset(PULSING);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index c17366a..74ab47f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -115,7 +115,9 @@
val onKeyguard = keyguardUpdateMonitor.isKeyguardVisible &&
!statusBarStateController.isDozing
- val shouldListen = (onKeyguard || bouncerVisible) && keyguardUpdateMonitor.isFaceEnrolled
+ val userId = KeyguardUpdateMonitor.getCurrentUser()
+ val isFaceEnabled = keyguardUpdateMonitor.isFaceAuthEnabledForUser(userId)
+ val shouldListen = (onKeyguard || bouncerVisible) && isFaceEnabled
if (shouldListen != isListening) {
isListening = shouldListen
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 89dddbf..f2fbd7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -136,7 +136,7 @@
private final DreamOverlayStateController mDreamOverlayStateController;
@Nullable
private final FoldAodAnimationController mFoldAodAnimationController;
- private KeyguardMessageAreaController<AuthKeyguardMessageArea> mKeyguardMessageAreaController;
+ KeyguardMessageAreaController<AuthKeyguardMessageArea> mKeyguardMessageAreaController;
private final PrimaryBouncerCallbackInteractor mPrimaryBouncerCallbackInteractor;
private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
private final AlternateBouncerInteractor mAlternateBouncerInteractor;
@@ -430,6 +430,7 @@
mDockManager.addListener(mDockEventListener);
mIsDocked = mDockManager.isDocked();
}
+ mKeyguardStateController.addCallback(mKeyguardStateControllerCallback);
}
/** Register a callback, to be invoked by the Predictive Back system. */
@@ -1564,6 +1565,14 @@
|| mode == KeyguardSecurityModel.SecurityMode.SimPuk;
}
+ private KeyguardStateController.Callback mKeyguardStateControllerCallback =
+ new KeyguardStateController.Callback() {
+ @Override
+ public void onUnlockedChanged() {
+ updateAlternateBouncerShowing(mAlternateBouncerInteractor.maybeHide());
+ }
+ };
+
/**
* Delegate used to send show and hide events to an alternate authentication method instead of
* the regular pin/pattern/password bouncer.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
index 2c57a26..67243b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
@@ -16,26 +16,15 @@
package com.android.systemui.statusbar.phone.dagger;
-import android.content.ContentResolver;
-import android.os.Handler;
import android.view.LayoutInflater;
-import android.view.ViewStub;
-
-import androidx.constraintlayout.motion.widget.MotionLayout;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
-import com.android.systemui.battery.BatteryMeterView;
-import com.android.systemui.battery.BatteryMeterViewController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.privacy.OngoingPrivacyChip;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.shade.CombinedShadeHeadersConstraintManager;
-import com.android.systemui.shade.CombinedShadeHeadersConstraintManagerImpl;
import com.android.systemui.shade.NotificationPanelView;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.NotificationShadeWindowView;
@@ -59,17 +48,13 @@
import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
-import com.android.systemui.statusbar.phone.StatusIconContainer;
import com.android.systemui.statusbar.phone.SystemBarAttributesListener;
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger;
import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
-import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.CarrierConfigTracker;
import com.android.systemui.util.settings.SecureSettings;
@@ -90,7 +75,6 @@
})
public abstract class StatusBarViewModule {
- public static final String SHADE_HEADER = "large_screen_shade_header";
public static final String STATUS_BAR_FRAGMENT = "status_bar_fragment";
/** */
@@ -136,76 +120,6 @@
abstract ShadeViewController bindsShadeViewController(
NotificationPanelViewController notificationPanelViewController);
- @Provides
- @Named(SHADE_HEADER)
- @CentralSurfacesComponent.CentralSurfacesScope
- public static MotionLayout getLargeScreenShadeHeaderBarView(
- NotificationShadeWindowView notificationShadeWindowView,
- FeatureFlags featureFlags) {
- ViewStub stub = notificationShadeWindowView.findViewById(R.id.qs_header_stub);
- int layoutId = R.layout.combined_qs_header;
- stub.setLayoutResource(layoutId);
- MotionLayout v = (MotionLayout) stub.inflate();
- return v;
- }
-
- /** */
- @Provides
- @CentralSurfacesComponent.CentralSurfacesScope
- public static CombinedShadeHeadersConstraintManager
- provideCombinedShadeHeadersConstraintManager() {
- return CombinedShadeHeadersConstraintManagerImpl.INSTANCE;
- }
-
- /** */
- @Provides
- @CentralSurfacesComponent.CentralSurfacesScope
- public static OngoingPrivacyChip getSplitShadeOngoingPrivacyChip(
- @Named(SHADE_HEADER) MotionLayout header) {
- return header.findViewById(R.id.privacy_chip);
- }
-
- /** */
- @Provides
- @CentralSurfacesComponent.CentralSurfacesScope
- static StatusIconContainer providesStatusIconContainer(
- @Named(SHADE_HEADER) MotionLayout header) {
- return header.findViewById(R.id.statusIcons);
- }
-
- /** */
- @Provides
- @CentralSurfacesComponent.CentralSurfacesScope
- @Named(SHADE_HEADER)
- static BatteryMeterView getBatteryMeterView(@Named(SHADE_HEADER) MotionLayout view) {
- return view.findViewById(R.id.batteryRemainingIcon);
- }
-
- @Provides
- @CentralSurfacesComponent.CentralSurfacesScope
- @Named(SHADE_HEADER)
- static BatteryMeterViewController getBatteryMeterViewController(
- @Named(SHADE_HEADER) BatteryMeterView batteryMeterView,
- UserTracker userTracker,
- ConfigurationController configurationController,
- TunerService tunerService,
- @Main Handler mainHandler,
- ContentResolver contentResolver,
- FeatureFlags featureFlags,
- BatteryController batteryController
- ) {
- return new BatteryMeterViewController(
- batteryMeterView,
- userTracker,
- configurationController,
- tunerService,
- mainHandler,
- contentResolver,
- featureFlags,
- batteryController);
-
- }
-
/** */
@Provides
@CentralSurfacesComponent.CentralSurfacesScope
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
index 98cde2a..abedd3220 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
@@ -28,6 +28,11 @@
void startCasting(CastDevice device);
void stopCasting(CastDevice device);
+ /**
+ * @return whether we have a connected device.
+ */
+ boolean hasConnectedCastDevice();
+
public interface Callback {
void onCastDevicesChanged();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index 7290a1a..f7b601b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -217,6 +217,12 @@
}
}
+ @Override
+ public boolean hasConnectedCastDevice() {
+ return getCastDevices().stream().anyMatch(
+ castDevice -> castDevice.state == CastDevice.STATE_CONNECTED);
+ }
+
private void setProjection(MediaProjectionInfo projection, boolean started) {
boolean changed = false;
final MediaProjectionInfo oldProjection = mProjection;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt
index aa502bc..f61f3b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt
@@ -34,6 +34,8 @@
private val halfFoldedStates =
context.resources.getIntArray(R.array.config_halfFoldedDeviceStates)
private val unfoldedStates = context.resources.getIntArray(R.array.config_openDeviceStates)
+ private val rearDisplayStates =
+ context.resources.getIntArray(R.array.config_rearDisplayDeviceStates)
fun logListeningChange(listening: Boolean) {
logBuffer.log(TAG, VERBOSE, { bool1 = listening }, { "setListening: $bool1" })
@@ -122,6 +124,7 @@
in foldedStates -> "Folded"
in unfoldedStates -> "Unfolded"
in halfFoldedStates -> "Half-Folded"
+ in rearDisplayStates -> "Rear display"
-1 -> "Uninitialized"
else -> "Unknown"
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
index 3d811cf..673819b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -240,7 +240,7 @@
|| (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB && mDebugUnlocked);
boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user);
- boolean faceAuthEnabled = mKeyguardUpdateMonitor.isFaceEnrolled();
+ boolean faceAuthEnabled = mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(user);
boolean changed = secure != mSecure || canDismissLockScreen != mCanDismissLockScreen
|| trustManaged != mTrustManaged || mTrusted != trusted
|| mFaceAuthEnabled != faceAuthEnabled;
diff --git a/packages/SystemUI/src/com/android/systemui/theme/DynamicColors.kt b/packages/SystemUI/src/com/android/systemui/theme/DynamicColors.kt
index 6026d2c..f0fa779 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/DynamicColors.kt
+++ b/packages/SystemUI/src/com/android/systemui/theme/DynamicColors.kt
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.systemui.theme
import android.util.Pair
@@ -24,68 +25,73 @@
@JvmField
val ALL_DYNAMIC_COLORS_MAPPED: List<Pair<String, DynamicColor>> =
arrayListOf(
- Pair.create("primary_container", MDC.primaryContainer),
- Pair.create("on_primary_container", MDC.onPrimaryContainer),
- Pair.create("primary", MDC.primary),
- Pair.create("on_primary", MDC.onPrimary),
- Pair.create("secondary_container", MDC.secondaryContainer),
- Pair.create("on_secondary_container", MDC.onSecondaryContainer),
- Pair.create("secondary", MDC.secondary),
- Pair.create("on_secondary", MDC.onSecondary),
- Pair.create("tertiary_container", MDC.tertiaryContainer),
- Pair.create("on_tertiary_container", MDC.onTertiaryContainer),
- Pair.create("tertiary", MDC.tertiary),
- Pair.create("on_tertiary", MDC.onTertiary),
- Pair.create("background", MDC.background),
- Pair.create("on_background", MDC.onBackground),
- Pair.create("surface", MDC.surface),
- Pair.create("on_surface", MDC.onSurface),
- Pair.create("surface_container_low", MDC.surfaceContainerLow),
- Pair.create("surface_container_lowest", MDC.surfaceContainerLowest),
- Pair.create("surface_container", MDC.surfaceContainer),
- Pair.create("surface_container_high", MDC.surfaceContainerHigh),
- Pair.create("surface_container_highest", MDC.surfaceContainerHighest),
- Pair.create("surface_bright", MDC.surfaceBright),
- Pair.create("surface_dim", MDC.surfaceDim),
- Pair.create("surface_variant", MDC.surfaceVariant),
- Pair.create("on_surface_variant", MDC.onSurfaceVariant),
- Pair.create("outline", MDC.outline),
- Pair.create("outline_variant", MDC.outlineVariant),
- Pair.create("error", MDC.error),
- Pair.create("on_error", MDC.onError),
- Pair.create("error_container", MDC.errorContainer),
- Pair.create("on_error_container", MDC.onErrorContainer),
- Pair.create("primary_fixed", MDC.primaryFixed),
- Pair.create("primary_fixed_dim", MDC.primaryFixedDim),
- Pair.create("on_primary_fixed", MDC.onPrimaryFixed),
- Pair.create("on_primary_fixed_variant", MDC.onPrimaryFixedVariant),
- Pair.create("secondary_fixed", MDC.secondaryFixed),
- Pair.create("secondary_fixed_dim", MDC.secondaryFixedDim),
- Pair.create("on_secondary_fixed", MDC.onSecondaryFixed),
- Pair.create("on_secondary_fixed_variant", MDC.onSecondaryFixedVariant),
- Pair.create("tertiary_fixed", MDC.tertiaryFixed),
- Pair.create("tertiary_fixed_dim", MDC.tertiaryFixedDim),
- Pair.create("on_tertiary_fixed", MDC.onTertiaryFixed),
- Pair.create("on_tertiary_fixed_variant", MDC.onTertiaryFixedVariant),
- Pair.create("control_activated", MDC.controlActivated),
- Pair.create("control_normal", MDC.controlNormal),
- Pair.create("control_highlight", MDC.controlHighlight),
- Pair.create("text_primary_inverse", MDC.textPrimaryInverse),
+ Pair.create("primary_container", MDC.primaryContainer()),
+ Pair.create("on_primary_container", MDC.onPrimaryContainer()),
+ Pair.create("primary", MDC.primary()),
+ Pair.create("on_primary", MDC.onPrimary()),
+ Pair.create("secondary_container", MDC.secondaryContainer()),
+ Pair.create("on_secondary_container", MDC.onSecondaryContainer()),
+ Pair.create("secondary", MDC.secondary()),
+ Pair.create("on_secondary", MDC.onSecondary()),
+ Pair.create("tertiary_container", MDC.tertiaryContainer()),
+ Pair.create("on_tertiary_container", MDC.onTertiaryContainer()),
+ Pair.create("tertiary", MDC.tertiary()),
+ Pair.create("on_tertiary", MDC.onTertiary()),
+ Pair.create("background", MDC.background()),
+ Pair.create("on_background", MDC.onBackground()),
+ Pair.create("surface", MDC.surface()),
+ Pair.create("on_surface", MDC.onSurface()),
+ Pair.create("surface_container_low", MDC.surfaceContainerLow()),
+ Pair.create("surface_container_lowest", MDC.surfaceContainerLowest()),
+ Pair.create("surface_container", MDC.surfaceContainer()),
+ Pair.create("surface_container_high", MDC.surfaceContainerHigh()),
+ Pair.create("surface_container_highest", MDC.surfaceContainerHighest()),
+ Pair.create("surface_bright", MDC.surfaceBright()),
+ Pair.create("surface_dim", MDC.surfaceDim()),
+ Pair.create("surface_variant", MDC.surfaceVariant()),
+ Pair.create("on_surface_variant", MDC.onSurfaceVariant()),
+ Pair.create("outline", MDC.outline()),
+ Pair.create("error", MDC.error()),
+ Pair.create("on_error", MDC.onError()),
+ Pair.create("error_container", MDC.errorContainer()),
+ Pair.create("on_error_container", MDC.onErrorContainer()),
+ Pair.create("primary_fixed", MDC.primaryFixed()),
+ Pair.create("primary_fixed_dim", MDC.primaryFixedDim()),
+ Pair.create("on_primary_fixed", MDC.onPrimaryFixed()),
+ Pair.create("on_primary_fixed_variant", MDC.onPrimaryFixedVariant()),
+ Pair.create("secondary_fixed", MDC.secondaryFixed()),
+ Pair.create("secondary_fixed_dim", MDC.secondaryFixedDim()),
+ Pair.create("on_secondary_fixed", MDC.onSecondaryFixed()),
+ Pair.create("on_secondary_fixed_variant", MDC.onSecondaryFixedVariant()),
+ Pair.create("tertiary_fixed", MDC.tertiaryFixed()),
+ Pair.create("tertiary_fixed_dim", MDC.tertiaryFixedDim()),
+ Pair.create("on_tertiary_fixed", MDC.onTertiaryFixed()),
+ Pair.create("on_tertiary_fixed_variant", MDC.onTertiaryFixedVariant()),
+ Pair.create("control_activated", MDC.controlActivated()),
+ Pair.create("control_normal", MDC.controlNormal()),
+ Pair.create("control_highlight", MDC.controlHighlight()),
+ Pair.create("text_primary_inverse", MDC.textPrimaryInverse()),
Pair.create(
"text_secondary_and_tertiary_inverse",
- MDC.textSecondaryAndTertiaryInverse
+ MDC.textSecondaryAndTertiaryInverse()
),
- Pair.create("text_primary_inverse_disable_only", MDC.textPrimaryInverseDisableOnly),
+ Pair.create(
+ "text_primary_inverse_disable_only",
+ MDC.textPrimaryInverseDisableOnly()
+ ),
Pair.create(
"text_secondary_and_tertiary_inverse_disabled",
- MDC.textSecondaryAndTertiaryInverseDisabled
+ MDC.textSecondaryAndTertiaryInverseDisabled()
),
- Pair.create("text_hint_inverse", MDC.textHintInverse),
- Pair.create("palette_key_color_primary", MDC.primaryPaletteKeyColor),
- Pair.create("palette_key_color_secondary", MDC.secondaryPaletteKeyColor),
- Pair.create("palette_key_color_tertiary", MDC.tertiaryPaletteKeyColor),
- Pair.create("palette_key_color_neutral", MDC.neutralPaletteKeyColor),
- Pair.create("palette_key_color_neutral_variant", MDC.neutralVariantPaletteKeyColor)
+ Pair.create("text_hint_inverse", MDC.textHintInverse()),
+ Pair.create("palette_key_color_primary", MDC.primaryPaletteKeyColor()),
+ Pair.create("palette_key_color_secondary", MDC.secondaryPaletteKeyColor()),
+ Pair.create("palette_key_color_tertiary", MDC.tertiaryPaletteKeyColor()),
+ Pair.create("palette_key_color_neutral", MDC.neutralPaletteKeyColor()),
+ Pair.create(
+ "palette_key_color_neutral_variant",
+ MDC.neutralVariantPaletteKeyColor()
+ )
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index faae8df..43d15bc 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.systemui.theme;
import static android.util.TypedValue.TYPE_INT_COLOR_ARGB8;
@@ -659,9 +660,9 @@
&& res.getColor(android.R.color.system_neutral2_500, theme)
== mColorScheme.getNeutral2().getS500()
&& res.getColor(android.R.color.system_primary_container_dark, theme)
- == MaterialDynamicColors.primaryContainer.getArgb(mDynamicSchemeDark)
+ == MaterialDynamicColors.primaryContainer().getArgb(mDynamicSchemeDark)
&& res.getColor(android.R.color.system_primary_container_light, theme)
- == MaterialDynamicColors.primaryContainer.getArgb(mDynamicSchemeLight))) {
+ == MaterialDynamicColors.primaryContainer().getArgb(mDynamicSchemeLight))) {
return false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
index 0ec1a21..c2922c4 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt
@@ -26,6 +26,7 @@
import android.content.pm.UserInfo
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
+import android.graphics.drawable.Icon
import android.os.RemoteException
import android.os.UserHandle
import android.os.UserManager
@@ -762,8 +763,18 @@
}
// TODO(b/246631653): cache the bitmaps to avoid the background work to fetch them.
- // TODO(b/246631653): downscale the bitmaps to R.dimen.max_avatar_size if requested.
- val userIcon = withContext(backgroundDispatcher) { manager.getUserIcon(userId) }
+ val userIcon = withContext(backgroundDispatcher) {
+ manager.getUserIcon(userId)
+ ?.let { bitmap ->
+ val iconSize =
+ applicationContext
+ .resources
+ .getDimensionPixelSize(R.dimen.bouncer_user_switcher_icon_size)
+ Icon.scaleDownIfNecessary(bitmap, iconSize, iconSize)
+ }
+ }
+
+
if (userIcon != null) {
return BitmapDrawable(userIcon)
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt b/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt
index 41c6b5d..64234c2 100644
--- a/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt
@@ -16,22 +16,20 @@
package com.android.systemui.util
-import android.os.Handler
+import android.os.Trace
import android.os.TraceNameSupplier
-import androidx.tracing.Trace
/**
- * Run a block within a [Trace] section. Calls [Trace.beginSection] before and [Trace.endSection]
- * after the passed block. If tracing is disabled, it will run the block directly to avoid using an
- * unnecessary try-finally block.
+ * Run a block within a [Trace] section.
+ * Calls [Trace.beginSection] before and [Trace.endSection] after the passed block.
*/
inline fun <T> traceSection(tag: String, block: () -> T): T =
- if (Trace.isEnabled()) {
- Trace.beginSection(tag)
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_APP)) {
+ Trace.traceBegin(Trace.TRACE_TAG_APP, tag)
try {
block()
} finally {
- Trace.endSection()
+ Trace.traceEnd(Trace.TRACE_TAG_APP)
}
} else {
block()
@@ -44,10 +42,8 @@
}
/**
- * Helper function for creating a [Runnable] that implements [TraceNameSupplier]. This is
- * useful when posting to a [Handler] so that the [Runnable] has a meaningful name in the
- * trace. Otherwise, the class name of the [Runnable] is used, which is often something like
- * `pkg.MyClass$$ExternalSyntheticLambda0`.
+ * Helper function for creating a Runnable object that implements TraceNameSupplier.
+ * This is useful for posting Runnables to Handlers with meaningful names.
*/
inline fun namedRunnable(tag: String, crossinline block: () -> Unit): Runnable {
return object : Runnable, TraceNameSupplier {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 71246c9..2962c14 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -383,7 +383,6 @@
}
private void setupFingerprintAuth(boolean isClass3) throws RemoteException {
- when(mAuthController.isFingerprintEnrolled(anyInt())).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
mFingerprintSensorProperties = List.of(
@@ -2693,42 +2692,33 @@
}
@Test
public void testFingerprintSensorProperties() throws RemoteException {
- // GIVEN no fingerprint sensor properties
- when(mAuthController.isFingerprintEnrolled(anyInt())).thenReturn(true);
mFingerprintAuthenticatorsRegisteredCallback.onAllAuthenticatorsRegistered(
new ArrayList<>());
- // THEN fingerprint is not possible
assertThat(mKeyguardUpdateMonitor.isUnlockWithFingerprintPossible(
KeyguardUpdateMonitor.getCurrentUser())).isFalse();
- // WHEN there are fingerprint sensor properties
mFingerprintAuthenticatorsRegisteredCallback
.onAllAuthenticatorsRegistered(mFingerprintSensorProperties);
- // THEN unlock with fp is possible & fingerprint starts listening
+ verifyFingerprintAuthenticateCall();
assertThat(mKeyguardUpdateMonitor.isUnlockWithFingerprintPossible(
KeyguardUpdateMonitor.getCurrentUser())).isTrue();
- verifyFingerprintAuthenticateCall();
}
@Test
public void testFaceSensorProperties() throws RemoteException {
- // GIVEN no face sensor properties
- when(mAuthController.isFaceAuthEnrolled(anyInt())).thenReturn(true);
mFaceAuthenticatorsRegisteredCallback.onAllAuthenticatorsRegistered(new ArrayList<>());
- // THEN face is not possible
- assertThat(mKeyguardUpdateMonitor.isUnlockWithFacePossible(
+ assertThat(mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(
KeyguardUpdateMonitor.getCurrentUser())).isFalse();
- // WHEN there are face sensor properties
mFaceAuthenticatorsRegisteredCallback.onAllAuthenticatorsRegistered(mFaceSensorProperties);
+ biometricsEnabledForCurrentUser();
- // THEN face is possible but face does NOT start listening immediately
- assertThat(mKeyguardUpdateMonitor.isUnlockWithFacePossible(
- KeyguardUpdateMonitor.getCurrentUser())).isTrue();
verifyFaceAuthenticateNeverCalled();
verifyFaceDetectNeverCalled();
+ assertThat(mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(
+ KeyguardUpdateMonitor.getCurrentUser())).isTrue();
}
@Test
@@ -2801,6 +2791,9 @@
}
private void mockCanBypassLockscreen(boolean canBypass) {
+ // force update the isFaceEnrolled cache:
+ mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(getCurrentUser());
+
mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
when(mKeyguardBypassController.canBypass()).thenReturn(canBypass);
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt
index dea2082..6fe8892 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt
@@ -18,6 +18,7 @@
import android.animation.Animator
import android.testing.AndroidTestingRunner
import android.transition.TransitionValues
+import android.view.View
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardStatusViewController.SplitShadeTransitionAdapter
import com.android.systemui.SysuiTestCase
@@ -44,14 +45,16 @@
@Test
fun createAnimator_nullStartValues_returnsNull() {
- val animator = adapter.createAnimator(startValues = null, endValues = TransitionValues())
+ val endValues = createEndValues()
+
+ val animator = adapter.createAnimator(startValues = null, endValues = endValues)
assertThat(animator).isNull()
}
@Test
fun createAnimator_nullEndValues_returnsNull() {
- val animator = adapter.createAnimator(startValues = TransitionValues(), endValues = null)
+ val animator = adapter.createAnimator(startValues = createStartValues(), endValues = null)
assertThat(animator).isNull()
}
@@ -59,10 +62,22 @@
@Test
fun createAnimator_nonNullStartAndEndValues_returnsAnimator() {
val animator =
- adapter.createAnimator(startValues = TransitionValues(), endValues = TransitionValues())
+ adapter.createAnimator(startValues = createStartValues(), endValues = createEndValues())
assertThat(animator).isNotNull()
}
+
+ private fun createStartValues() =
+ TransitionValues().also { values ->
+ values.view = View(context)
+ adapter.captureStartValues(values)
+ }
+
+ private fun createEndValues() =
+ TransitionValues().also { values ->
+ values.view = View(context)
+ adapter.captureEndValues(values)
+ }
}
private fun SplitShadeTransitionAdapter.createAnimator(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/accessibility/OWNERS
new file mode 100644
index 0000000..a2001e6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/accessibility/OWNERS
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/SystemActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/SystemActionsTest.java
new file mode 100644
index 0000000..025c88c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/SystemActionsTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.input.InputManager;
+import android.os.RemoteException;
+import android.telecom.TelecomManager;
+import android.telephony.TelephonyManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.KeyEvent;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.settings.FakeDisplayTracker;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.shade.ShadeController;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
+
+import dagger.Lazy;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+@TestableLooper.RunWithLooper
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class SystemActionsTest extends SysuiTestCase {
+ @Mock
+ private UserTracker mUserTracker;
+ @Mock
+ private NotificationShadeWindowController mNotificationShadeController;
+ @Mock
+ private ShadeController mShadeController;
+ @Mock
+ private Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy;
+ @Mock
+ private Optional<Recents> mRecentsOptional;
+ @Mock
+ private TelecomManager mTelecomManager;
+ @Mock
+ private InputManager mInputManager;
+ private final FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext);
+
+ private SystemActions mSystemActions;
+
+ @Before
+ public void setUp() throws RemoteException {
+ MockitoAnnotations.initMocks(this);
+ mContext.addMockSystemService(TelecomManager.class, mTelecomManager);
+ mContext.addMockSystemService(InputManager.class, mInputManager);
+ mSystemActions = new SystemActions(mContext, mUserTracker, mNotificationShadeController,
+ mShadeController, mCentralSurfacesOptionalLazy, mRecentsOptional, mDisplayTracker);
+ }
+
+ @Test
+ public void handleHeadsetHook_callStateIdle_injectsKeyEvents() {
+ when(mTelecomManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_IDLE);
+ // Use a custom doAnswer captor that copies the KeyEvent before storing it, because the
+ // method under test modifies the event object after injecting it which prevents
+ // reliably asserting on the event properties.
+ final List<KeyEvent> keyEvents = new ArrayList<>();
+ doAnswer(invocation -> {
+ keyEvents.add(new KeyEvent(invocation.getArgument(0)));
+ return null;
+ }).when(mInputManager).injectInputEvent(any(), anyInt());
+
+ mSystemActions.handleHeadsetHook();
+
+ assertThat(keyEvents.size()).isEqualTo(2);
+ assertThat(keyEvents.get(0).getKeyCode()).isEqualTo(KeyEvent.KEYCODE_HEADSETHOOK);
+ assertThat(keyEvents.get(0).getAction()).isEqualTo(KeyEvent.ACTION_DOWN);
+ assertThat(keyEvents.get(1).getKeyCode()).isEqualTo(KeyEvent.KEYCODE_HEADSETHOOK);
+ assertThat(keyEvents.get(1).getAction()).isEqualTo(KeyEvent.ACTION_UP);
+ }
+
+ @Test
+ public void handleHeadsetHook_callStateRinging_answersCall() {
+ when(mTelecomManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_RINGING);
+
+ mSystemActions.handleHeadsetHook();
+
+ verify(mTelecomManager).acceptRingingCall();
+ }
+
+ @Test
+ public void handleHeadsetHook_callStateOffhook_endsCall() {
+ when(mTelecomManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_OFFHOOK);
+
+ mSystemActions.handleHeadsetHook();
+
+ verify(mTelecomManager).endCall();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
index 578e1d4..cc00436 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
@@ -159,22 +159,11 @@
@Test
fun doesNotStartIfAnimationIsCancelled() {
val runner = activityLaunchAnimator.createRunner(controller)
- runner.onAnimationCancelled(false /* isKeyguardOccluded */)
+ runner.onAnimationCancelled()
runner.onAnimationStart(0, emptyArray(), emptyArray(), emptyArray(), iCallback)
waitForIdleSync()
- verify(controller).onLaunchAnimationCancelled(false /* newKeyguardOccludedState */)
- verify(controller, never()).onLaunchAnimationStart(anyBoolean())
- }
-
- @Test
- fun passesOccludedStateToLaunchAnimationCancelled_ifTrue() {
- val runner = activityLaunchAnimator.createRunner(controller)
- runner.onAnimationCancelled(true /* isKeyguardOccluded */)
- runner.onAnimationStart(0, emptyArray(), emptyArray(), emptyArray(), iCallback)
-
- waitForIdleSync()
- verify(controller).onLaunchAnimationCancelled(true /* newKeyguardOccludedState */)
+ verify(controller).onLaunchAnimationCancelled()
verify(controller, never()).onLaunchAnimationStart(anyBoolean())
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
index 6d4c467..a20875b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
@@ -49,6 +49,7 @@
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.Dispatchers
import org.junit.After
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -62,6 +63,7 @@
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
+@Ignore("b/279650412")
@RunWith(AndroidJUnit4::class)
@RunWithLooper(setAsMainLooper = true)
@SmallTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FingerprintRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FingerprintRepositoryImplTest.kt
new file mode 100644
index 0000000..f3a100b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FingerprintRepositoryImplTest.kt
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.data.repository
+
+import android.hardware.biometrics.ComponentInfoInternal
+import android.hardware.biometrics.SensorLocationInternal
+import android.hardware.biometrics.SensorProperties
+import android.hardware.fingerprint.FingerprintManager
+import android.hardware.fingerprint.FingerprintSensorProperties
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
+import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.shared.model.FingerprintSensorType
+import com.android.systemui.biometrics.shared.model.SensorStrength
+import com.android.systemui.coroutines.collectLastValue
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+
+@SmallTest
+@RunWith(JUnit4::class)
+class FingerprintRepositoryImplTest : SysuiTestCase() {
+
+ @JvmField @Rule var mockitoRule = MockitoJUnit.rule()
+ private lateinit var testScope: TestScope
+
+ @Mock private lateinit var fingerprintManager: FingerprintManager
+ private lateinit var repository: FingerprintPropertyRepositoryImpl
+
+ @Captor
+ private lateinit var fingerprintAuthenticatorsCaptor:
+ ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback.Stub>
+
+ @Before
+ fun setup() {
+ val dispatcher = StandardTestDispatcher()
+ testScope = TestScope(dispatcher)
+ repository =
+ FingerprintPropertyRepositoryImpl(testScope.backgroundScope, fingerprintManager)
+ testScope.runCurrent()
+
+ verify(fingerprintManager)
+ .addAuthenticatorsRegisteredCallback(fingerprintAuthenticatorsCaptor.capture())
+ }
+
+ @Test
+ fun initializeProperties() =
+ testScope.runTest {
+ val isInitialized = collectLastValue(repository.isInitialized)
+
+ assertDefaultProperties()
+ assertThat(isInitialized()).isFalse()
+
+ val fingerprintProps =
+ listOf(
+ FingerprintSensorPropertiesInternal(
+ 1 /* sensorId */,
+ SensorProperties.STRENGTH_STRONG,
+ 5 /* maxEnrollmentsPerUser */,
+ listOf<ComponentInfoInternal>(
+ ComponentInfoInternal(
+ "sensor" /* componentId */,
+ "vendor/model/revision" /* hardwareVersion */,
+ "1.01" /* firmwareVersion */,
+ "00000001" /* serialNumber */,
+ "" /* softwareVersion */
+ )
+ ),
+ FingerprintSensorProperties.TYPE_REAR,
+ false /* halControlsIllumination */,
+ true /* resetLockoutRequiresHardwareAuthToken */,
+ listOf<SensorLocationInternal>(
+ SensorLocationInternal(
+ "" /* displayId */,
+ 540 /* sensorLocationX */,
+ 1636 /* sensorLocationY */,
+ 130 /* sensorRadius */
+ )
+ )
+ )
+ )
+
+ fingerprintAuthenticatorsCaptor.value.onAllAuthenticatorsRegistered(fingerprintProps)
+
+ assertThat(repository.sensorId.value).isEqualTo(1)
+ assertThat(repository.strength.value).isEqualTo(SensorStrength.STRONG)
+ assertThat(repository.sensorType.value).isEqualTo(FingerprintSensorType.REAR)
+ with(repository.sensorLocation.value) {
+ assertThat(displayId).isEqualTo("")
+ assertThat(sensorLocationX).isEqualTo(540)
+ assertThat(sensorLocationY).isEqualTo(1636)
+ assertThat(sensorRadius).isEqualTo(130)
+ }
+ assertThat(isInitialized()).isTrue()
+ }
+
+ private fun assertDefaultProperties() {
+ assertThat(repository.sensorId.value).isEqualTo(-1)
+ assertThat(repository.strength.value).isEqualTo(SensorStrength.CONVENIENCE)
+ assertThat(repository.sensorType.value).isEqualTo(FingerprintSensorType.UNKNOWN)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
index ebbe096..26cbd77 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
@@ -41,11 +41,11 @@
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@SmallTest
@@ -378,7 +378,13 @@
executor: DelayableExecutor,
lazyController: Lazy<ControlsController>,
userTracker: UserTracker
-) : ControlsBindingControllerImpl(context, executor, lazyController, userTracker) {
+) : ControlsBindingControllerImpl(
+ context,
+ executor,
+ lazyController,
+ mock(PackageUpdateMonitor.Factory::class.java),
+ userTracker
+) {
companion object {
val providers = mutableListOf<ControlsProviderLifecycleManager>()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
index da548f7..b5d3476 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
@@ -30,6 +30,10 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.FakeSystemClock
import org.junit.After
import org.junit.Assert.assertEquals
@@ -39,17 +43,17 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers
-import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyString
-import org.mockito.ArgumentMatchers.eq
import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.mock
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.inOrder
import org.mockito.Mockito.never
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@SmallTest
@@ -62,16 +66,21 @@
private lateinit var subscriberService: IControlsSubscriber.Stub
@Mock
private lateinit var service: IControlsProvider.Stub
-
+ @Mock
+ private lateinit var packageUpdateMonitor: PackageUpdateMonitor
@Captor
private lateinit var wrapperCaptor: ArgumentCaptor<ControlActionWrapper>
+ private lateinit var packageUpdateMonitorFactory: FakePackageUpdateMonitorFactory
+
private val componentName = ComponentName("test.pkg", "test.cls")
private lateinit var manager: ControlsProviderLifecycleManager
private lateinit var executor: FakeExecutor
+ private lateinit var fakeSystemClock: FakeSystemClock
companion object {
fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
+ private val USER = UserHandle.of(0)
}
@Before
@@ -79,16 +88,20 @@
MockitoAnnotations.initMocks(this)
context.addMockService(componentName, service)
- executor = FakeExecutor(FakeSystemClock())
+ fakeSystemClock = FakeSystemClock()
+ executor = FakeExecutor(fakeSystemClock)
`when`(service.asBinder()).thenCallRealMethod()
- `when`(service.queryLocalInterface(ArgumentMatchers.anyString())).thenReturn(service)
+ `when`(service.queryLocalInterface(anyString())).thenReturn(service)
+
+ packageUpdateMonitorFactory = FakePackageUpdateMonitorFactory(packageUpdateMonitor)
manager = ControlsProviderLifecycleManager(
context,
executor,
actionCallbackService,
- UserHandle.of(0),
- componentName
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
)
}
@@ -122,7 +135,7 @@
@Test
fun testNullBinding() {
- val mockContext = mock(Context::class.java)
+ val mockContext = mock<Context>()
lateinit var serviceConnection: ServiceConnection
`when`(mockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer {
val component = (it.arguments[0] as Intent).component
@@ -139,8 +152,9 @@
mockContext,
executor,
actionCallbackService,
- UserHandle.of(0),
- componentName
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
)
nullManager.bindService()
@@ -229,14 +243,15 @@
@Test
fun testFalseBindCallsUnbind() {
- val falseContext = mock(Context::class.java)
+ val falseContext = mock<Context>()
`when`(falseContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(false)
val manager = ControlsProviderLifecycleManager(
falseContext,
executor,
actionCallbackService,
- UserHandle.of(0),
- componentName
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
)
manager.bindService()
executor.runAllReady()
@@ -247,4 +262,150 @@
verify(falseContext).bindServiceAsUser(any(), captor.capture(), anyInt(), any())
verify(falseContext).unbindService(captor.value)
}
+
+ @Test
+ fun testPackageUpdateMonitor_createdWithCorrectValues() {
+ assertEquals(USER, packageUpdateMonitorFactory.lastUser)
+ assertEquals(componentName.packageName, packageUpdateMonitorFactory.lastPackage)
+ }
+
+ @Test
+ fun testBound_packageMonitorStartsMonitoring() {
+ manager.bindService()
+ executor.runAllReady()
+
+ // Service will connect and monitoring should start
+ verify(packageUpdateMonitor).startMonitoring()
+ }
+
+ @Test
+ fun testOnPackageUpdateWhileBound_unbound_thenBindAgain() {
+ val mockContext = mock<Context> {
+ `when`(bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true)
+ }
+
+ val manager = ControlsProviderLifecycleManager(
+ mockContext,
+ executor,
+ actionCallbackService,
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
+ )
+
+ manager.bindService()
+ executor.runAllReady()
+ clearInvocations(mockContext)
+
+ packageUpdateMonitorFactory.lastCallback?.run()
+ executor.runAllReady()
+
+ val inOrder = inOrder(mockContext)
+ inOrder.verify(mockContext).unbindService(any())
+ inOrder.verify(mockContext).bindServiceAsUser(any(), any(), anyInt(), any())
+ }
+
+ @Test
+ fun testOnPackageUpdateWhenNotBound_nothingHappens() {
+ val mockContext = mock<Context> {
+ `when`(bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true)
+ }
+
+ ControlsProviderLifecycleManager(
+ mockContext,
+ executor,
+ actionCallbackService,
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
+ )
+
+ packageUpdateMonitorFactory.lastCallback?.run()
+ verifyNoMoreInteractions(mockContext)
+ }
+
+ @Test
+ fun testUnbindService_stopsTracking() {
+ manager.bindService()
+ manager.unbindService()
+ executor.runAllReady()
+
+ verify(packageUpdateMonitor).stopMonitoring()
+ }
+
+ @Test
+ fun testRebindForPanelWithSameFlags() {
+ val mockContext = mock<Context> {
+ `when`(bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true)
+ }
+
+ val manager = ControlsProviderLifecycleManager(
+ mockContext,
+ executor,
+ actionCallbackService,
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
+ )
+
+ manager.bindServiceForPanel()
+ executor.runAllReady()
+
+ val flagsCaptor = argumentCaptor<Int>()
+ verify(mockContext).bindServiceAsUser(any(), any(), capture(flagsCaptor), any())
+ clearInvocations(mockContext)
+
+ packageUpdateMonitorFactory.lastCallback?.run()
+ executor.runAllReady()
+
+ verify(mockContext).bindServiceAsUser(any(), any(), eq(flagsCaptor.value), any())
+ }
+
+ @Test
+ fun testBindAfterSecurityExceptionWorks() {
+ val mockContext = mock<Context> {
+ `when`(bindServiceAsUser(any(), any(), anyInt(), any()))
+ .thenThrow(SecurityException("exception"))
+ }
+
+ val manager = ControlsProviderLifecycleManager(
+ mockContext,
+ executor,
+ actionCallbackService,
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
+ )
+
+ manager.bindServiceForPanel()
+ executor.runAllReady()
+
+ `when`(mockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true)
+
+ manager.bindServiceForPanel()
+ executor.runAllReady()
+
+ verify(mockContext, times(2)).bindServiceAsUser(any(), any(), anyInt(), any())
+ }
+
+ private class FakePackageUpdateMonitorFactory(
+ private val monitor: PackageUpdateMonitor
+ ) : PackageUpdateMonitor.Factory {
+
+ var lastUser: UserHandle? = null
+ var lastPackage: String? = null
+ var lastCallback: Runnable? = null
+
+ override fun create(
+ user: UserHandle,
+ packageName: String,
+ callback: Runnable
+ ): PackageUpdateMonitor {
+ lastUser = user
+ lastPackage = packageName
+ lastCallback = callback
+ return monitor
+ }
+ }
}
+
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/PackageUpdateMonitorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/PackageUpdateMonitorTest.kt
new file mode 100644
index 0000000..6954710
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/PackageUpdateMonitorTest.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.controls.controller
+
+import android.content.Context
+import android.os.Handler
+import android.os.UserHandle
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class PackageUpdateMonitorTest : SysuiTestCase() {
+
+ @Mock private lateinit var context: Context
+ @Mock private lateinit var bgHandler: Handler
+
+ private lateinit var underTest: PackageUpdateMonitor
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ }
+
+ @Test
+ fun startMonitoring_registerOnlyOnce() {
+ underTest = PackageUpdateMonitor(USER, PACKAGE, {}, bgHandler, context)
+
+ underTest.startMonitoring()
+ // There are two receivers registered
+ verify(context, times(2))
+ .registerReceiverAsUser(any(), eq(USER), any(), eq(null), eq(bgHandler))
+
+ underTest.startMonitoring()
+ verifyNoMoreInteractions(context)
+ }
+
+ @Test
+ fun stopMonitoring_unregistersOnlyOnce() {
+ underTest = PackageUpdateMonitor(USER, PACKAGE, {}, bgHandler, context)
+
+ underTest.startMonitoring()
+ clearInvocations(context)
+
+ underTest.stopMonitoring()
+ verify(context).unregisterReceiver(any())
+
+ underTest.stopMonitoring()
+ verifyNoMoreInteractions(context)
+ }
+
+ @Test
+ fun onPackageUpdated_correctPackageAndUser_callbackRuns() {
+ val callback = mock<Runnable>()
+
+ underTest = PackageUpdateMonitor(USER, PACKAGE, callback, bgHandler, context)
+
+ underTest.onPackageUpdateFinished(PACKAGE, UserHandle.getUid(USER.identifier, 10000))
+ verify(callback).run()
+ }
+
+ @Test
+ fun onPackageUpdated_correctPackage_wrongUser_callbackDoesntRun() {
+ val callback = mock<Runnable>()
+
+ underTest = PackageUpdateMonitor(USER, PACKAGE, callback, bgHandler, context)
+
+ underTest.onPackageUpdateFinished(PACKAGE, UserHandle.getUid(USER.identifier + 1, 10000))
+ verify(callback, never()).run()
+ }
+
+ @Test
+ fun onPackageUpdated_wrongPackage_correctUser_callbackDoesntRun() {
+ val callback = mock<Runnable>()
+
+ underTest = PackageUpdateMonitor(USER, PACKAGE, callback, bgHandler, context)
+
+ underTest.onPackageUpdateFinished("bad", UserHandle.getUid(USER.identifier + 1, 10000))
+ verify(callback, never()).run()
+ }
+
+ companion object {
+ private val USER = UserHandle.of(0)
+ private val PACKAGE = "pkg"
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
index c3506e8..5414259 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.controls.ui
+import android.app.ActivityOptions
import android.app.PendingIntent
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
@@ -24,7 +25,10 @@
import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
import com.android.wm.shell.taskview.TaskView
+import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -69,6 +73,25 @@
verify(taskView).startActivity(eq(pendingIntent), any(), any(), any())
}
+ @Test
+ fun testActivityOptionsAllowBal() {
+ // GIVEN the dialog is created with a PendingIntent
+ val dialog = createDialog(pendingIntent)
+
+ // WHEN the TaskView is initialized
+ dialog.stateCallback.onInitialized()
+
+ val optionsCaptor = argumentCaptor<ActivityOptions>()
+
+ // THEN the ActivityOptions have the correct flags
+ verify(taskView).startActivity(any(), any(), capture(optionsCaptor), any())
+
+ assertThat(optionsCaptor.value.pendingIntentBackgroundActivityStartMode)
+ .isEqualTo(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
+ assertThat(optionsCaptor.value.isPendingIntentBackgroundActivityLaunchAllowedByPermission)
+ .isTrue()
+ }
+
private fun createDialog(pendingIntent: PendingIntent): DetailDialog {
return DetailDialog(
mContext,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
index b7c6246..039682c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
@@ -24,6 +24,7 @@
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito.anyLong
+import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.eq
import org.mockito.Mockito.never
import org.mockito.Mockito.times
@@ -49,6 +50,7 @@
@Mock private lateinit var stateController: DreamOverlayStateController
@Mock private lateinit var configController: ConfigurationController
@Mock private lateinit var transitionViewModel: DreamingToLockscreenTransitionViewModel
+ @Mock private lateinit var logger: DreamLogger
private lateinit var controller: DreamOverlayAnimationsController
@Before
@@ -67,6 +69,7 @@
DREAM_IN_COMPLICATIONS_ANIMATION_DURATION,
DREAM_IN_TRANSLATION_Y_DISTANCE,
DREAM_IN_TRANSLATION_Y_DURATION,
+ logger
)
val mockView: View = mock()
@@ -82,9 +85,9 @@
verify(stateController).setExitAnimationsRunning(true)
val captor = argumentCaptor<Animator.AnimatorListener>()
- verify(mockAnimator).addListener(captor.capture())
+ verify(mockAnimator, atLeastOnce()).addListener(captor.capture())
- captor.value.onAnimationEnd(mockAnimator)
+ captor.allValues.forEach { it.onAnimationEnd(mockAnimator) }
verify(stateController).setExitAnimationsRunning(false)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
index 6f9dedf..fae6375 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
@@ -18,9 +18,12 @@
package com.android.systemui.keyboard.data.repository
import android.hardware.input.InputManager
+import android.hardware.input.InputManager.KeyboardBacklightListener
+import android.hardware.input.KeyboardBacklightState
import android.view.InputDevice
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.FlowValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
@@ -29,9 +32,11 @@
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -50,6 +55,7 @@
@Captor
private lateinit var deviceListenerCaptor: ArgumentCaptor<InputManager.InputDeviceListener>
+ @Captor private lateinit var backlightListenerCaptor: ArgumentCaptor<KeyboardBacklightListener>
@Mock private lateinit var inputManager: InputManager
private lateinit var underTest: KeyboardRepository
@@ -174,7 +180,71 @@
@Test
fun passesKeyboardBacklightValues_fromBacklightListener() {
- // TODO(b/268645734): implement when implementing backlight listener
+ testScope.runTest {
+ // we want to capture backlight listener but this can only be done after Flow is
+ // subscribed to and listener is actually registered in inputManager
+ val backlight by collectLastValueImmediately(underTest.backlight)
+
+ verify(inputManager)
+ .registerKeyboardBacklightListener(any(), backlightListenerCaptor.capture())
+
+ backlightListenerCaptor.value.onBacklightChanged(current = 1, max = 5)
+
+ assertThat(backlight?.level).isEqualTo(1)
+ assertThat(backlight?.maxLevel).isEqualTo(5)
+ }
+ }
+
+ private fun <T> TestScope.collectLastValueImmediately(flow: Flow<T>): FlowValue<T?> {
+ val lastValue = collectLastValue(flow)
+ // runCurrent() makes us wait for collect that happens in collectLastValue and ensures
+ // Flow is initialized
+ runCurrent()
+ return lastValue
+ }
+
+ @Test
+ fun keyboardBacklightValuesNotPassed_fromBacklightListener_whenNotTriggeredByKeyPress() {
+ testScope.runTest() {
+ val backlight by collectLastValueImmediately(underTest.backlight)
+ verify(inputManager)
+ .registerKeyboardBacklightListener(any(), backlightListenerCaptor.capture())
+
+ backlightListenerCaptor.value.onBacklightChanged(
+ current = 1,
+ max = 5,
+ triggeredByKeyPress = false
+ )
+ assertThat(backlight).isNull()
+ }
+ }
+
+ @Test
+ fun passesKeyboardBacklightValues_fromBacklightListener_whenTriggeredByKeyPress() {
+ testScope.runTest() {
+ val backlight by collectLastValueImmediately(underTest.backlight)
+ verify(inputManager)
+ .registerKeyboardBacklightListener(any(), backlightListenerCaptor.capture())
+
+ backlightListenerCaptor.value.onBacklightChanged(
+ current = 1,
+ max = 5,
+ triggeredByKeyPress = true
+ )
+ assertThat(backlight).isNotNull()
+ }
+ }
+
+ private fun KeyboardBacklightListener.onBacklightChanged(
+ current: Int,
+ max: Int,
+ triggeredByKeyPress: Boolean = true
+ ) {
+ onKeyboardBacklightChanged(
+ /* deviceId= */ 0,
+ TestBacklightState(current, max),
+ triggeredByKeyPress
+ )
}
private companion object {
@@ -199,4 +269,12 @@
whenever(it.isFullKeyboard).thenReturn(fullKeyboard)
}
}
+
+ private class TestBacklightState(
+ private val brightnessLevel: Int,
+ private val maxBrightnessLevel: Int
+ ) : KeyboardBacklightState() {
+ override fun getBrightnessLevel() = brightnessLevel
+ override fun getMaxBrightnessLevel() = maxBrightnessLevel
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
index b46d996..f8cb408 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
@@ -19,7 +19,6 @@
import androidx.test.filters.SmallTest
import com.android.systemui.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.controller.ControlsController
@@ -46,7 +45,6 @@
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(Parameterized::class)
class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index b50cf73..1d0b58a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -67,6 +67,7 @@
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.util.mockito.KotlinArgumentCaptor
import com.android.systemui.util.mockito.captureMany
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.time.SystemClock
@@ -193,8 +194,24 @@
bypassControllerOverride: KeyguardBypassController? = bypassController
): DeviceEntryFaceAuthRepositoryImpl {
val systemClock = FakeSystemClock()
- val faceAuthBuffer = TableLogBuffer(10, "face auth", systemClock)
- val faceDetectBuffer = TableLogBuffer(10, "face detect", systemClock)
+ val faceAuthBuffer =
+ TableLogBuffer(
+ 10,
+ "face auth",
+ systemClock,
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope
+ )
+ val faceDetectBuffer =
+ TableLogBuffer(
+ 10,
+ "face detect",
+ systemClock,
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope
+ )
keyguardTransitionRepository = FakeKeyguardTransitionRepository()
val keyguardTransitionInteractor =
KeyguardTransitionInteractor(keyguardTransitionRepository)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
index f4d2843..d0bfaa9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
@@ -23,7 +23,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.FlakyTest
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Interpolators
import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -48,7 +47,6 @@
import org.junit.runner.RunWith
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@FlakyTest(bugId = 270760395)
class KeyguardTransitionRepositoryTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/FakeLogProxy.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/FakeLogProxy.kt
new file mode 100644
index 0000000..471c461
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/FakeLogProxy.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log.table
+
+/**
+ * Fake [LogProxy] that collects all lines sent to it. Mimics the ADB logcat format without the
+ * timestamp. [FakeLogProxy.d] will write a log like so:
+ * ```
+ * logger.d("TAG", "message here")
+ * // writes this to the [logs] field
+ * "D TAG: message here"
+ * ```
+ *
+ * Logs sent to this class are collected as a list of strings for simple test assertions.
+ */
+class FakeLogProxy : LogProxy {
+ val logs: MutableList<String> = mutableListOf()
+
+ override fun v(tag: String, message: String) {
+ logs.add("V $tag: $message")
+ }
+
+ override fun d(tag: String, message: String) {
+ logs.add("D $tag: $message")
+ }
+
+ override fun i(tag: String, message: String) {
+ logs.add("I $tag: $message")
+ }
+
+ override fun w(tag: String, message: String) {
+ logs.add("W $tag: $message")
+ }
+
+ override fun e(tag: String, message: String) {
+ logs.add("E $tag: $message")
+ }
+
+ override fun wtf(tag: String, message: String) {
+ logs.add("WTF $tag: $message")
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
index c49337a..1d182cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
@@ -19,6 +19,7 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
@@ -39,7 +40,8 @@
@OptIn(ExperimentalCoroutinesApi::class)
class LogDiffsForTableTest : SysuiTestCase() {
- private val testScope = TestScope(UnconfinedTestDispatcher())
+ private val testDispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
private lateinit var systemClock: FakeSystemClock
private lateinit var tableLogBuffer: TableLogBuffer
@@ -47,7 +49,15 @@
@Before
fun setUp() {
systemClock = FakeSystemClock()
- tableLogBuffer = TableLogBuffer(MAX_SIZE, BUFFER_NAME, systemClock)
+ tableLogBuffer =
+ TableLogBuffer(
+ MAX_SIZE,
+ BUFFER_NAME,
+ systemClock,
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
}
// ---- Flow<Boolean> tests ----
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
index af83a56..8ba7643 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
@@ -22,13 +22,20 @@
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import org.junit.Test
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
class TableLogBufferFactoryTest : SysuiTestCase() {
private val dumpManager: DumpManager = mock()
private val systemClock = FakeSystemClock()
- private val underTest = TableLogBufferFactory(dumpManager, systemClock)
+ private val testDispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
+ private val underTest =
+ TableLogBufferFactory(dumpManager, systemClock, mock(), testDispatcher, testScope)
@Test
fun create_alwaysCreatesNewInstance() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
index aed830a..a2b2322 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
@@ -19,31 +19,66 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
import java.io.StringWriter
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import org.junit.Before
import org.junit.Test
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
class TableLogBufferTest : SysuiTestCase() {
private lateinit var underTest: TableLogBuffer
private lateinit var systemClock: FakeSystemClock
private lateinit var outputWriter: StringWriter
+ private lateinit var logcatEchoTracker: LogcatEchoTracker
+ private lateinit var localLogcat: FakeLogProxy
+
+ private val testDispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
@Before
fun setup() {
+ localLogcat = FakeLogProxy()
+ logcatEchoTracker = mock()
systemClock = FakeSystemClock()
outputWriter = StringWriter()
- underTest = TableLogBuffer(MAX_SIZE, NAME, systemClock)
+ underTest =
+ TableLogBuffer(
+ MAX_SIZE,
+ NAME,
+ systemClock,
+ logcatEchoTracker,
+ testDispatcher,
+ testScope.backgroundScope,
+ localLogcat = localLogcat,
+ )
+ underTest.init()
}
@Test(expected = IllegalArgumentException::class)
fun maxSizeZero_throwsException() {
- TableLogBuffer(maxSize = 0, "name", systemClock)
+ TableLogBuffer(
+ maxSize = 0,
+ "name",
+ systemClock,
+ logcatEchoTracker,
+ testDispatcher,
+ testScope.backgroundScope,
+ localLogcat = localLogcat,
+ )
}
@Test
@@ -791,6 +826,112 @@
assertThat(dumpedString).contains(evictedColumnLog3)
}
+ @Test
+ fun logcat_bufferNotLoggable_tagNotLoggable_noEcho() {
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), any())).thenReturn(false)
+ whenever(logcatEchoTracker.isTagLoggable(eq("columnName"), any())).thenReturn(false)
+
+ underTest.logChange("prefix", "columnName", true)
+
+ assertThat(localLogcat.logs).isEmpty()
+ }
+
+ @Test
+ fun logcat_bufferIsLoggable_tagNotLoggable_echoes() {
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), any())).thenReturn(true)
+ whenever(logcatEchoTracker.isTagLoggable(eq("columnName"), any())).thenReturn(false)
+
+ underTest.logChange("prefix", "columnName", true)
+
+ assertThat(localLogcat.logs).hasSize(1)
+ }
+
+ @Test
+ fun logcat_bufferNotLoggable_tagIsLoggable_echoes() {
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), any())).thenReturn(false)
+ whenever(logcatEchoTracker.isTagLoggable(eq("columnName"), any())).thenReturn(true)
+
+ underTest.logChange("prefix", "columnName", true)
+
+ assertThat(localLogcat.logs).hasSize(1)
+ }
+
+ @Test
+ fun logcat_echoesDebugLogs_debugDisabled_noEcho() {
+ // Allow any log other than debug
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), any())).thenAnswer { invocation ->
+ (invocation.getArgument(1) as LogLevel) != LogLevel.DEBUG
+ }
+
+ underTest.logChange("prefix", "columnName", true)
+
+ assertThat(localLogcat.logs).isEmpty()
+ }
+
+ @Test
+ fun logcat_echoesDebugLogs_debugEnabled_echoes() {
+ // Only allow debug logs
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), eq(LogLevel.DEBUG))).thenReturn(true)
+
+ underTest.logChange("prefix", "columnName", true)
+
+ assertThat(localLogcat.logs).hasSize(1)
+ }
+
+ @Test
+ fun logcat_bufferNotLoggable_tagIsLoggable_usesColNameForTagCheck() {
+ systemClock.setCurrentTimeMillis(1000L)
+
+ val nonLoggingTag = "nonLoggingColName"
+ val loggingTag = "loggingColName"
+
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), any())).thenReturn(false)
+ whenever(logcatEchoTracker.isTagLoggable(eq(loggingTag), eq(LogLevel.DEBUG)))
+ .thenReturn(true)
+ whenever(logcatEchoTracker.isTagLoggable(eq(nonLoggingTag), eq(LogLevel.DEBUG)))
+ .thenReturn(false)
+
+ underTest.logChange("", nonLoggingTag, true)
+ underTest.logChange("", loggingTag, true)
+
+ assertThat(localLogcat.logs).hasSize(1)
+
+ val timestamp = TABLE_LOG_DATE_FORMAT.format(1000L)
+ val expectedMessage = "${timestamp}${SEPARATOR}${loggingTag}${SEPARATOR}true"
+ val expectedLine = "D $NAME: $expectedMessage"
+
+ assertThat(localLogcat.logs[0]).isEqualTo(expectedLine)
+ }
+
+ @Test
+ fun logcat_bufferLoggable_multipleMessagesAreEchoed() {
+ systemClock.setCurrentTimeMillis(1000L)
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), any())).thenReturn(true)
+
+ val col1 = "column1"
+ val col2 = "column2"
+
+ // Log a couple of columns that flip bits
+ underTest.logChange("", col1, true)
+ underTest.logChange("", col2, false)
+ underTest.logChange("", col1, false)
+ underTest.logChange("", col2, true)
+
+ assertThat(localLogcat.logs).hasSize(4)
+
+ val timestamp = TABLE_LOG_DATE_FORMAT.format(1000L)
+ val msg1 = "${timestamp}${SEPARATOR}${col1}${SEPARATOR}true"
+ val msg2 = "${timestamp}${SEPARATOR}${col2}${SEPARATOR}false"
+ val msg3 = "${timestamp}${SEPARATOR}${col1}${SEPARATOR}false"
+ val msg4 = "${timestamp}${SEPARATOR}${col2}${SEPARATOR}true"
+ val expected = listOf(msg1, msg2, msg3, msg4).map { "D $NAME: $it" }
+
+ // Logs use the same bg dispatcher for writing to logcat, they should be in order
+ for ((msg, logLine) in expected zip localLogcat.logs) {
+ assertThat(logLine).isEqualTo(msg)
+ }
+ }
+
private fun dumpChanges(): String {
underTest.dump(PrintWriter(outputWriter), arrayOf())
return outputWriter.toString()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDeviceManagerTest.kt
index a45e9d9..0c57e7b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDeviceManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDeviceManagerTest.kt
@@ -468,7 +468,7 @@
}
@Test
- fun audioInfoChanged() {
+ fun audioInfoPlaybackTypeChanged() {
whenever(playbackInfo.getPlaybackType()).thenReturn(PlaybackInfo.PLAYBACK_TYPE_LOCAL)
whenever(controller.getPlaybackInfo()).thenReturn(playbackInfo)
// GIVEN a controller with local playback type
@@ -486,6 +486,25 @@
}
@Test
+ fun audioInfoVolumeControlIdChanged() {
+ whenever(playbackInfo.getPlaybackType()).thenReturn(PlaybackInfo.PLAYBACK_TYPE_LOCAL)
+ whenever(playbackInfo.getVolumeControlId()).thenReturn(null)
+ whenever(controller.getPlaybackInfo()).thenReturn(playbackInfo)
+ // GIVEN a controller with local playback type
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+ reset(mr2)
+ // WHEN onAudioInfoChanged fires with a volume control id change
+ whenever(playbackInfo.getVolumeControlId()).thenReturn("placeholder id")
+ val captor = ArgumentCaptor.forClass(MediaController.Callback::class.java)
+ verify(controller).registerCallback(captor.capture())
+ captor.value.onAudioInfoChanged(playbackInfo)
+ // THEN the route is checked
+ verify(mr2).getRoutingSessionForMediaController(eq(controller))
+ }
+
+ @Test
fun audioInfoHasntChanged() {
whenever(playbackInfo.getPlaybackType()).thenReturn(PlaybackInfo.PLAYBACK_TYPE_REMOTE)
whenever(controller.getPlaybackInfo()).thenReturn(playbackInfo)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
index 1a00ac2..07f7c15 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
@@ -17,7 +17,9 @@
package com.android.systemui.media.controls.ui
import android.app.PendingIntent
+import android.content.res.ColorStateList
import android.content.res.Configuration
+import android.os.LocaleList
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.util.MathUtils.abs
@@ -26,6 +28,7 @@
import com.android.internal.logging.InstanceId
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dagger.qualifiers.Main
@@ -50,9 +53,11 @@
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
+import java.util.Locale
import javax.inject.Provider
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
@@ -68,6 +73,7 @@
import org.mockito.Mock
import org.mockito.Mockito.floatThat
import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
@@ -77,6 +83,8 @@
private val DATA = MediaTestUtils.emptyMediaData
private val SMARTSPACE_KEY = "smartspace"
+private const val PAUSED_LOCAL = "paused local"
+private const val PLAYING_LOCAL = "playing local"
@SmallTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@@ -118,6 +126,7 @@
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
+ context.resources.configuration.locales = LocaleList(Locale.US, Locale.UK)
transitionRepository = FakeKeyguardTransitionRepository()
mediaCarouselController =
MediaCarouselController(
@@ -157,7 +166,7 @@
// Test values: key, data, last active time
val playingLocal =
Triple(
- "playing local",
+ PLAYING_LOCAL,
DATA.copy(
active = true,
isPlaying = true,
@@ -181,7 +190,7 @@
val pausedLocal =
Triple(
- "paused local",
+ PAUSED_LOCAL,
DATA.copy(
active = true,
isPlaying = false,
@@ -384,8 +393,8 @@
testPlayerOrdering()
// playing paused player
listener.value.onMediaDataLoaded(
- "paused local",
- "paused local",
+ PAUSED_LOCAL,
+ PAUSED_LOCAL,
DATA.copy(
active = true,
isPlaying = true,
@@ -394,8 +403,8 @@
)
)
listener.value.onMediaDataLoaded(
- "playing local",
- "playing local",
+ PLAYING_LOCAL,
+ PLAYING_LOCAL,
DATA.copy(
active = true,
isPlaying = false,
@@ -405,7 +414,7 @@
)
assertEquals(
- MediaPlayerData.getMediaPlayerIndex("paused local"),
+ MediaPlayerData.getMediaPlayerIndex(PAUSED_LOCAL),
mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
)
// paused player order should stays the same in visibleMediaPLayer map.
@@ -486,7 +495,7 @@
@Test
fun testMediaLoaded_ScrollToActivePlayer() {
listener.value.onMediaDataLoaded(
- "playing local",
+ PLAYING_LOCAL,
null,
DATA.copy(
active = true,
@@ -496,7 +505,7 @@
)
)
listener.value.onMediaDataLoaded(
- "paused local",
+ PAUSED_LOCAL,
null,
DATA.copy(
active = true,
@@ -514,8 +523,8 @@
mediaCarouselController.shouldScrollToKey = true
// switching between media players.
listener.value.onMediaDataLoaded(
- "playing local",
- "playing local",
+ PLAYING_LOCAL,
+ PLAYING_LOCAL,
DATA.copy(
active = true,
isPlaying = false,
@@ -524,8 +533,8 @@
)
)
listener.value.onMediaDataLoaded(
- "paused local",
- "paused local",
+ PAUSED_LOCAL,
+ PAUSED_LOCAL,
DATA.copy(
active = true,
isPlaying = true,
@@ -535,7 +544,7 @@
)
assertEquals(
- MediaPlayerData.getMediaPlayerIndex("paused local"),
+ MediaPlayerData.getMediaPlayerIndex(PAUSED_LOCAL),
mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
)
}
@@ -548,7 +557,7 @@
false
)
listener.value.onMediaDataLoaded(
- "playing local",
+ PLAYING_LOCAL,
null,
DATA.copy(
active = true,
@@ -558,7 +567,7 @@
)
)
- var playerIndex = MediaPlayerData.getMediaPlayerIndex("playing local")
+ var playerIndex = MediaPlayerData.getMediaPlayerIndex(PLAYING_LOCAL)
assertEquals(
playerIndex,
mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
@@ -569,7 +578,7 @@
// And check that the card stays in its position.
mediaCarouselController.shouldScrollToKey = true
listener.value.onMediaDataLoaded(
- "playing local",
+ PLAYING_LOCAL,
null,
DATA.copy(
active = true,
@@ -579,7 +588,7 @@
packageName = "PACKAGE_NAME"
)
)
- playerIndex = MediaPlayerData.getMediaPlayerIndex("playing local")
+ playerIndex = MediaPlayerData.getMediaPlayerIndex(PLAYING_LOCAL)
assertEquals(playerIndex, 0)
}
@@ -676,36 +685,52 @@
@Test
fun testOnConfigChanged_playersAreAddedBack() {
- listener.value.onMediaDataLoaded(
- "playing local",
- null,
- DATA.copy(
- active = true,
- isPlaying = true,
- playbackLocation = MediaData.PLAYBACK_LOCAL,
- resumption = false
- )
- )
- listener.value.onMediaDataLoaded(
- "paused local",
- null,
- DATA.copy(
- active = true,
- isPlaying = false,
- playbackLocation = MediaData.PLAYBACK_LOCAL,
- resumption = false
- )
- )
+ testConfigurationChange { configListener.value.onConfigChanged(Configuration()) }
+ }
- val playersSize = MediaPlayerData.players().size
+ @Test
+ fun testOnUiModeChanged_playersAreAddedBack() {
+ testConfigurationChange(configListener.value::onUiModeChanged)
- configListener.value.onConfigChanged(Configuration())
+ verify(pageIndicator).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+ verify(pageIndicator, times(2)).setNumPages(any())
+ }
- assertEquals(playersSize, MediaPlayerData.players().size)
- assertEquals(
- MediaPlayerData.getMediaPlayerIndex("playing local"),
- mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
- )
+ @Test
+ fun testOnDensityOrFontScaleChanged_playersAreAddedBack() {
+ testConfigurationChange(configListener.value::onDensityOrFontScaleChanged)
+
+ verify(pageIndicator).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+ // when recreateMedia is set to true, page indicator is updated on removal and addition.
+ verify(pageIndicator, times(4)).setNumPages(any())
+ }
+
+ @Test
+ fun testOnThemeChanged_playersAreAddedBack() {
+ testConfigurationChange(configListener.value::onThemeChanged)
+
+ verify(pageIndicator).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+ verify(pageIndicator, times(2)).setNumPages(any())
+ }
+
+ @Test
+ fun testOnLocaleListChanged_playersAreAddedBack() {
+ context.resources.configuration.locales = LocaleList(Locale.US, Locale.UK, Locale.CANADA)
+ testConfigurationChange(configListener.value::onLocaleListChanged)
+
+ verify(pageIndicator, never()).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+
+ context.resources.configuration.locales = LocaleList(Locale.UK, Locale.US, Locale.CANADA)
+ testConfigurationChange(configListener.value::onLocaleListChanged)
+
+ verify(pageIndicator).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+ // When recreateMedia is set to true, page indicator is updated on removal and addition.
+ verify(pageIndicator, times(4)).setNumPages(any())
}
@Test
@@ -846,4 +871,43 @@
// Then the carousel visibility is updated
assertTrue(stateUpdated)
}
+
+ /**
+ * Helper method when a configuration change occurs.
+ *
+ * @param function called when a certain configuration change occurs.
+ */
+ private fun testConfigurationChange(function: () -> Unit) {
+ mediaCarouselController.pageIndicator = pageIndicator
+ listener.value.onMediaDataLoaded(
+ PLAYING_LOCAL,
+ null,
+ DATA.copy(
+ active = true,
+ isPlaying = true,
+ playbackLocation = MediaData.PLAYBACK_LOCAL,
+ resumption = false
+ )
+ )
+ listener.value.onMediaDataLoaded(
+ PAUSED_LOCAL,
+ null,
+ DATA.copy(
+ active = true,
+ isPlaying = false,
+ playbackLocation = MediaData.PLAYBACK_LOCAL,
+ resumption = false
+ )
+ )
+
+ val playersSize = MediaPlayerData.players().size
+ reset(pageIndicator)
+ function()
+
+ assertEquals(playersSize, MediaPlayerData.players().size)
+ assertEquals(
+ MediaPlayerData.getMediaPlayerIndex(PLAYING_LOCAL),
+ mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
+ )
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index 0bdcaf4..299303d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -19,6 +19,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
@@ -33,7 +34,12 @@
import android.app.KeyguardManager;
import android.app.Notification;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.media.AudioDeviceAttributes;
import android.media.AudioManager;
@@ -44,6 +50,7 @@
import android.media.RoutingSessionInfo;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
+import android.media.session.PlaybackState;
import android.os.PowerExemptionManager;
import android.os.RemoteException;
import android.service.notification.StatusBarNotification;
@@ -74,6 +81,9 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
@@ -93,29 +103,54 @@
private static final String TEST_SONG = "test_song";
private static final String TEST_SESSION_ID = "test_session_id";
private static final String TEST_SESSION_NAME = "test_session_name";
- private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
- private final ActivityLaunchAnimator.Controller mActivityLaunchAnimatorController = mock(
- ActivityLaunchAnimator.Controller.class);
- private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock(
- NearbyMediaDevicesManager.class);
+ @Mock
+ private DialogLaunchAnimator mDialogLaunchAnimator;
+ @Mock
+ private ActivityLaunchAnimator.Controller mActivityLaunchAnimatorController;
+ @Mock
+ private NearbyMediaDevicesManager mNearbyMediaDevicesManager;
// Mock
- private MediaController mMediaController = mock(MediaController.class);
- private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class);
- private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager =
- mock(CachedBluetoothDeviceManager.class);
- private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class);
- private MediaOutputController.Callback mCb = mock(MediaOutputController.Callback.class);
- private MediaDevice mMediaDevice1 = mock(MediaDevice.class);
- private MediaDevice mMediaDevice2 = mock(MediaDevice.class);
- private NearbyDevice mNearbyDevice1 = mock(NearbyDevice.class);
- private NearbyDevice mNearbyDevice2 = mock(NearbyDevice.class);
- private MediaMetadata mMediaMetadata = mock(MediaMetadata.class);
- private RoutingSessionInfo mRemoteSessionInfo = mock(RoutingSessionInfo.class);
- private ActivityStarter mStarter = mock(ActivityStarter.class);
- private AudioManager mAudioManager = mock(AudioManager.class);
- private KeyguardManager mKeyguardManager = mock(KeyguardManager.class);
- private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class);
- private CommonNotifCollection mNotifCollection = mock(CommonNotifCollection.class);
+ @Mock
+ private MediaController mMediaController;
+ @Mock
+ private MediaSessionManager mMediaSessionManager;
+ @Mock
+ private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager;
+ @Mock
+ private LocalBluetoothManager mLocalBluetoothManager;
+ @Mock
+ private MediaOutputController.Callback mCb;
+ @Mock
+ private MediaDevice mMediaDevice1;
+ @Mock
+ private MediaDevice mMediaDevice2;
+ @Mock
+ private NearbyDevice mNearbyDevice1;
+ @Mock
+ private NearbyDevice mNearbyDevice2;
+ @Mock
+ private MediaMetadata mMediaMetadata;
+ @Mock
+ private RoutingSessionInfo mRemoteSessionInfo;
+ @Mock
+ private ActivityStarter mStarter;
+ @Mock
+ private AudioManager mAudioManager;
+ @Mock
+ private KeyguardManager mKeyguardManager;
+ @Mock
+ private ActivityLaunchAnimator.Controller mController;
+ @Mock
+ private PowerExemptionManager mPowerExemptionManager;
+ @Mock
+ private CommonNotifCollection mNotifCollection;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private Drawable mDrawable;
+ @Mock
+ private PlaybackState mPlaybackState;
+
private FeatureFlags mFlags = mock(FeatureFlags.class);
private View mDialogLaunchView = mock(View.class);
private MediaOutputController.Callback mCallback = mock(MediaOutputController.Callback.class);
@@ -131,8 +166,11 @@
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext.setMockPackageManager(mPackageManager);
mSpyContext = spy(mContext);
when(mMediaController.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
mMediaControllers.add(mMediaController);
when(mMediaSessionManager.getActiveSessions(any())).thenReturn(mMediaControllers);
doReturn(mMediaSessionManager).when(mSpyContext).getSystemService(
@@ -258,6 +296,34 @@
}
@Test
+ public void tryToLaunchMediaApplication_intentNotNull_startActivity() {
+ when(mDialogLaunchAnimator.createActivityLaunchController(any(View.class))).thenReturn(
+ mController);
+ Intent intent = new Intent(TEST_PACKAGE_NAME);
+ doReturn(intent).when(mPackageManager).getLaunchIntentForPackage(TEST_PACKAGE_NAME);
+ mMediaOutputController.start(mCallback);
+
+ mMediaOutputController.tryToLaunchMediaApplication(mDialogLaunchView);
+
+ verify(mStarter).startActivity(any(Intent.class), anyBoolean(),
+ Mockito.eq(mController));
+ }
+
+ @Test
+ public void tryToLaunchInAppRoutingIntent_componentNameNotNull_startActivity() {
+ when(mDialogLaunchAnimator.createActivityLaunchController(any(View.class))).thenReturn(
+ mController);
+ mMediaOutputController.start(mCallback);
+ when(mLocalMediaManager.getLinkedItemComponentName()).thenReturn(
+ new ComponentName(TEST_PACKAGE_NAME, ""));
+
+ mMediaOutputController.tryToLaunchInAppRoutingIntent(TEST_DEVICE_1_ID, mDialogLaunchView);
+
+ verify(mStarter).startActivity(any(Intent.class), anyBoolean(),
+ Mockito.eq(mController));
+ }
+
+ @Test
public void onDevicesUpdated_unregistersNearbyDevicesCallback() throws RemoteException {
mMediaOutputController.start(mCb);
@@ -342,6 +408,30 @@
}
@Test
+ public void advanced_onDeviceListUpdateWithConnectedDeviceRemote_verifyItemSize() {
+ when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT)).thenReturn(true);
+ when(mMediaDevice1.getFeatures()).thenReturn(
+ ImmutableList.of(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK));
+ when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice1);
+ mMediaOutputController.start(mCb);
+ reset(mCb);
+
+ mMediaOutputController.onDeviceListUpdate(mMediaDevices);
+ final List<MediaDevice> devices = new ArrayList<>();
+ for (MediaItem item : mMediaOutputController.getMediaItemList()) {
+ if (item.getMediaDevice().isPresent()) {
+ devices.add(item.getMediaDevice().get());
+ }
+ }
+
+ assertThat(devices.containsAll(mMediaDevices)).isTrue();
+ assertThat(devices.size()).isEqualTo(mMediaDevices.size());
+ assertThat(mMediaOutputController.getMediaItemList().size()).isEqualTo(
+ mMediaDevices.size() + 1);
+ verify(mCb).onDeviceListChanged();
+ }
+
+ @Test
public void advanced_categorizeMediaItems_withSuggestedDevice_verifyDeviceListSize() {
when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT)).thenReturn(true);
when(mMediaDevice1.isSuggestedDevice()).thenReturn(true);
@@ -582,6 +672,17 @@
}
@Test
+ public void isAnyDeviceTransferring_advancedLayoutSupport() {
+ when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT)).thenReturn(true);
+ when(mMediaDevice1.getState()).thenReturn(
+ LocalMediaManager.MediaDeviceState.STATE_CONNECTING);
+ mMediaOutputController.start(mCb);
+ mMediaOutputController.onDeviceListUpdate(mMediaDevices);
+
+ assertThat(mMediaOutputController.isAnyDeviceTransferring()).isTrue();
+ }
+
+ @Test
public void isPlaying_stateIsNull() {
when(mMediaController.getPlaybackState()).thenReturn(null);
@@ -661,22 +762,6 @@
}
@Test
- public void connectDevice_verifyConnect() {
- when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2);
-
- mMediaOutputController.connectDevice(mMediaDevice1);
-
- // Wait for background thread execution
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- verify(mLocalMediaManager).connectDevice(mMediaDevice1);
- }
-
- @Test
public void getActiveRemoteMediaDevice_isSystemSession_returnSession() {
when(mRemoteSessionInfo.getId()).thenReturn(TEST_SESSION_ID);
when(mRemoteSessionInfo.getName()).thenReturn(TEST_SESSION_NAME);
@@ -883,6 +968,56 @@
}
@Test
+ public void getDeviceIconCompat_deviceIconIsNotNull_returnsIcon() {
+ when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2);
+ when(mMediaDevice1.getIcon()).thenReturn(mDrawable);
+
+ assertThat(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).isInstanceOf(
+ IconCompat.class);
+ }
+
+ @Test
+ public void getDeviceIconCompat_deviceIconIsNull_returnsIcon() {
+ when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2);
+ when(mMediaDevice1.getIcon()).thenReturn(null);
+
+ assertThat(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).isInstanceOf(
+ IconCompat.class);
+ }
+
+ @Test
+ public void setColorFilter_setColorFilterToDrawable() {
+ mMediaOutputController.setColorFilter(mDrawable, true);
+
+ verify(mDrawable).setColorFilter(any(PorterDuffColorFilter.class));
+ }
+
+ @Test
+ public void resetGroupMediaDevices_clearGroupDevices() {
+ final MediaDevice selectedMediaDevice1 = mock(MediaDevice.class);
+ final MediaDevice selectedMediaDevice2 = mock(MediaDevice.class);
+ final MediaDevice selectableMediaDevice1 = mock(MediaDevice.class);
+ final MediaDevice selectableMediaDevice2 = mock(MediaDevice.class);
+ final List<MediaDevice> selectedMediaDevices = new ArrayList<>();
+ final List<MediaDevice> selectableMediaDevices = new ArrayList<>();
+ when(selectedMediaDevice1.getId()).thenReturn(TEST_DEVICE_1_ID);
+ when(selectedMediaDevice2.getId()).thenReturn(TEST_DEVICE_2_ID);
+ when(selectableMediaDevice1.getId()).thenReturn(TEST_DEVICE_3_ID);
+ when(selectableMediaDevice2.getId()).thenReturn(TEST_DEVICE_4_ID);
+ selectedMediaDevices.add(selectedMediaDevice1);
+ selectedMediaDevices.add(selectedMediaDevice2);
+ selectableMediaDevices.add(selectableMediaDevice1);
+ selectableMediaDevices.add(selectableMediaDevice2);
+ doReturn(selectedMediaDevices).when(mLocalMediaManager).getSelectedMediaDevice();
+ doReturn(selectableMediaDevices).when(mLocalMediaManager).getSelectableMediaDevice();
+ assertThat(mMediaOutputController.getGroupMediaDevices().isEmpty()).isFalse();
+
+ mMediaOutputController.resetGroupMediaDevices();
+
+ assertThat(mMediaOutputController.mGroupMediaDevices.isEmpty()).isTrue();
+ }
+
+ @Test
public void isVolumeControlEnabled_isCastWithVolumeFixed_returnsFalse() {
when(mMediaDevice1.getDeviceType()).thenReturn(
MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE);
@@ -919,6 +1054,42 @@
}
@Test
+ public void setTemporaryAllowListExceptionIfNeeded_packageNameIsNull_NoAction() {
+ MediaOutputController testMediaOutputController = new MediaOutputController(mSpyContext,
+ null,
+ mMediaSessionManager, mLocalBluetoothManager, mStarter,
+ mNotifCollection, mDialogLaunchAnimator,
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
+ mKeyguardManager, mFlags);
+
+ testMediaOutputController.setTemporaryAllowListExceptionIfNeeded(mMediaDevice2);
+
+ verify(mPowerExemptionManager, never()).addToTemporaryAllowList(anyString(), anyInt(),
+ anyString(),
+ anyLong());
+ }
+
+ @Test
+ public void onMetadataChanged_triggersOnMetadataChanged() {
+ mMediaOutputController.mCallback = this.mCallback;
+
+ mMediaOutputController.mCb.onMetadataChanged(mMediaMetadata);
+
+ verify(mMediaOutputController.mCallback).onMediaChanged();
+ }
+
+ @Test
+ public void onPlaybackStateChanged_updateWithNullState_onMediaStoppedOrPaused() {
+ when(mPlaybackState.getState()).thenReturn(PlaybackState.STATE_PLAYING);
+ mMediaOutputController.mCallback = this.mCallback;
+ mMediaOutputController.start(mCb);
+
+ mMediaOutputController.mCb.onPlaybackStateChanged(null);
+
+ verify(mMediaOutputController.mCallback).onMediaStoppedOrPaused();
+ }
+
+ @Test
public void launchBluetoothPairing_isKeyguardLocked_dismissDialog() {
when(mDialogLaunchAnimator.createActivityLaunchController(mDialogLaunchView)).thenReturn(
mActivityLaunchAnimatorController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
index fb5197e..4ce32d2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/DynamicColorTest.java
@@ -17,18 +17,16 @@
package com.android.systemui.monet;
import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
-
import static org.junit.Assert.assertTrue;
-
import androidx.test.filters.SmallTest;
-import com.android.systemui.SysuiTestCase;
import com.android.systemui.monet.contrast.Contrast;
import com.android.systemui.monet.dynamiccolor.DynamicColor;
import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors;
import com.android.systemui.monet.dynamiccolor.ToneDeltaConstraint;
import com.android.systemui.monet.dynamiccolor.TonePolarity;
+import com.android.systemui.SysuiTestCase;
import com.android.systemui.monet.hct.Hct;
import com.android.systemui.monet.scheme.DynamicScheme;
import com.android.systemui.monet.scheme.SchemeContent;
@@ -36,182 +34,174 @@
import com.android.systemui.monet.scheme.SchemeMonochrome;
import com.android.systemui.monet.scheme.SchemeTonalSpot;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+@Ignore("b/279581953")
@SmallTest
@RunWith(JUnit4.class)
-public final class DynamicColorTest extends SysuiTestCase {
+public final class DynamicColorTest extends SysuiTestCase{
- @Test
- public void fromArgbNoBackground_doesntChangeForContrast() {
- final int blueArgb = 0xff0000ff;
- final DynamicColor dynamicColor = DynamicColor.fromArgb(blueArgb);
+ private final MaterialDynamicColors dynamicColors = new MaterialDynamicColors();
- final SchemeTonalSpot standardContrast = new SchemeTonalSpot(Hct.fromInt(blueArgb), false,
- 0.0);
- assertThat(dynamicColor.getArgb(standardContrast)).isSameColorAs(blueArgb);
+ @Test
+ public void fromArgbNoBackground_doesntChangeForContrast() {
+ final int blueArgb = 0xff0000ff;
+ final DynamicColor dynamicColor = DynamicColor.fromArgb(blueArgb);
- final SchemeTonalSpot minContrast = new SchemeTonalSpot(Hct.fromInt(blueArgb), false, -1.0);
- assertThat(dynamicColor.getArgb(minContrast)).isSameColorAs(blueArgb);
+ final SchemeTonalSpot standardContrast = new SchemeTonalSpot(Hct.fromInt(blueArgb), false, 0.0);
+ assertThat(dynamicColor.getArgb(standardContrast)).isSameColorAs(blueArgb);
- final SchemeTonalSpot maxContrast = new SchemeTonalSpot(Hct.fromInt(blueArgb), false, 1.0);
- assertThat(dynamicColor.getArgb(maxContrast)).isSameColorAs(blueArgb);
- }
+ final SchemeTonalSpot minContrast = new SchemeTonalSpot(Hct.fromInt(blueArgb), false, -1.0);
+ assertThat(dynamicColor.getArgb(minContrast)).isSameColorAs(blueArgb);
- @Test
- public void toneDeltaConstraintNoPreference_evaluatesCorrectly() {
- final int blueArgb = 0xff0000ff;
- final int redArgb = 0xffff0000;
- final DynamicColor otherDynamicColor = DynamicColor.fromArgb(redArgb);
- final DynamicColor dynamicColor =
- DynamicColor.fromArgb(
- blueArgb,
- (s) -> 30.0,
- null,
- (s) -> new ToneDeltaConstraint(30, otherDynamicColor,
- TonePolarity.NO_PREFERENCE));
- final SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(blueArgb), false, 0.0);
- assertThat(dynamicColor.getArgb(scheme)).isSameColorAs(0xff0000ef);
- }
+ final SchemeTonalSpot maxContrast = new SchemeTonalSpot(Hct.fromInt(blueArgb), false, 1.0);
+ assertThat(dynamicColor.getArgb(maxContrast)).isSameColorAs(blueArgb);
+ }
- @Test
- public void dynamicColor_withOpacity() {
- final DynamicColor dynamicColor =
- new DynamicColor(
- s -> 0.0,
- s -> 0.0,
- s -> s.isDark ? 100.0 : 0.0,
- s -> s.isDark ? 0.20 : 0.12,
- null,
- scheme ->
- DynamicColor.toneMinContrastDefault(
- (s) -> s.isDark ? 100.0 : 0.0, null, scheme, null),
- scheme ->
- DynamicColor.toneMaxContrastDefault(
- (s) -> s.isDark ? 100.0 : 0.0, null, scheme, null),
- null);
- final SchemeTonalSpot lightScheme = new SchemeTonalSpot(Hct.fromInt(0xff4285f4), false,
- 0.0);
- assertThat(dynamicColor.getArgb(lightScheme)).isSameColorAs(0x1f000000);
+ @Test
+ public void toneDeltaConstraintNoPreference_evaluatesCorrectly() {
+ final int blueArgb = 0xff0000ff;
+ final int redArgb = 0xffff0000;
+ final DynamicColor otherDynamicColor = DynamicColor.fromArgb(redArgb);
+ final DynamicColor dynamicColor =
+ DynamicColor.fromArgb(
+ blueArgb,
+ (s) -> 30.0,
+ null,
+ (s) -> new ToneDeltaConstraint(30, otherDynamicColor, TonePolarity.NO_PREFERENCE));
+ final SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(blueArgb), false, 0.0);
+ assertThat(dynamicColor.getArgb(scheme)).isSameColorAs(0xff0000ef);
+ }
- final SchemeTonalSpot darkScheme = new SchemeTonalSpot(Hct.fromInt(0xff4285f4), true, 0.0);
- assertThat(dynamicColor.getArgb(darkScheme)).isSameColorAs(0x33ffffff);
- }
+ @Test
+ public void dynamicColor_withOpacity() {
+ final DynamicColor dynamicColor =
+ new DynamicColor(
+ s -> 0.0,
+ s -> 0.0,
+ s -> s.isDark ? 100.0 : 0.0,
+ s -> s.isDark ? 0.20 : 0.12,
+ null,
+ scheme ->
+ DynamicColor.toneMinContrastDefault(
+ (s) -> s.isDark ? 100.0 : 0.0, null, scheme, null),
+ scheme ->
+ DynamicColor.toneMaxContrastDefault(
+ (s) -> s.isDark ? 100.0 : 0.0, null, scheme, null),
+ null);
+ final SchemeTonalSpot lightScheme = new SchemeTonalSpot(Hct.fromInt(0xff4285f4), false, 0.0);
+ assertThat(dynamicColor.getArgb(lightScheme)).isSameColorAs(0x1f000000);
- @Test
- public void respectsContrast() {
- final Hct[] seedColors =
- new Hct[]{
- Hct.fromInt(0xFFFF0000),
- Hct.fromInt(0xFFFFFF00),
- Hct.fromInt(0xFF00FF00),
- Hct.fromInt(0xFF0000FF)
- };
+ final SchemeTonalSpot darkScheme = new SchemeTonalSpot(Hct.fromInt(0xff4285f4), true, 0.0);
+ assertThat(dynamicColor.getArgb(darkScheme)).isSameColorAs(0x33ffffff);
+ }
- final double[] contrastLevels = {-1.0, -0.5, 0.0, 0.5, 1.0};
+ @Test
+ public void respectsContrast() {
+ final Hct[] seedColors =
+ new Hct[] {
+ Hct.fromInt(0xFFFF0000),
+ Hct.fromInt(0xFFFFFF00),
+ Hct.fromInt(0xFF00FF00),
+ Hct.fromInt(0xFF0000FF)
+ };
- for (Hct seedColor : seedColors) {
- for (double contrastLevel : contrastLevels) {
- for (boolean isDark : new boolean[]{false, true}) {
- final DynamicScheme[] schemes =
- new DynamicScheme[]{
- new SchemeContent(seedColor, isDark, contrastLevel),
- new SchemeMonochrome(seedColor, isDark, contrastLevel),
- new SchemeTonalSpot(seedColor, isDark, contrastLevel),
- new SchemeFidelity(seedColor, isDark, contrastLevel)
- };
- for (final DynamicScheme scheme : schemes) {
- assertTrue(
- pairSatisfiesContrast(
- scheme, MaterialDynamicColors.onPrimary,
- MaterialDynamicColors.primary));
- assertTrue(
- pairSatisfiesContrast(
- scheme,
- MaterialDynamicColors.onPrimaryContainer,
- MaterialDynamicColors.primaryContainer));
- assertTrue(
- pairSatisfiesContrast(
- scheme, MaterialDynamicColors.onSecondary,
- MaterialDynamicColors.secondary));
- assertTrue(
- pairSatisfiesContrast(
- scheme,
- MaterialDynamicColors.onSecondaryContainer,
- MaterialDynamicColors.secondaryContainer));
- assertTrue(
- pairSatisfiesContrast(
- scheme, MaterialDynamicColors.onTertiary,
- MaterialDynamicColors.tertiary));
- assertTrue(
- pairSatisfiesContrast(
- scheme,
- MaterialDynamicColors.onTertiaryContainer,
- MaterialDynamicColors.tertiaryContainer));
- assertTrue(
- pairSatisfiesContrast(
- scheme, MaterialDynamicColors.onError,
- MaterialDynamicColors.error));
- assertTrue(
- pairSatisfiesContrast(
- scheme,
- MaterialDynamicColors.onErrorContainer,
- MaterialDynamicColors.errorContainer));
- assertTrue(
- pairSatisfiesContrast(
- scheme, MaterialDynamicColors.onBackground,
- MaterialDynamicColors.background));
- assertTrue(
- pairSatisfiesContrast(
- scheme,
- MaterialDynamicColors.onSurfaceVariant,
- MaterialDynamicColors.surfaceVariant));
- assertTrue(
- pairSatisfiesContrast(
- scheme,
- MaterialDynamicColors.onSurfaceInverse,
- MaterialDynamicColors.surfaceInverse));
- }
- }
- }
+ final double[] contrastLevels = {-1.0, -0.5, 0.0, 0.5, 1.0};
+
+ for (Hct seedColor : seedColors) {
+ for (double contrastLevel : contrastLevels) {
+ for (boolean isDark : new boolean[] {false, true}) {
+ final DynamicScheme[] schemes =
+ new DynamicScheme[] {
+ new SchemeContent(seedColor, isDark, contrastLevel),
+ new SchemeMonochrome(seedColor, isDark, contrastLevel),
+ new SchemeTonalSpot(seedColor, isDark, contrastLevel),
+ new SchemeFidelity(seedColor, isDark, contrastLevel)
+ };
+ for (final DynamicScheme scheme : schemes) {
+ assertTrue(
+ pairSatisfiesContrast(scheme, dynamicColors.onPrimary(), dynamicColors.primary()));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, dynamicColors.onPrimaryContainer(), dynamicColors.primaryContainer()));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, dynamicColors.onSecondary(), dynamicColors.secondary()));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ dynamicColors.onSecondaryContainer(),
+ dynamicColors.secondaryContainer()));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, dynamicColors.onTertiary(), dynamicColors.tertiary()));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme,
+ dynamicColors.onTertiaryContainer(),
+ dynamicColors.tertiaryContainer()));
+ assertTrue(
+ pairSatisfiesContrast(scheme, dynamicColors.onError(), dynamicColors.error()));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, dynamicColors.onErrorContainer(), dynamicColors.errorContainer()));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, dynamicColors.onBackground(), dynamicColors.background()));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, dynamicColors.onSurfaceVariant(), dynamicColors.surfaceVariant()));
+ assertTrue(
+ pairSatisfiesContrast(
+ scheme, dynamicColors.inverseOnSurface(), dynamicColors.inverseSurface()));
+ }
}
+ }
}
+ }
- @Test
- public void valuesAreCorrect() {
- // Checks that the values of certain dynamic colors match Dart results.
- assertThat(
- MaterialDynamicColors.onPrimaryContainer.getArgb(
- new SchemeFidelity(Hct.fromInt(0xFFFF0000), false, 0.5)))
- .isSameColorAs(0xFFFFE5E1);
- assertThat(
- MaterialDynamicColors.onSecondaryContainer.getArgb(
- new SchemeContent(Hct.fromInt(0xFF0000FF), false, 0.5)))
- .isSameColorAs(0xFFFFFCFF);
- assertThat(
- MaterialDynamicColors.onTertiaryContainer.getArgb(
- new SchemeContent(Hct.fromInt(0xFFFFFF00), true, -0.5)))
- .isSameColorAs(0xFF616600);
- assertThat(
- MaterialDynamicColors.surfaceInverse.getArgb(
- new SchemeContent(Hct.fromInt(0xFF0000FF), false, 0.0)))
- .isSameColorAs(0xFF464652);
- assertThat(
- MaterialDynamicColors.primaryInverse.getArgb(
- new SchemeContent(Hct.fromInt(0xFFFF0000), false, -0.5)))
- .isSameColorAs(0xFFFF8C7A);
- assertThat(
- MaterialDynamicColors.outlineVariant.getArgb(
- new SchemeContent(Hct.fromInt(0xFFFFFF00), true, 0.0)))
- .isSameColorAs(0xFF484831);
- }
+ @Test
+ public void valuesAreCorrect() {
+ // Checks that the values of certain dynamic colors match Dart results.
+ assertThat(
+ dynamicColors
+ .onPrimaryContainer()
+ .getArgb(new SchemeFidelity(Hct.fromInt(0xFFFF0000), false, 0.5)))
+ .isSameColorAs(0xFFFFE5E1);
+ assertThat(
+ dynamicColors
+ .onSecondaryContainer()
+ .getArgb(new SchemeContent(Hct.fromInt(0xFF0000FF), false, 0.5)))
+ .isSameColorAs(0xFFFFFCFF);
+ assertThat(
+ dynamicColors
+ .onTertiaryContainer()
+ .getArgb(new SchemeContent(Hct.fromInt(0xFFFFFF00), true, -0.5)))
+ .isSameColorAs(0xFF616600);
+ assertThat(
+ dynamicColors
+ .inverseSurface()
+ .getArgb(new SchemeContent(Hct.fromInt(0xFF0000FF), false, 0.0)))
+ .isSameColorAs(0xFF2F2F3B);
+ assertThat(
+ dynamicColors
+ .inversePrimary()
+ .getArgb(new SchemeContent(Hct.fromInt(0xFFFF0000), false, -0.5)))
+ .isSameColorAs(0xFFFF907F);
+ assertThat(
+ dynamicColors
+ .outlineVariant()
+ .getArgb(new SchemeContent(Hct.fromInt(0xFFFFFF00), true, 0.0)))
+ .isSameColorAs(0xFF484831);
+ }
- private boolean pairSatisfiesContrast(DynamicScheme scheme, DynamicColor fg, DynamicColor bg) {
- double fgTone = fg.getHct(scheme).getTone();
- double bgTone = bg.getHct(scheme).getTone();
- double minimumRequirement = scheme.contrastLevel >= 0.0 ? 4.5 : 3.0;
- return Contrast.ratioOfTones(fgTone, bgTone) >= minimumRequirement;
- }
+ private boolean pairSatisfiesContrast(DynamicScheme scheme, DynamicColor fg, DynamicColor bg) {
+ double fgTone = fg.getHct(scheme).getTone();
+ double bgTone = bg.getHct(scheme).getTone();
+ double minimumRequirement = scheme.contrastLevel >= 0.0 ? 4.5 : 3.0;
+ return Contrast.ratioOfTones(fgTone, bgTone) >= minimumRequirement;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeContentTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeContentTest.java
index 1ddfc4d..704aed8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeContentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeContentTest.java
@@ -25,246 +25,229 @@
import com.android.systemui.monet.hct.Hct;
import com.android.systemui.monet.scheme.SchemeContent;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+@Ignore("b/279581953")
@SmallTest
@RunWith(JUnit4.class)
public final class SchemeContentTest extends SysuiTestCase {
+ private final MaterialDynamicColors dynamicColors = new MaterialDynamicColors();
+
@Test
public void testKeyColors() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.primaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff080CFF);
- assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.secondaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff656DD3);
- assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.tertiaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff81009F);
- assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff767684);
- assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralVariantPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff757589);
}
@Test
public void lightTheme_minContrast_primary() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFF1218FF);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xFF1218FF);
}
@Test
public void lightTheme_standardContrast_primary() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFF0001C3);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xFF0001C3);
}
@Test
public void lightTheme_maxContrast_primary() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFF000181);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xFF000181);
}
@Test
public void lightTheme_minContrast_primaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFF5660FF);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xFF5660FF);
}
@Test
public void lightTheme_standardContrast_primaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFF2D36FF);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xFF2D36FF);
}
@Test
public void lightTheme_maxContrast_primaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFF0000E3);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xFF0000E3);
}
@Test
public void lightTheme_minContrast_tertiaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFFB042CC);
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(0xFFB042CC);
}
@Test
public void lightTheme_standardContrast_tertiaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFF9221AF);
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(0xFF9221AF);
}
@Test
public void lightTheme_maxContrast_tertiaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFF73008E);
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(0xFF73008E);
}
@Test
public void lightTheme_minContrast_objectionableTertiaryContainerLightens() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF850096), false, -1.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFFD03A71);
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(0xFFD03A71);
}
@Test
public void lightTheme_standardContrast_objectionableTertiaryContainerLightens() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF850096), false, 0.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFFAC1B57);
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(0xFFAC1B57);
}
@Test
public void lightTheme_maxContrast_objectionableTertiaryContainerDarkens() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF850096), false, 1.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFF870040);
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(0xFF870040);
}
@Test
public void lightTheme_minContrast_onPrimaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFFCBCDFF);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xFFCBCDFF);
}
@Test
public void lightTheme_standardContrast_onPrimaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFFCECFFF);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xFFCECFFF);
}
@Test
public void lightTheme_maxContrast_onPrimaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFFD6D6FF);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xFFD6D6FF);
}
@Test
public void lightTheme_minContrast_surface() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, -1);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xFFFBF8FF);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xFFFBF8FF);
}
@Test
public void lightTheme_standardContrast_surface() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xFFFBF8FF);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xFFFBF8FF);
}
@Test
public void lightTheme_maxContrast_surface() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xFFFBF8FF);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xFFFBF8FF);
}
@Test
public void darkTheme_minContrast_primary() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFF5660FF);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xFF5660FF);
}
@Test
public void darkTheme_standardContrast_primary() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFFBEC2FF);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xFFBEC2FF);
}
@Test
public void darkTheme_maxContrast_primary() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFFF6F4FF);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xFFF6F4FF);
}
@Test
public void darkTheme_minContrast_primaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFF0000E6);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xFF0000E6);
}
@Test
public void darkTheme_standardContrast_primaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFF0000E6);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xFF0000E6);
}
@Test
public void darkTheme_maxContrast_primaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFFC4C6FF);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xFFC4C6FF);
}
@Test
public void darkTheme_minContrast_onPrimaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFF7A83FF);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xFF7A83FF);
}
@Test
public void darkTheme_standardContrast_onPrimaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFFA4AAFF);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xFFA4AAFF);
}
@Test
public void darkTheme_maxContrast_onPrimaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFF0001C6);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xFF0001C6);
}
@Test
public void darkTheme_minContrast_onTertiaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFFCF60EA);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xFFCF60EA);
}
@Test
public void darkTheme_standardContrast_onTertiaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFFEB8CFF);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xFFEB8CFF);
}
@Test
public void darkTheme_maxContrast_onTertiaryContainer() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xFF63007B);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xFF63007B);
}
@Test
public void darkTheme_minContrast_surface() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xFF12121D);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xFF12121D);
}
@Test
public void darkTheme_standardContrast_surface() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xFF12121D);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xFF12121D);
}
@Test
public void darkTheme_maxContrast_surface() {
SchemeContent scheme = new SchemeContent(Hct.fromInt(0xFF0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xFF12121D);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xFF12121D);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeExpressiveTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeExpressiveTest.java
index 31e8711..32a589d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeExpressiveTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeExpressiveTest.java
@@ -25,183 +25,175 @@
import com.android.systemui.monet.hct.Hct;
import com.android.systemui.monet.scheme.SchemeExpressive;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+@Ignore("b/279581953")
@SmallTest
@RunWith(JUnit4.class)
public final class SchemeExpressiveTest extends SysuiTestCase {
+ private final MaterialDynamicColors dynamicColors = new MaterialDynamicColors();
+
@Test
public void testKeyColors() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.primaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff35855F);
- assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.secondaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff8C6D8C);
- assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.tertiaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff806EA1);
- assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff79757F);
- assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralVariantPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff7A7585);
}
@Test
public void lightTheme_minContrast_primary() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff32835D);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xffad603c);
}
@Test
public void lightTheme_standardContrast_primary() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff146C48);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff924b28);
}
@Test
public void lightTheme_maxContrast_primary() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff002818);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff401400);
}
@Test
public void lightTheme_minContrast_primaryContainer() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffA2F4C6);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffffdbcc);
}
@Test
public void lightTheme_standardContrast_primaryContainer() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffA2F4C6);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffffdbcc);
}
@Test
public void lightTheme_maxContrast_primaryContainer() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff004D31);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff6f3010);
}
@Test
public void lightTheme_minContrast_onPrimaryContainer() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff1e724e);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff99512e);
}
@Test
public void lightTheme_standardContrast_onPrimaryContainer() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff002112);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff351000);
}
@Test
public void lightTheme_maxContrast_onPrimaryContainer() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff9aebbe);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffffd0bc);
}
@Test
public void lightTheme_minContrast_surface() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffdf7ff);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void lightTheme_standardContrast_surface() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffdf7ff);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void lightTheme_maxContrast_surface() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffdf7ff);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void darkTheme_minContrast_primary() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff32835d);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xffad603c);
}
@Test
public void darkTheme_standardContrast_primary() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff87d7ab);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xffffb595);
}
@Test
public void darkTheme_maxContrast_primary() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffd5ffe4);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xfffff3ee);
}
@Test
public void darkTheme_minContrast_primaryContainer() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff005234);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff743413);
}
@Test
public void darkTheme_standardContrast_primaryContainer() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff005234);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff743413);
}
@Test
public void darkTheme_maxContrast_primaryContainer() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff8bdbaf);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffffbb9e);
}
@Test
public void darkTheme_minContrast_onPrimaryContainer() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff76c59b);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xfff99f75);
}
@Test
public void darkTheme_standardContrast_onPrimaryContainer() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffa2f4c6);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffffdbcc);
}
@Test
public void darkTheme_maxContrast_onPrimaryContainer() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff004229);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff622706);
}
@Test
public void darkTheme_minContrast_surface() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff14121a);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff12131a);
}
@Test
public void darkTheme_standardContrast_surface() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff14121a);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff12131a);
}
@Test
public void darkTheme_maxContrast_surface() {
SchemeExpressive scheme = new SchemeExpressive(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff14121a);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff12131a);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFidelityTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFidelityTest.java
index 511f83b..6844a92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFidelityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFidelityTest.java
@@ -25,245 +25,230 @@
import com.android.systemui.monet.hct.Hct;
import com.android.systemui.monet.scheme.SchemeFidelity;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+@Ignore("b/279581953")
@SmallTest
@RunWith(JUnit4.class)
public final class SchemeFidelityTest extends SysuiTestCase {
+
+ private final MaterialDynamicColors dynamicColors = new MaterialDynamicColors();
+
@Test
public void testKeyColors() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.primaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff080CFF);
- assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.secondaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff656DD3);
- assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.tertiaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff9D0002);
- assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff767684);
- assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralVariantPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff757589);
}
@Test
public void lightTheme_minContrast_primary() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff1218ff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff1218ff);
}
@Test
public void lightTheme_standardContrast_primary() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff0001c3);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff0001c3);
}
@Test
public void lightTheme_maxContrast_primary() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff000181);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff000181);
}
@Test
public void lightTheme_minContrast_primaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff5660ff);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff5660ff);
}
@Test
public void lightTheme_standardContrast_primaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff2d36ff);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff2d36ff);
}
@Test
public void lightTheme_maxContrast_primaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff0000e3);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff0000e3);
}
@Test
public void lightTheme_minContrast_tertiaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffd93628);
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(0xffd93628);
}
@Test
public void lightTheme_standardContrast_tertiaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffb31910);
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(0xffb31910);
}
@Test
public void lightTheme_maxContrast_tertiaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff8c0002);
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(0xff8c0002);
}
@Test
public void lightTheme_minContrast_objectionableTertiaryContainerLightens() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff850096), false, -1.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffbcac5a);
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(0xffbcac5a);
}
@Test
public void lightTheme_standardContrast_objectionableTertiaryContainerLightens() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff850096), false, 0.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffbcac5a);
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(0xffbcac5a);
}
@Test
public void lightTheme_maxContrast_objectionableTertiaryContainerDarkens() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff850096), false, 1.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff4d4300);
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(0xff4d4300);
}
@Test
public void lightTheme_minContrast_onPrimaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffcbcdff);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffcbcdff);
}
@Test
public void lightTheme_standardContrast_onPrimaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffcecfff);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffcecfff);
}
@Test
public void lightTheme_maxContrast_onPrimaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffd6d6ff);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffd6d6ff);
}
@Test
public void lightTheme_minContrast_surface() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void lightTheme_standardContrast_surface() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void lightTheme_maxContrast_surface() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void darkTheme_minContrast_primary() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff5660ff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff5660ff);
}
@Test
public void darkTheme_standardContrast_primary() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffbec2ff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xffbec2ff);
}
@Test
public void darkTheme_maxContrast_primary() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xfff6f4ff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xfff6f4ff);
}
@Test
public void darkTheme_minContrast_primaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff0000e6);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff0000e6);
}
@Test
public void darkTheme_standardContrast_primaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff0000e6);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff0000e6);
}
@Test
public void darkTheme_maxContrast_primaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffc4c6ff);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffc4c6ff);
}
@Test
public void darkTheme_minContrast_onPrimaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff7a83ff);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff7a83ff);
}
@Test
public void darkTheme_standardContrast_onPrimaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffa4aaff);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffa4aaff);
}
@Test
public void darkTheme_maxContrast_onPrimaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff0001c6);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff0001c6);
}
@Test
public void darkTheme_minContrast_onTertiaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xfffe513e);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xfffe513e);
}
@Test
public void darkTheme_standardContrast_onTertiaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffFF9181);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xffFF9181);
}
@Test
public void darkTheme_maxContrast_onTertiaryContainer() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff790001);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xff790001);
}
@Test
public void darkTheme_minContrast_surface() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12121d);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff12121d);
}
@Test
public void darkTheme_standardContrast_surface() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12121d);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff12121d);
}
@Test
public void darkTheme_maxContrast_surface() {
SchemeFidelity scheme = new SchemeFidelity(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12121d);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff12121d);
}
+
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFruitSaladTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFruitSaladTest.java
index 4cf14d5..4bca2c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFruitSaladTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeFruitSaladTest.java
@@ -25,226 +25,230 @@
import com.android.systemui.monet.hct.Hct;
import com.android.systemui.monet.scheme.SchemeFruitSalad;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+@Ignore("b/279581953")
@SmallTest
@RunWith(JUnit4.class)
public final class SchemeFruitSaladTest extends SysuiTestCase {
+ private final MaterialDynamicColors dynamicColors = new MaterialDynamicColors();
+
@Test
public void testKeyColors() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.primaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff0091C0);
- assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.secondaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff3A7E9E);
- assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.tertiaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff6E72AC);
- assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff777682);
- assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralVariantPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff75758B);
}
@Test
public void lightTheme_minContrast_primary() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff007ea7);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff007ea7);
}
@Test
public void lightTheme_standardContrast_primary() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff006688);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff006688);
}
@Test
public void lightTheme_maxContrast_primary() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff002635);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff002635);
}
@Test
public void lightTheme_minContrast_primaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(
0xffC2E8FF);
}
@Test
public void lightTheme_standardContrast_primaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(
0xffC2E8FF);
}
@Test
public void lightTheme_maxContrast_primaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(
0xff004862);
}
@Test
public void lightTheme_minContrast_tertiaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(
0xffE0E0FF);
}
@Test
public void lightTheme_standardContrast_tertiaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(
0xffE0E0FF);
}
@Test
public void lightTheme_maxContrast_tertiaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(
0xFF3A3E74);
}
@Test
public void lightTheme_minContrast_onPrimaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(
0xff006C90);
}
@Test
public void lightTheme_standardContrast_onPrimaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(
0xff001E2B);
}
@Test
public void lightTheme_maxContrast_onPrimaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(
0xffACE1FF);
}
@Test
public void lightTheme_minContrast_surface() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void lightTheme_standardContrast_surface() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void lightTheme_maxContrast_surface() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void darkTheme_minContrast_primary() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff007EA7);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff007EA7);
}
@Test
public void darkTheme_standardContrast_primary() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFF76D1FF);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xFF76D1FF);
}
@Test
public void darkTheme_maxContrast_primary() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xFFECF7FF);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xFFECF7FF);
}
@Test
public void darkTheme_minContrast_primaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(
0xFF004D67);
}
@Test
public void darkTheme_standardContrast_primaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(
0xFF004D67);
}
@Test
public void darkTheme_maxContrast_primaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(
0xFF83D5FF);
}
@Test
public void darkTheme_minContrast_onPrimaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(
0xff55C0F2);
}
@Test
public void darkTheme_standardContrast_onPrimaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(
0xffC2E8FF);
}
@Test
public void darkTheme_maxContrast_onPrimaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(
0xff003E54);
}
@Test
public void darkTheme_minContrast_onTertiaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(
0xffADB0EF);
}
@Test
public void darkTheme_standardContrast_onTertiaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(
0xffe0e0ff);
}
@Test
public void darkTheme_maxContrast_onTertiaryContainer() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(
0xff30346A);
}
@Test
public void darkTheme_minContrast_surface() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12131c);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff12131c);
}
@Test
public void darkTheme_standardContrast_surface() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12131c);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff12131c);
}
@Test
public void darkTheme_maxContrast_surface() {
SchemeFruitSalad scheme = new SchemeFruitSalad(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12131c);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff12131c);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeMonochromeTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeMonochromeTest.java
index 3eca4dc..d511422 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeMonochromeTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeMonochromeTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.monet;
+import static com.google.common.truth.Truth.assertThat;
import static com.android.systemui.monet.utils.ArgbSubject.assertThat;
import androidx.test.filters.SmallTest;
@@ -25,204 +26,227 @@
import com.android.systemui.monet.hct.Hct;
import com.android.systemui.monet.scheme.SchemeMonochrome;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+@Ignore("b/279581953")
@SmallTest
@RunWith(JUnit4.class)
public final class SchemeMonochromeTest extends SysuiTestCase {
+ private final MaterialDynamicColors dynamicColors = new MaterialDynamicColors();
+
@Test
public void testKeyColors() {
SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.primaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff070707);
- assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.secondaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff070707);
- assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.tertiaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff070707);
- assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff070707);
- assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralVariantPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff070707);
}
@Test
public void lightTheme_minContrast_primary() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff747474);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, -1);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff3c3c3c);
}
@Test
public void lightTheme_standardContrast_primary() {
SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff5e5e5e);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff000000);
}
@Test
public void lightTheme_maxContrast_primary() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff222222);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 1);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff000000);
}
@Test
public void lightTheme_minContrast_primaryContainer() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe2e2e2);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, -1);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff5f5f5f);
}
@Test
public void lightTheme_standardContrast_primaryContainer() {
SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe2e2e2);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff3b3b3b);
}
@Test
public void lightTheme_maxContrast_primaryContainer() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff434343);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 1);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff3a3a3a);
}
@Test
public void lightTheme_minContrast_onPrimaryContainer() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff646464);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, -1);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffd9d9d9);
}
@Test
public void lightTheme_standardContrast_onPrimaryContainer() {
SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff1b1b1b);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffffffff);
}
@Test
public void lightTheme_maxContrast_onPrimaryContainer() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffdadada);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 1);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffcdcdcd);
}
@Test
public void lightTheme_minContrast_surface() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfff9f9f9);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, -1);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfff9f9f9);
}
@Test
public void lightTheme_standardContrast_surface() {
SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfff9f9f9);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfff9f9f9);
}
@Test
public void lightTheme_maxContrast_surface() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfff9f9f9);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 1);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfff9f9f9);
}
@Test
public void darkTheme_minContrast_primary() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff747474);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xffcccccc);
}
@Test
public void darkTheme_standardContrast_primary() {
SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffc6c6c6);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xffffffff);
}
@Test
public void darkTheme_maxContrast_primary() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xfff5f5f5);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xffffffff);
}
@Test
public void darkTheme_minContrast_primaryContainer() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff474747);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffa3a3a3);
}
@Test
public void darkTheme_standardContrast_primaryContainer() {
SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff474747);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffd4d4d4);
}
@Test
public void darkTheme_maxContrast_primaryContainer() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffcbcbcb);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffd5d5d5);
}
@Test
public void darkTheme_minContrast_onPrimaryContainer() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffb5b5b5);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff393939);
}
@Test
public void darkTheme_standardContrast_onPrimaryContainer() {
SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe2e2e2);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff000000);
}
@Test
public void darkTheme_maxContrast_onPrimaryContainer() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff393939);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff404040);
}
@Test
public void darkTheme_minContrast_onTertiaryContainer() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffb5b5b5);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xffd1d1d1);
}
@Test
public void darkTheme_standardContrast_onTertiaryContainer() {
SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe2e2e2);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xff000000);
}
@Test
public void darkTheme_maxContrast_onTertiaryContainer() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff393939);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xff393939);
}
@Test
public void darkTheme_minContrast_surface() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131313);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, -1);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff131313);
}
@Test
public void darkTheme_standardContrast_surface() {
SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131313);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff131313);
}
@Test
public void darkTheme_maxContrast_surface() {
- SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131313);
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 1);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff131313);
+ }
+
+ @Test
+ public void darkTheme_monochromeSpec() {
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), true, 0.0);
+ assertThat(dynamicColors.primary().getHct(scheme).getTone()).isWithin(1).of(100);
+ assertThat(dynamicColors.onPrimary().getHct(scheme).getTone()).isWithin(1).of(10);
+ assertThat(dynamicColors.primaryContainer().getHct(scheme).getTone()).isWithin(1).of(85);
+ assertThat(dynamicColors.onPrimaryContainer().getHct(scheme).getTone()).isWithin(1).of(0);
+ assertThat(dynamicColors.secondary().getHct(scheme).getTone()).isWithin(1).of(80);
+ assertThat(dynamicColors.onSecondary().getHct(scheme).getTone()).isWithin(1).of(10);
+ assertThat(dynamicColors.secondaryContainer().getHct(scheme).getTone()).isWithin(1).of(30);
+ assertThat(dynamicColors.onSecondaryContainer().getHct(scheme).getTone()).isWithin(1).of(90);
+ assertThat(dynamicColors.tertiary().getHct(scheme).getTone()).isWithin(1).of(90);
+ assertThat(dynamicColors.onTertiary().getHct(scheme).getTone()).isWithin(1).of(10);
+ assertThat(dynamicColors.tertiaryContainer().getHct(scheme).getTone()).isWithin(1).of(60);
+ assertThat(dynamicColors.onTertiaryContainer().getHct(scheme).getTone()).isWithin(1).of(0);
+ }
+
+ @Test
+ public void lightTheme_monochromeSpec() {
+ SchemeMonochrome scheme = new SchemeMonochrome(Hct.fromInt(0xff0000ff), false, 0.0);
+ assertThat(dynamicColors.primary().getHct(scheme).getTone()).isWithin(1).of(0);
+ assertThat(dynamicColors.onPrimary().getHct(scheme).getTone()).isWithin(1).of(90);
+ assertThat(dynamicColors.primaryContainer().getHct(scheme).getTone()).isWithin(1).of(25);
+ assertThat(dynamicColors.onPrimaryContainer().getHct(scheme).getTone()).isWithin(1).of(100);
+ assertThat(dynamicColors.secondary().getHct(scheme).getTone()).isWithin(1).of(40);
+ assertThat(dynamicColors.onSecondary().getHct(scheme).getTone()).isWithin(1).of(100);
+ assertThat(dynamicColors.secondaryContainer().getHct(scheme).getTone()).isWithin(1).of(85);
+ assertThat(dynamicColors.onSecondaryContainer().getHct(scheme).getTone()).isWithin(1).of(10);
+ assertThat(dynamicColors.tertiary().getHct(scheme).getTone()).isWithin(1).of(25);
+ assertThat(dynamicColors.onTertiary().getHct(scheme).getTone()).isWithin(1).of(90);
+ assertThat(dynamicColors.tertiaryContainer().getHct(scheme).getTone()).isWithin(1).of(49);
+ assertThat(dynamicColors.onTertiaryContainer().getHct(scheme).getTone()).isWithin(1).of(100);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeNeutralTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeNeutralTest.java
index 71e9f4d..4f3fc7d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeNeutralTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeNeutralTest.java
@@ -25,204 +25,193 @@
import com.android.systemui.monet.hct.Hct;
import com.android.systemui.monet.scheme.SchemeNeutral;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+@Ignore("b/279581953")
@SmallTest
@RunWith(JUnit4.class)
public final class SchemeNeutralTest extends SysuiTestCase {
+ private final MaterialDynamicColors dynamicColors = new MaterialDynamicColors();
+
@Test
public void testKeyColors() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.primaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff767685);
- assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.secondaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff777680);
- assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.tertiaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff75758B);
- assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff787678);
- assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralVariantPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff787678);
}
@Test
public void lightTheme_minContrast_primary() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff737383);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff737383);
}
@Test
public void lightTheme_standardContrast_primary() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff5d5d6c);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff5d5d6c);
}
@Test
public void lightTheme_maxContrast_primary() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff21212e);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff21212e);
}
@Test
public void lightTheme_minContrast_primaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe2e1f3);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffe2e1f3);
}
@Test
public void lightTheme_standardContrast_primaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe2e1f3);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffe2e1f3);
}
@Test
public void lightTheme_maxContrast_primaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff414250);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff414250);
}
@Test
public void lightTheme_minContrast_onPrimaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff636372);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff636372);
}
@Test
public void lightTheme_standardContrast_onPrimaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff1a1b27);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff1a1b27);
}
@Test
public void lightTheme_maxContrast_onPrimaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffd9d8ea);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffd9d8ea);
}
@Test
public void lightTheme_minContrast_surface() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffcf8fa);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffcf8fa);
}
@Test
public void lightTheme_standardContrast_surface() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffcf8fa);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffcf8fa);
}
@Test
public void lightTheme_maxContrast_surface() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffcf8fa);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffcf8fa);
}
@Test
public void darkTheme_minContrast_primary() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff737383);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff737383);
}
@Test
public void darkTheme_standardContrast_primary() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffc6c5d6);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xffc6c5d6);
}
@Test
public void darkTheme_maxContrast_primary() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xfff6f4ff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xfff6f4ff);
}
@Test
public void darkTheme_minContrast_primaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff454654);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff454654);
}
@Test
public void darkTheme_standardContrast_primaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff454654);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff454654);
}
@Test
public void darkTheme_maxContrast_primaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffcac9da);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffcac9da);
}
@Test
public void darkTheme_minContrast_onPrimaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffb5b3c4);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffb5b3c4);
}
@Test
public void darkTheme_standardContrast_onPrimaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe2e1f3);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffe2e1f3);
}
@Test
public void darkTheme_maxContrast_onPrimaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff373846);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff373846);
}
@Test
public void darkTheme_minContrast_onTertiaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffb3b3cb);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xffb3b3cb);
}
@Test
public void darkTheme_standardContrast_onTertiaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe1e0f9);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xffe1e0f9);
}
@Test
public void darkTheme_maxContrast_onTertiaryContainer() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff37374b);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xff37374b);
}
@Test
public void darkTheme_minContrast_surface() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131315);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff131315);
}
@Test
public void darkTheme_standardContrast_surface() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131315);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff131315);
}
@Test
public void darkTheme_maxContrast_surface() {
SchemeNeutral scheme = new SchemeNeutral(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131315);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff131315);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeRainbowTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeRainbowTest.java
index cc6f044..ece3f9a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeRainbowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeRainbowTest.java
@@ -25,225 +25,229 @@
import com.android.systemui.monet.hct.Hct;
import com.android.systemui.monet.scheme.SchemeRainbow;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+@Ignore("b/279581953")
@SmallTest
@RunWith(JUnit4.class)
public final class SchemeRainbowTest extends SysuiTestCase {
+ private final MaterialDynamicColors dynamicColors = new MaterialDynamicColors();
+
@Test
public void testKeyColors() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.primaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff696FC4);
- assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.secondaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff75758B);
- assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.tertiaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff936B84);
- assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff070707);
- assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralVariantPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff070707);
}
@Test
public void lightTheme_minContrast_primary() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff676DC1);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff676DC1);
}
@Test
public void lightTheme_standardContrast_primary() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff5056A9);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff5056A9);
}
@Test
public void lightTheme_maxContrast_primary() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff0F136A);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff0F136A);
}
@Test
public void lightTheme_minContrast_primaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(
0xffE0E0FF);
}
@Test
public void lightTheme_standardContrast_primaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(
0xffE0E0FF);
}
@Test
public void lightTheme_maxContrast_primaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(
0xff34398B);
}
@Test
public void lightTheme_minContrast_tertiaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(
0xffffd8ee);
}
@Test
public void lightTheme_standardContrast_tertiaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(
0xffffd8ee);
}
@Test
public void lightTheme_maxContrast_tertiaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.tertiaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.tertiaryContainer().getArgb(scheme)).isSameColorAs(
0xff5A384E);
}
@Test
public void lightTheme_minContrast_onPrimaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(
0xff565CB0);
}
@Test
public void lightTheme_standardContrast_onPrimaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(
0xff050865);
}
@Test
public void lightTheme_maxContrast_onPrimaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(
0xffd6d6ff);
}
@Test
public void lightTheme_minContrast_surface() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfff9f9f9);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfff9f9f9);
}
@Test
public void lightTheme_standardContrast_surface() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfff9f9f9);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfff9f9f9);
}
@Test
public void lightTheme_maxContrast_surface() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfff9f9f9);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfff9f9f9);
}
@Test
public void darkTheme_minContrast_primary() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff676DC1);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff676DC1);
}
@Test
public void darkTheme_standardContrast_primary() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffbec2ff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xffbec2ff);
}
@Test
public void darkTheme_maxContrast_primary() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xfff6f4ff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xfff6f4ff);
}
@Test
public void darkTheme_minContrast_primaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(
0xff383E8F);
}
@Test
public void darkTheme_standardContrast_primaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(
0xff383E8F);
}
@Test
public void darkTheme_maxContrast_primaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(
0xffc4c6ff);
}
@Test
public void darkTheme_minContrast_onPrimaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(
0xffa9afff);
}
@Test
public void darkTheme_standardContrast_onPrimaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(
0xffe0e0ff);
}
@Test
public void darkTheme_maxContrast_onPrimaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(
0xff292f81);
}
@Test
public void darkTheme_minContrast_onTertiaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(
0xffd5a8c3);
}
@Test
public void darkTheme_standardContrast_onTertiaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(
0xffffd8ee);
}
@Test
public void darkTheme_maxContrast_onTertiaryContainer() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(
0xff4f2e44);
}
@Test
public void darkTheme_minContrast_surface() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131313);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff131313);
}
@Test
public void darkTheme_standardContrast_surface() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131313);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff131313);
}
@Test
public void darkTheme_maxContrast_surface() {
SchemeRainbow scheme = new SchemeRainbow(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131313);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff131313);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeTonalSpotTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeTonalSpotTest.java
index e4880d9..01d199b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeTonalSpotTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeTonalSpotTest.java
@@ -25,348 +25,338 @@
import com.android.systemui.monet.hct.Hct;
import com.android.systemui.monet.scheme.SchemeTonalSpot;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+@Ignore("b/279581953")
@SmallTest
@RunWith(JUnit4.class)
public final class SchemeTonalSpotTest extends SysuiTestCase {
+ private final MaterialDynamicColors dynamicColors = new MaterialDynamicColors();
+
@Test
public void testKeyColors() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.primaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff6E72AC);
- assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.secondaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff75758B);
- assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.tertiaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff936B84);
- assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff78767A);
- assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralVariantPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff777680);
}
+
@Test
public void lightTheme_minContrast_primary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff6c70aa);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff6a6fb1);
}
@Test
public void lightTheme_standardContrast_primary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff555992);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff545999);
}
@Test
public void lightTheme_maxContrast_primary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff181c51);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff161a59);
}
@Test
public void lightTheme_minContrast_primaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe0e0ff);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffe0e0ff);
}
@Test
public void lightTheme_standardContrast_primaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe0e0ff);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffe0e0ff);
}
@Test
public void lightTheme_maxContrast_primaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff3a3e74);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff383c7c);
}
@Test
public void lightTheme_minContrast_onPrimaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff5C5F98);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff5a5fa0);
}
@Test
public void lightTheme_standardContrast_onPrimaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff11144B);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff0e1253);
}
@Test
public void lightTheme_maxContrast_onPrimaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffd6d6ff);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffd6d6ff);
}
@Test
public void lightTheme_minContrast_surface() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xffFCF8FD);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void lightTheme_standardContrast_surface() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xffFCF8FD);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void lightTheme_maxContrast_surface() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xffFCF8FD);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void lightTheme_minContrast_onSurface() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.onSurface.getArgb(scheme)).isSameColorAs(0xff605E62);
+ assertThat(dynamicColors.onSurface().getArgb(scheme)).isSameColorAs(0xff5f5e65);
}
@Test
public void lightTheme_standardContrast_onSurface() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.onSurface.getArgb(scheme)).isSameColorAs(0xff1B1B1F);
+ assertThat(dynamicColors.onSurface().getArgb(scheme)).isSameColorAs(0xff1b1b21);
}
@Test
public void lightTheme_maxContrast_onSurface() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.onSurface.getArgb(scheme)).isSameColorAs(0xff1B1A1E);
+ assertThat(dynamicColors.onSurface().getArgb(scheme)).isSameColorAs(0xff1a1a20);
}
@Test
public void lightTheme_minContrast_onSecondary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.onSecondary.getArgb(scheme)).isSameColorAs(0xffcfcfe7);
+ assertThat(dynamicColors.onSecondary().getArgb(scheme)).isSameColorAs(0xffcfcfe7);
}
@Test
public void lightTheme_standardContrast_onSecondary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.onSecondary.getArgb(scheme)).isSameColorAs(0xffffffff);
+ assertThat(dynamicColors.onSecondary().getArgb(scheme)).isSameColorAs(0xffffffff);
}
@Test
public void lightTheme_maxContrast_onSecondary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.onSecondary.getArgb(scheme)).isSameColorAs(0xffababc3);
+ assertThat(dynamicColors.onSecondary().getArgb(scheme)).isSameColorAs(0xffababc3);
}
@Test
public void lightTheme_minContrast_onTertiary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.onTertiary.getArgb(scheme)).isSameColorAs(0xfff3c3df);
+ assertThat(dynamicColors.onTertiary().getArgb(scheme)).isSameColorAs(0xfff3c3df);
}
@Test
public void lightTheme_standardContrast_onTertiary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.onTertiary.getArgb(scheme)).isSameColorAs(0xffffffff);
+ assertThat(dynamicColors.onTertiary().getArgb(scheme)).isSameColorAs(0xffffffff);
}
@Test
public void lightTheme_maxContrast_onTertiary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.onTertiary.getArgb(scheme)).isSameColorAs(0xffcda0bb);
+ assertThat(dynamicColors.onTertiary().getArgb(scheme)).isSameColorAs(0xffcda0bb);
}
@Test
public void lightTheme_minContrast_onError() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.onError.getArgb(scheme)).isSameColorAs(0xffffc2bb);
+ assertThat(dynamicColors.onError().getArgb(scheme)).isSameColorAs(0xffffc2bb);
}
@Test
public void lightTheme_standardContrast_onError() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.onError.getArgb(scheme)).isSameColorAs(0xffffffff);
+ assertThat(dynamicColors.onError().getArgb(scheme)).isSameColorAs(0xffffffff);
}
@Test
public void lightTheme_maxContrast_onError() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.onError.getArgb(scheme)).isSameColorAs(0xffff8d80);
+ assertThat(dynamicColors.onError().getArgb(scheme)).isSameColorAs(0xffff8d80);
}
@Test
public void darkTheme_minContrast_primary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff6C70AA);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff6a6fb1);
}
@Test
public void darkTheme_standardContrast_primary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffbec2ff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xffbec2ff);
}
@Test
public void darkTheme_maxContrast_primary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xfff6f4ff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xfff6f4ff);
}
@Test
public void darkTheme_minContrast_primaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff3E4278);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff3c4180);
}
@Test
public void darkTheme_standardContrast_primaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff3E4278);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff3c4180);
}
@Test
public void darkTheme_maxContrast_primaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffc4c6ff);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffc4c6ff);
}
@Test
public void darkTheme_minContrast_onPrimaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffadb0ef);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffabaff7);
}
@Test
public void darkTheme_standardContrast_onPrimaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe0e0ff);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffe0e0ff);
}
@Test
public void darkTheme_maxContrast_onPrimaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff30346A);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff2e3271);
}
@Test
public void darkTheme_minContrast_onTertiaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffd5a8c3);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xffd5a8c3);
}
@Test
public void darkTheme_standardContrast_onTertiaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffffd8ee);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xffffd8ee);
}
@Test
public void darkTheme_maxContrast_onTertiaryContainer() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff4f2e44);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xff4f2e44);
}
@Test
public void darkTheme_minContrast_onSecondary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onSecondary.getArgb(scheme)).isSameColorAs(0xfffffbff);
+ assertThat(dynamicColors.onSecondary().getArgb(scheme)).isSameColorAs(0xfffffbff);
}
@Test
public void darkTheme_standardContrast_onSecondary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onSecondary.getArgb(scheme)).isSameColorAs(0xff2e2f42);
+ assertThat(dynamicColors.onSecondary().getArgb(scheme)).isSameColorAs(0xff2e2f42);
}
@Test
public void darkTheme_maxContrast_onSecondary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onSecondary.getArgb(scheme)).isSameColorAs(0xff505165);
+ assertThat(dynamicColors.onSecondary().getArgb(scheme)).isSameColorAs(0xff505165);
}
@Test
public void darkTheme_minContrast_onTertiary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onTertiary.getArgb(scheme)).isSameColorAs(0xfffffbff);
+ assertThat(dynamicColors.onTertiary().getArgb(scheme)).isSameColorAs(0xfffffbff);
}
@Test
public void darkTheme_standardContrast_onTertiary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onTertiary.getArgb(scheme)).isSameColorAs(0xff46263b);
+ assertThat(dynamicColors.onTertiary().getArgb(scheme)).isSameColorAs(0xff46263b);
}
@Test
public void darkTheme_maxContrast_onTertiary() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onTertiary.getArgb(scheme)).isSameColorAs(0xff6b485f);
+ assertThat(dynamicColors.onTertiary().getArgb(scheme)).isSameColorAs(0xff6b485f);
}
@Test
public void darkTheme_minContrast_onError() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onError.getArgb(scheme)).isSameColorAs(0xfffffbff);
+ assertThat(dynamicColors.onError().getArgb(scheme)).isSameColorAs(0xfffffbff);
}
@Test
public void darkTheme_standardContrast_onError() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onError.getArgb(scheme)).isSameColorAs(0xff690005);
+ assertThat(dynamicColors.onError().getArgb(scheme)).isSameColorAs(0xff690005);
}
@Test
public void darkTheme_maxContrast_onError() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onError.getArgb(scheme)).isSameColorAs(0xffa80710);
+ assertThat(dynamicColors.onError().getArgb(scheme)).isSameColorAs(0xffa80710);
}
@Test
public void darkTheme_minContrast_surface() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131316);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff131318);
}
@Test
public void darkTheme_standardContrast_surface() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131316);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff131318);
}
@Test
public void darkTheme_maxContrast_surface() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff131316);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff131318);
}
@Test
public void darkTheme_minContrast_onSurface() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onSurface.getArgb(scheme)).isSameColorAs(0xffa4a2a6);
+ assertThat(dynamicColors.onSurface().getArgb(scheme)).isSameColorAs(0xffa4a2a9);
}
@Test
public void darkTheme_standardContrast_onSurface() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onSurface.getArgb(scheme)).isSameColorAs(0xffe5e1e6);
+ assertThat(dynamicColors.onSurface().getArgb(scheme)).isSameColorAs(0xffe4e1e9);
}
@Test
public void darkTheme_maxContrast_onSurface() {
SchemeTonalSpot scheme = new SchemeTonalSpot(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onSurface.getArgb(scheme)).isSameColorAs(0xffe6e2e7);
+ assertThat(dynamicColors.onSurface().getArgb(scheme)).isSameColorAs(0xffe5e2ea);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeVibrantTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeVibrantTest.java
index e5963a2..0fb53eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeVibrantTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/SchemeVibrantTest.java
@@ -25,204 +25,193 @@
import com.android.systemui.monet.hct.Hct;
import com.android.systemui.monet.scheme.SchemeVibrant;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+@Ignore("b/279581953")
@SmallTest
@RunWith(JUnit4.class)
public final class SchemeVibrantTest extends SysuiTestCase {
+ private final MaterialDynamicColors dynamicColors = new MaterialDynamicColors();
+
@Test
public void testKeyColors() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.primaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff080CFF);
- assertThat(MaterialDynamicColors.secondaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.secondaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff7B7296);
- assertThat(MaterialDynamicColors.tertiaryPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.tertiaryPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff886C9D);
- assertThat(MaterialDynamicColors.neutralPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff777682);
- assertThat(MaterialDynamicColors.neutralVariantPaletteKeyColor.getArgb(scheme))
+ assertThat(dynamicColors.neutralVariantPaletteKeyColor().getArgb(scheme))
.isSameColorAs(0xff767685);
}
@Test
public void lightTheme_minContrast_primary() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff5660ff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff5660ff);
}
@Test
public void lightTheme_standardContrast_primary() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff343dff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff343dff);
}
@Test
public void lightTheme_maxContrast_primary() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff000181);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff000181);
}
@Test
public void lightTheme_minContrast_primaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe0e0ff);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffe0e0ff);
}
@Test
public void lightTheme_standardContrast_primaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe0e0ff);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffe0e0ff);
}
@Test
public void lightTheme_maxContrast_primaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff0000e3);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff0000e3);
}
@Test
public void lightTheme_minContrast_onPrimaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff3e47ff);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff3e47ff);
}
@Test
public void lightTheme_standardContrast_onPrimaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff00006e);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff00006e);
}
@Test
public void lightTheme_maxContrast_onPrimaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffd6d6ff);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffd6d6ff);
}
@Test
public void lightTheme_minContrast_surface() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void lightTheme_standardContrast_surface() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void lightTheme_maxContrast_surface() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), false, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xfffbf8ff);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xfffbf8ff);
}
@Test
public void darkTheme_minContrast_primary() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xff5660ff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xff5660ff);
}
@Test
public void darkTheme_standardContrast_primary() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xffbec2ff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xffbec2ff);
}
@Test
public void darkTheme_maxContrast_primary() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primary.getArgb(scheme)).isSameColorAs(0xfff6f4ff);
+ assertThat(dynamicColors.primary().getArgb(scheme)).isSameColorAs(0xfff6f4ff);
}
@Test
public void darkTheme_minContrast_primaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff0000ef);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff0000ef);
}
@Test
public void darkTheme_standardContrast_primaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff0000ef);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xff0000ef);
}
@Test
public void darkTheme_maxContrast_primaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.primaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffc4c6ff);
+ assertThat(dynamicColors.primaryContainer().getArgb(scheme)).isSameColorAs(0xffc4c6ff);
}
@Test
public void darkTheme_minContrast_onPrimaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffa9afff);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffa9afff);
}
@Test
public void darkTheme_standardContrast_onPrimaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffe0e0ff);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xffe0e0ff);
}
@Test
public void darkTheme_maxContrast_onPrimaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onPrimaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff0001c6);
+ assertThat(dynamicColors.onPrimaryContainer().getArgb(scheme)).isSameColorAs(0xff0001c6);
}
@Test
public void darkTheme_minContrast_onTertiaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xffc9a9df);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xffc9a9df);
}
@Test
public void darkTheme_standardContrast_onTertiaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xfff2daff);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xfff2daff);
}
@Test
public void darkTheme_maxContrast_onTertiaryContainer() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.onTertiaryContainer.getArgb(scheme)).isSameColorAs(
- 0xff472e5b);
+ assertThat(dynamicColors.onTertiaryContainer().getArgb(scheme)).isSameColorAs(0xff472e5b);
}
@Test
public void darkTheme_minContrast_surface() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, -1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12131C);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff12131a);
}
@Test
public void darkTheme_standardContrast_surface() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 0.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12131C);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff12131a);
}
@Test
public void darkTheme_maxContrast_surface() {
SchemeVibrant scheme = new SchemeVibrant(Hct.fromInt(0xff0000ff), true, 1.0);
- assertThat(MaterialDynamicColors.surface.getArgb(scheme)).isSameColorAs(0xff12131C);
+ assertThat(dynamicColors.surface().getArgb(scheme)).isSameColorAs(0xff12131a);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
index d9428f8..611c5b9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
@@ -104,6 +104,9 @@
continueTouch(START_X + touchSlop.toFloat() + 1)
// Move again to cross the back trigger threshold
continueTouch(START_X + touchSlop + triggerThreshold + 1)
+ // Wait threshold duration and hold touch past trigger threshold
+ Thread.sleep((MAX_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION + 1).toLong())
+ continueTouch(START_X + touchSlop + triggerThreshold + 1)
assertThat(mBackPanelController.currentState)
.isEqualTo(BackPanelController.GestureState.ACTIVE)
@@ -114,14 +117,22 @@
finishTouchActionUp(START_X + touchSlop + triggerThreshold + 1)
assertThat(mBackPanelController.currentState)
- .isEqualTo(BackPanelController.GestureState.FLUNG)
+ .isEqualTo(BackPanelController.GestureState.COMMITTED)
verify(backCallback).triggerBack()
}
@Test
fun handlesBackCancelled() {
startTouch()
+ // Move once to cross the touch slop
continueTouch(START_X + touchSlop.toFloat() + 1)
+ // Move again to cross the back trigger threshold
+ continueTouch(
+ START_X + touchSlop + triggerThreshold -
+ mBackPanelController.params.deactivationTriggerThreshold
+ )
+ // Wait threshold duration and hold touch before trigger threshold
+ Thread.sleep((MAX_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION + 1).toLong())
continueTouch(
START_X + touchSlop + triggerThreshold -
mBackPanelController.params.deactivationTriggerThreshold
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
index 55f221d..5dbcd33 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -45,8 +45,8 @@
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.notetask.NoteTaskController.Companion.EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE
+import com.android.systemui.notetask.NoteTaskController.Companion.SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT
import com.android.systemui.notetask.NoteTaskController.Companion.SHORTCUT_ID
-import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity
import com.android.systemui.settings.FakeUserTracker
@@ -423,8 +423,8 @@
eq(COMPONENT_ENABLED_STATE_ENABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(argument.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+
+ assertThat(argument.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
}
@Test
@@ -438,8 +438,7 @@
eq(COMPONENT_ENABLED_STATE_DISABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(argument.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+ assertThat(argument.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
}
@Test
@@ -458,8 +457,7 @@
eq(COMPONENT_ENABLED_STATE_ENABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(argument.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+ assertThat(argument.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
}
@Test
@@ -479,8 +477,7 @@
eq(COMPONENT_ENABLED_STATE_DISABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(argument.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+ assertThat(argument.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
}
// endregion
@@ -664,8 +661,7 @@
eq(COMPONENT_ENABLED_STATE_ENABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(actualComponent.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+ assertThat(actualComponent.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
verify(shortcutManager, never()).disableShortcuts(any())
verify(shortcutManager).enableShortcuts(listOf(SHORTCUT_ID))
val actualShortcuts = argumentCaptor<List<ShortcutInfo>>()
@@ -696,8 +692,7 @@
eq(COMPONENT_ENABLED_STATE_DISABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(argument.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+ assertThat(argument.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
verify(shortcutManager).disableShortcuts(listOf(SHORTCUT_ID))
verify(shortcutManager, never()).enableShortcuts(any())
verify(shortcutManager, never()).updateShortcuts(any())
@@ -714,8 +709,7 @@
eq(COMPONENT_ENABLED_STATE_DISABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(argument.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+ assertThat(argument.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
verify(shortcutManager).disableShortcuts(listOf(SHORTCUT_ID))
verify(shortcutManager, never()).enableShortcuts(any())
verify(shortcutManager, never()).updateShortcuts(any())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
index 88d7e9c..2dc78a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
@@ -587,14 +587,14 @@
assertEquals(addLink(mContext.getString(R.string.monitoring_description_two_named_vpns,
VPN_PACKAGE, VPN_PACKAGE_2)),
mFooterUtils.getVpnMessage(false, true, VPN_PACKAGE, VPN_PACKAGE_2));
- assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
- VPN_PACKAGE)),
+ assertEquals(addLink(mContext.getString(
+ R.string.monitoring_description_managed_device_named_vpn, VPN_PACKAGE)),
mFooterUtils.getVpnMessage(true, false, VPN_PACKAGE, null));
assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
VPN_PACKAGE)),
mFooterUtils.getVpnMessage(false, false, VPN_PACKAGE, null));
- assertEquals(addLink(mContext.getString(R.string.monitoring_description_named_vpn,
- VPN_PACKAGE_2)),
+ assertEquals(addLink(mContext.getString(
+ R.string.monitoring_description_managed_device_named_vpn, VPN_PACKAGE_2)),
mFooterUtils.getVpnMessage(true, true, null, VPN_PACKAGE_2));
assertEquals(addLink(mContext.getString(
R.string.monitoring_description_managed_profile_named_vpn,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index e0af81a..9a8ec88 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -115,6 +115,7 @@
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.shade.data.repository.ShadeRepository;
import com.android.systemui.shade.transition.ShadeTransitionController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -158,6 +159,7 @@
import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
import com.android.systemui.statusbar.phone.TapAgainViewController;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
+import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -306,6 +308,8 @@
mEmptySpaceClickListenerCaptor;
@Mock protected ActivityStarter mActivityStarter;
@Mock protected KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor;
+ @Mock protected ShadeRepository mShadeRepository;
+ @Mock private CastController mCastController;
protected final int mMaxUdfpsBurnInOffsetY = 5;
protected KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
@@ -675,7 +679,9 @@
mFeatureFlags,
mInteractionJankMonitor,
mShadeLog,
- mKeyguardFaceAuthInteractor
+ mKeyguardFaceAuthInteractor,
+ mShadeRepository,
+ mCastController
);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
index f68c3a8..1cf3873 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
@@ -69,6 +69,7 @@
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.shade.data.repository.ShadeRepository;
import com.android.systemui.shade.transition.ShadeTransitionController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -87,8 +88,11 @@
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
+import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import dagger.Lazy;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -99,8 +103,6 @@
import java.util.List;
-import dagger.Lazy;
-
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@@ -156,6 +158,7 @@
@Mock private ShadeLogger mShadeLogger;
@Mock private DumpManager mDumpManager;
@Mock private UiEventLogger mUiEventLogger;
+ @Mock private CastController mCastController;
private SysuiStatusBarStateController mStatusBarStateController;
@@ -244,7 +247,9 @@
mFeatureFlags,
mInteractionJankMonitor,
mShadeLogger,
- mock(KeyguardFaceAuthInteractor.class)
+ mock(KeyguardFaceAuthInteractor.class),
+ mock(ShadeRepository.class),
+ mCastController
);
mFragmentListener = mQsController.getQsFragmentListener();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
new file mode 100644
index 0000000..8f2c93b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.data.repository
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.RoboPilotTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.shade.ShadeExpansionChangeEvent
+import com.android.systemui.shade.ShadeExpansionStateManager
+import com.android.systemui.shade.domain.model.ShadeModel
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RoboPilotTest
+@RunWith(AndroidJUnit4::class)
+class ShadeRepositoryImplTest : SysuiTestCase() {
+
+ @Mock private lateinit var shadeExpansionStateManager: ShadeExpansionStateManager
+ private val testDispatcher = StandardTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
+
+ private lateinit var underTest: ShadeRepositoryImpl
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ underTest = ShadeRepositoryImpl(shadeExpansionStateManager)
+ }
+
+ @Test
+ fun shadeExpansionChangeEvent() =
+ testScope.runTest {
+ var latest: ShadeModel? = null
+ val job = underTest.shadeModel.onEach { latest = it }.launchIn(this)
+ runCurrent()
+ assertThat(latest?.expansionAmount).isEqualTo(0f)
+ assertThat(latest?.isExpanded).isEqualTo(false)
+ assertThat(latest?.isUserDragging).isEqualTo(false)
+
+ val captor = withArgCaptor {
+ verify(shadeExpansionStateManager).addExpansionListener(capture())
+ }
+
+ captor.onPanelExpansionChanged(
+ ShadeExpansionChangeEvent(
+ fraction = 1f,
+ expanded = true,
+ tracking = false,
+ dragDownPxAmount = 0f,
+ )
+ )
+ runCurrent()
+ assertThat(latest?.expansionAmount).isEqualTo(1f)
+ assertThat(latest?.isExpanded).isEqualTo(true)
+ assertThat(latest?.isUserDragging).isEqualTo(false)
+
+ captor.onPanelExpansionChanged(
+ ShadeExpansionChangeEvent(
+ fraction = .67f,
+ expanded = false,
+ tracking = true,
+ dragDownPxAmount = 0f,
+ )
+ )
+ runCurrent()
+ assertThat(latest?.expansionAmount).isEqualTo(.67f)
+ assertThat(latest?.isExpanded).isEqualTo(false)
+ assertThat(latest?.isUserDragging).isEqualTo(true)
+
+ job.cancel()
+ }
+
+ @Test
+ fun updateQsExpansion() =
+ testScope.runTest {
+ assertThat(underTest.qsExpansion.value).isEqualTo(0f)
+
+ underTest.setQsExpansion(.5f)
+ assertThat(underTest.qsExpansion.value).isEqualTo(.5f)
+
+ underTest.setQsExpansion(.82f)
+ assertThat(underTest.qsExpansion.value).isEqualTo(.82f)
+
+ underTest.setQsExpansion(1f)
+ assertThat(underTest.qsExpansion.value).isEqualTo(1f)
+ }
+
+ @Test
+ fun updateUdfpsTransitionToFullShadeProgress() =
+ testScope.runTest {
+ assertThat(underTest.udfpsTransitionToFullShadeProgress.value).isEqualTo(0f)
+
+ underTest.setUdfpsTransitionToFullShadeProgress(.5f)
+ assertThat(underTest.udfpsTransitionToFullShadeProgress.value).isEqualTo(.5f)
+
+ underTest.setUdfpsTransitionToFullShadeProgress(.82f)
+ assertThat(underTest.udfpsTransitionToFullShadeProgress.value).isEqualTo(.82f)
+
+ underTest.setUdfpsTransitionToFullShadeProgress(1f)
+ assertThat(underTest.udfpsTransitionToFullShadeProgress.value).isEqualTo(1f)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index 78f5bf2..eef4470 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
@@ -43,6 +43,8 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
@@ -172,7 +174,7 @@
}
@Test
- fun clockIdConflict_ErrorWithoutCrash() {
+ fun clockIdConflict_ErrorWithoutCrash_unloadDuplicate() {
val mockPluginLifecycle1 = mock<PluginLifecycleManager<ClockProviderPlugin>>()
val plugin1 = FakeClockPlugin()
.addClock("clock_1", "clock 1", { mockClock }, { mockThumbnail })
@@ -199,6 +201,8 @@
assertEquals(registry.createExampleClock("clock_2"), mockClock)
assertEquals(registry.getClockThumbnail("clock_1"), mockThumbnail)
assertEquals(registry.getClockThumbnail("clock_2"), mockThumbnail)
+ verify(mockPluginLifecycle1, never()).unloadPlugin()
+ verify(mockPluginLifecycle2, times(2)).unloadPlugin()
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index 2106da8..2351f760 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -15,6 +15,7 @@
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.qs.QS
import com.android.systemui.shade.ShadeViewController
+import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
import com.android.systemui.statusbar.notification.stack.AmbientState
@@ -127,6 +128,7 @@
},
qsTransitionControllerFactory = { qsTransitionController },
activityStarter = activityStarter,
+ shadeRepository = FakeShadeRepository(),
)
transitionController.addCallback(transitionControllerCallback)
whenever(nsslController.view).thenReturn(stackscroller)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index 9186c35..4c83194 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -617,24 +617,9 @@
}
@Test
- public void applyRoundnessAndInv_should_be_immediately_applied_on_childrenContainer_legacy()
- throws Exception {
- ExpandableNotificationRow group = mNotificationTestHelper.createGroup();
- group.useRoundnessSourceTypes(false);
- Assert.assertEquals(0f, group.getBottomRoundness(), 0.001f);
- Assert.assertEquals(0f, group.getChildrenContainer().getBottomRoundness(), 0.001f);
-
- group.requestBottomRoundness(1f, SourceType.from(""), false);
-
- Assert.assertEquals(1f, group.getBottomRoundness(), 0.001f);
- Assert.assertEquals(1f, group.getChildrenContainer().getBottomRoundness(), 0.001f);
- }
-
- @Test
public void applyRoundnessAndInvalidate_should_be_immediately_applied_on_childrenContainer()
throws Exception {
ExpandableNotificationRow group = mNotificationTestHelper.createGroup();
- group.useRoundnessSourceTypes(true);
Assert.assertEquals(0f, group.getBottomRoundness(), 0.001f);
Assert.assertEquals(0f, group.getChildrenContainer().getBottomRoundness(), 0.001f);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
index e41929f..be976a1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
@@ -25,7 +25,6 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.notification.LegacySourceType;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
@@ -158,55 +157,7 @@
}
@Test
- public void addNotification_shouldResetOnScrollRoundness() throws Exception {
- ExpandableNotificationRow row = mNotificationTestHelper.createRowWithRoundness(
- /* topRoundness = */ 1f,
- /* bottomRoundness = */ 1f,
- /* sourceType = */ LegacySourceType.OnScroll);
-
- mChildrenContainer.addNotification(row, 0);
-
- Assert.assertEquals(0f, row.getTopRoundness(), /* delta = */ 0f);
- Assert.assertEquals(0f, row.getBottomRoundness(), /* delta = */ 0f);
- }
-
- @Test
- public void addNotification_shouldNotResetOtherRoundness() throws Exception {
- ExpandableNotificationRow row1 = mNotificationTestHelper.createRowWithRoundness(
- /* topRoundness = */ 1f,
- /* bottomRoundness = */ 1f,
- /* sourceType = */ LegacySourceType.DefaultValue);
- ExpandableNotificationRow row2 = mNotificationTestHelper.createRowWithRoundness(
- /* topRoundness = */ 1f,
- /* bottomRoundness = */ 1f,
- /* sourceType = */ LegacySourceType.OnDismissAnimation);
-
- mChildrenContainer.addNotification(row1, 0);
- mChildrenContainer.addNotification(row2, 0);
-
- Assert.assertEquals(1f, row1.getTopRoundness(), /* delta = */ 0f);
- Assert.assertEquals(1f, row1.getBottomRoundness(), /* delta = */ 0f);
- Assert.assertEquals(1f, row2.getTopRoundness(), /* delta = */ 0f);
- Assert.assertEquals(1f, row2.getBottomRoundness(), /* delta = */ 0f);
- }
-
- @Test
- public void applyRoundnessAndInvalidate_should_be_immediately_applied_on_last_child_legacy() {
- mChildrenContainer.useRoundnessSourceTypes(false);
- List<ExpandableNotificationRow> children = mChildrenContainer.getAttachedChildren();
- ExpandableNotificationRow notificationRow = children.get(children.size() - 1);
- Assert.assertEquals(0f, mChildrenContainer.getBottomRoundness(), 0.001f);
- Assert.assertEquals(0f, notificationRow.getBottomRoundness(), 0.001f);
-
- mChildrenContainer.requestBottomRoundness(1f, SourceType.from(""), false);
-
- Assert.assertEquals(1f, mChildrenContainer.getBottomRoundness(), 0.001f);
- Assert.assertEquals(1f, notificationRow.getBottomRoundness(), 0.001f);
- }
-
- @Test
public void applyRoundnessAndInvalidate_should_be_immediately_applied_on_last_child() {
- mChildrenContainer.useRoundnessSourceTypes(true);
List<ExpandableNotificationRow> children = mChildrenContainer.getAttachedChildren();
ExpandableNotificationRow notificationRow = children.get(children.size() - 1);
Assert.assertEquals(0f, mChildrenContainer.getBottomRoundness(), 0.001f);
@@ -220,8 +171,6 @@
@Test
public void applyRoundnessAndInvalidate_should_be_immediately_applied_on_header() {
- mChildrenContainer.useRoundnessSourceTypes(true);
-
NotificationHeaderViewWrapper header = mChildrenContainer.getNotificationHeaderWrapper();
Assert.assertEquals(0f, header.getTopRoundness(), 0.001f);
@@ -232,7 +181,6 @@
@Test
public void applyRoundnessAndInvalidate_should_be_immediately_applied_on_headerLowPriority() {
- mChildrenContainer.useRoundnessSourceTypes(true);
mChildrenContainer.setIsLowPriority(true);
NotificationHeaderViewWrapper header = mChildrenContainer.getNotificationHeaderWrapper();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
deleted file mode 100644
index bd0a556..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification.stack;
-
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.res.Resources;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.testing.TestableLooper.RunWithLooper;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.logging.NotificationRoundnessLogger;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
-import com.android.systemui.util.DeviceConfigProxy;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-import java.util.HashSet;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
-public class NotificationRoundnessManagerTest extends SysuiTestCase {
-
- private NotificationRoundnessManager mRoundnessManager;
- private HashSet<ExpandableView> mAnimatedChildren = new HashSet<>();
- private Runnable mRoundnessCallback = mock(Runnable.class);
- private ExpandableNotificationRow mFirst;
- private ExpandableNotificationRow mSecond;
- private NotificationRoundnessLogger mLogger = mock(NotificationRoundnessLogger.class);
- private float mSmallRadiusRatio;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- final Resources resources = mContext.getResources();
- mSmallRadiusRatio = resources.getDimension(R.dimen.notification_corner_radius_small)
- / resources.getDimension(R.dimen.notification_corner_radius);
- mRoundnessManager = new NotificationRoundnessManager(
- new NotificationSectionsFeatureManager(new DeviceConfigProxy(), mContext),
- mLogger,
- mock(DumpManager.class),
- mock(FeatureFlags.class));
- allowTestableLooperAsMainThread();
- NotificationTestHelper testHelper = new NotificationTestHelper(
- mContext,
- mDependency,
- TestableLooper.get(this));
- mFirst = testHelper.createRow();
- mFirst.setHeadsUpAnimatingAwayListener(animatingAway
- -> mRoundnessManager.updateView(mFirst, false));
- mSecond = testHelper.createRow();
- mSecond.setHeadsUpAnimatingAwayListener(animatingAway
- -> mRoundnessManager.updateView(mSecond, false));
- mRoundnessManager.setOnRoundingChangedCallback(mRoundnessCallback);
- mRoundnessManager.setAnimatedChildren(mAnimatedChildren);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mFirst),
- createSection(null, null)
- });
- mRoundnessManager.setExpanded(1.0f, 1.0f);
- mRoundnessManager.setShouldRoundPulsingViews(true);
- reset(mRoundnessCallback);
- }
-
- @Test
- public void testCallbackCalledWhenSecondChanged() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mSecond),
- createSection(null, null)
- });
- verify(mRoundnessCallback, atLeast(1)).run();
- }
-
- @Test
- public void testCallbackCalledWhenFirstChanged() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mFirst),
- createSection(null, null)
- });
- verify(mRoundnessCallback, atLeast(1)).run();
- }
-
- @Test
- public void testCallbackCalledWhenSecondSectionFirstChanged() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mFirst),
- createSection(mSecond, null)
- });
- verify(mRoundnessCallback, atLeast(1)).run();
- }
-
- @Test
- public void testCallbackCalledWhenSecondSectionLastChanged() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mFirst),
- createSection(null, mSecond)
- });
- verify(mRoundnessCallback, atLeast(1)).run();
- }
-
- @Test
- public void testCallbackNotCalledWhenFirstChangesSections() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(null, mFirst),
- createSection(mFirst, null)
- });
- verify(mRoundnessCallback, never()).run();
- }
-
- @Test
- public void testRoundnessSetOnLast() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(1.0f, mSecond.getBottomRoundness(), 0.0f);
- Assert.assertEquals(mSmallRadiusRatio, mSecond.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundnessPulsing() throws Exception {
- // Let's create a notification that's neither the first or last item of the stack,
- // this way we'll ensure that it won't have any rounded corners by default.
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mSecond),
- createSection(null, null)
- });
- NotificationTestHelper testHelper = new NotificationTestHelper(
- mContext,
- mDependency,
- TestableLooper.get(this));
- ExpandableNotificationRow row = testHelper.createRow();
- NotificationEntry entry = mock(NotificationEntry.class);
- when(entry.getRow()).thenReturn(row);
-
- when(testHelper.getStatusBarStateController().isDozing()).thenReturn(true);
- row.setHeadsUp(true);
- mRoundnessManager.updateView(entry.getRow(), false);
- Assert.assertEquals(1f, row.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1f, row.getTopRoundness(), 0.0f);
-
- row.setHeadsUp(false);
- mRoundnessManager.updateView(entry.getRow(), false);
- Assert.assertEquals(mSmallRadiusRatio, row.getBottomRoundness(), 0.0f);
- Assert.assertEquals(mSmallRadiusRatio, row.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundnessSetOnSecondSectionLast() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mFirst),
- createSection(null, mSecond)
- });
- Assert.assertEquals(1.0f, mSecond.getBottomRoundness(), 0.0f);
- Assert.assertEquals(mSmallRadiusRatio, mSecond.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundnessSetOnSecondSectionFirst() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mFirst),
- createSection(mSecond, null)
- });
- Assert.assertEquals(mSmallRadiusRatio, mSecond.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mSecond.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundnessSetOnNew() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, null),
- createSection(null, null)
- });
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testCompleteReplacement() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testNotCalledWhenRemoved() {
- mFirst.setRemoved();
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(1.0f, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundedWhenPinnedAndCollapsed() {
- mFirst.setPinned(true);
- mRoundnessManager.setExpanded(0.0f /* expandedHeight */, 0.0f /* appearFraction */);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(1.0f, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundedWhenGoingAwayAndCollapsed() {
- mFirst.setHeadsUpAnimatingAway(true);
- mRoundnessManager.setExpanded(0.0f /* expandedHeight */, 0.0f /* appearFraction */);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(1.0f, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundedNormalRoundingWhenExpanded() {
- mFirst.setHeadsUpAnimatingAway(true);
- mRoundnessManager.setExpanded(1.0f /* expandedHeight */, 0.0f /* appearFraction */);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testTrackingHeadsUpRoundedIfPushingUp() {
- mRoundnessManager.setExpanded(1.0f /* expandedHeight */, -0.5f /* appearFraction */);
- mRoundnessManager.setTrackingHeadsUp(mFirst);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(1.0f, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testTrackingHeadsUpPartiallyRoundedIfPushingDown() {
- mRoundnessManager.setExpanded(1.0f /* expandedHeight */, 0.5f /* appearFraction */);
- mRoundnessManager.setTrackingHeadsUp(mFirst);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(0.5f, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(0.5f, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundingUpdatedWhenAnimatingAwayTrue() {
- mRoundnessManager.setExpanded(0.0f, 0.0f);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- mFirst.setHeadsUpAnimatingAway(true);
- Assert.assertEquals(1.0f, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mFirst.getTopRoundness(), 0.0f);
- }
-
-
- @Test
- public void testRoundingUpdatedWhenAnimatingAwayFalse() {
- mRoundnessManager.setExpanded(0.0f, 0.0f);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- mFirst.setHeadsUpAnimatingAway(true);
- mFirst.setHeadsUpAnimatingAway(false);
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testNoViewsFirstOrLastInSectionWhenSecondSectionEmpty() {
- Assert.assertTrue(mFirst.isFirstInSection());
- Assert.assertTrue(mFirst.isLastInSection());
- }
-
- @Test
- public void testNoViewsFirstOrLastInSectionWhenFirstSectionEmpty() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(null, null),
- createSection(mSecond, mSecond)
- });
- Assert.assertTrue(mSecond.isFirstInSection());
- Assert.assertTrue(mSecond.isLastInSection());
- }
-
- @Test
- public void testFirstAndLastViewsInSectionSetWhenBothSectionsNonEmpty() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mFirst),
- createSection(mSecond, mSecond)
- });
- Assert.assertTrue(mFirst.isFirstInSection());
- Assert.assertTrue(mFirst.isLastInSection());
- Assert.assertTrue(mSecond.isFirstInSection());
- Assert.assertTrue(mSecond.isLastInSection());
- }
-
- @Test
- public void testLoggingOnRoundingUpdate() {
- NotificationSection[] sections = new NotificationSection[]{
- createSection(mFirst, mSecond),
- createSection(null, null)
- };
- mRoundnessManager.updateRoundedChildren(sections);
- verify(mLogger).onSectionCornersUpdated(sections, /*anyChanged=*/ true);
- verify(mLogger, atLeast(1)).onCornersUpdated(eq(mFirst), anyBoolean(),
- anyBoolean(), anyBoolean(), anyBoolean());
- verify(mLogger, atLeast(1)).onCornersUpdated(eq(mSecond), anyBoolean(),
- anyBoolean(), anyBoolean(), anyBoolean());
- }
-
- private NotificationSection createSection(ExpandableNotificationRow first,
- ExpandableNotificationRow last) {
- NotificationSection section = mock(NotificationSection.class);
- when(section.getFirstVisibleChild()).thenReturn(first);
- when(section.getLastVisibleChild()).thenReturn(last);
- return section;
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
index 30da08e..f38881c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -96,8 +96,7 @@
mIncomingHeaderController,
mPeopleHeaderController,
mAlertingHeaderController,
- mSilentHeaderController,
- mFeatureFlag
+ mSilentHeaderController
);
// Required in order for the header inflation to work properly
when(mNssl.generateLayoutParams(any(AttributeSet.class)))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
index b1d3daa..05b70eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
@@ -12,7 +12,6 @@
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator
import com.android.systemui.statusbar.NotificationShelf
import com.android.systemui.statusbar.StatusBarIconView
-import com.android.systemui.statusbar.notification.LegacySourceType
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
@@ -359,39 +358,6 @@
)
}
- @Test
- fun resetOnScrollRoundness_shouldSetOnScrollTo0() {
- val row: ExpandableNotificationRow = notificationTestHelper.createRowWithRoundness(
- /* topRoundness = */ 1f,
- /* bottomRoundness = */ 1f,
- /* sourceType = */ LegacySourceType.OnScroll)
-
- NotificationShelf.resetLegacyOnScrollRoundness(row)
-
- assertEquals(0f, row.topRoundness)
- assertEquals(0f, row.bottomRoundness)
- }
-
- @Test
- fun resetOnScrollRoundness_shouldNotResetOtherRoundness() {
- val row1: ExpandableNotificationRow = notificationTestHelper.createRowWithRoundness(
- /* topRoundness = */ 1f,
- /* bottomRoundness = */ 1f,
- /* sourceType = */ LegacySourceType.DefaultValue)
- val row2: ExpandableNotificationRow = notificationTestHelper.createRowWithRoundness(
- /* topRoundness = */ 1f,
- /* bottomRoundness = */ 1f,
- /* sourceType = */ LegacySourceType.OnDismissAnimation)
-
- NotificationShelf.resetLegacyOnScrollRoundness(row1)
- NotificationShelf.resetLegacyOnScrollRoundness(row2)
-
- assertEquals(1f, row1.topRoundness)
- assertEquals(1f, row1.bottomRoundness)
- assertEquals(1f, row2.topRoundness)
- assertEquals(1f, row2.bottomRoundness)
- }
-
private fun setFractionToShade(fraction: Float) {
whenever(ambientState.fractionToShade).thenReturn(fraction)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
index 81a3f12..45725ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
@@ -6,7 +6,6 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
import com.android.systemui.util.mockito.mock
import junit.framework.Assert.assertEquals
@@ -30,14 +29,7 @@
NotificationTestHelper(mContext, mDependency, TestableLooper.get(this))
}
- private fun notificationTargetsHelper(
- notificationGroupCorner: Boolean = true,
- ) =
- NotificationTargetsHelper(
- FakeFeatureFlags().apply {
- set(Flags.USE_ROUNDNESS_SOURCETYPES, notificationGroupCorner)
- }
- )
+ private fun notificationTargetsHelper() = NotificationTargetsHelper(FakeFeatureFlags())
@Test
fun targetsForFirstNotificationInGroup() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index 205cebd..2f1e372 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -34,8 +34,6 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.ShadeHeadsUpTracker;
@@ -82,7 +80,6 @@
private KeyguardStateController mKeyguardStateController;
private CommandQueue mCommandQueue;
private NotificationRoundnessManager mNotificationRoundnessManager;
- private FeatureFlags mFeatureFlag;
@Before
public void setUp() throws Exception {
@@ -103,9 +100,7 @@
mKeyguardStateController = mock(KeyguardStateController.class);
mCommandQueue = mock(CommandQueue.class);
mNotificationRoundnessManager = mock(NotificationRoundnessManager.class);
- mFeatureFlag = mock(FeatureFlags.class);
when(mShadeViewController.getShadeHeadsUpTracker()).thenReturn(mShadeHeadsUpTracker);
- when(mFeatureFlag.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES)).thenReturn(true);
mHeadsUpAppearanceController = new HeadsUpAppearanceController(
mock(NotificationIconAreaController.class),
mHeadsUpManager,
@@ -118,7 +113,6 @@
mStackScrollerController,
mShadeViewController,
mNotificationRoundnessManager,
- mFeatureFlag,
mHeadsUpStatusBarView,
new Clock(mContext, null),
Optional.of(mOperatorNameView));
@@ -202,7 +196,6 @@
mStackScrollerController,
mShadeViewController,
mNotificationRoundnessManager,
- mFeatureFlag,
mHeadsUpStatusBarView,
new Clock(mContext, null),
Optional.empty());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 6be0e2d..e56f0d6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -84,6 +84,7 @@
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.unfold.SysUIUnfoldComponent;
import com.google.common.truth.Truth;
@@ -151,13 +152,15 @@
private WindowOnBackInvokedDispatcher mOnBackInvokedDispatcher;
@Captor
private ArgumentCaptor<OnBackInvokedCallback> mBackCallbackCaptor;
+ @Captor
+ private ArgumentCaptor<KeyguardStateController.Callback> mKeyguardStateControllerCallback;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContainer.findViewById(anyInt())).thenReturn(mKeyguardMessageArea);
- when(mKeyguardMessageAreaFactory.create(any(KeyguardMessageArea.class)))
+ when(mKeyguardMessageAreaFactory.create(any()))
.thenReturn(mKeyguardMessageAreaController);
when(mBouncerView.getDelegate()).thenReturn(mBouncerViewDelegate);
when(mBouncerViewDelegate.getBackCallback()).thenReturn(mBouncerViewDelegateBackCallback);
@@ -909,4 +912,26 @@
// THEN the alternateBouncer doesn't hide
verify(mAlternateBouncerInteractor, never()).hide();
}
+
+ @Test
+ public void onDeviceUnlocked_hideAlternateBouncerAndClearMessageArea() {
+ reset(mKeyguardUpdateMonitor);
+ reset(mKeyguardMessageAreaController);
+
+ // GIVEN keyguard state controller callback is registered
+ verify(mKeyguardStateController).addCallback(mKeyguardStateControllerCallback.capture());
+
+ // GIVEN alternate bouncer state = not visible
+ when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(false);
+
+ // WHEN the device is unlocked
+ mKeyguardStateControllerCallback.getValue().onUnlockedChanged();
+
+ // THEN the false visibility state is propagated to the keyguardUpdateMonitor
+ verify(mKeyguardUpdateMonitor).setAlternateBouncerShowing(eq(false));
+
+ // THEN message area visibility updated to FALSE with empty message
+ verify(mKeyguardMessageAreaController).setIsVisible(eq(false));
+ verify(mKeyguardMessageAreaController).setMessage(eq(""));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
index 3ec9690..bde05b9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
@@ -53,6 +53,7 @@
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import org.junit.After
import org.junit.Before
import org.junit.Test
@@ -92,13 +93,15 @@
private val mobileMappings = FakeMobileMappingsProxy()
private val subscriptionManagerProxy = FakeSubscriptionManagerProxy()
+ private val testDispatcher = UnconfinedTestDispatcher()
private val scope = CoroutineScope(IMMEDIATE)
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- logFactory = TableLogBufferFactory(dumpManager, FakeSystemClock())
+ logFactory =
+ TableLogBufferFactory(dumpManager, FakeSystemClock(), mock(), testDispatcher, scope)
// Never start in demo mode
whenever(demoModeController.isInDemoMode).thenReturn(false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
index 37fac34..7573b28 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
@@ -61,11 +61,18 @@
internal class DemoMobileConnectionParameterizedTest(private val testCase: TestCase) :
SysuiTestCase() {
- private val logFactory = TableLogBufferFactory(mock(), FakeSystemClock())
-
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
+ private val logFactory =
+ TableLogBufferFactory(
+ mock(),
+ FakeSystemClock(),
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
+
private val fakeNetworkEventFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
private val fakeWifiEventFlow = MutableStateFlow<FakeWifiEventModel?>(null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
index 1251dfa..efaf152 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
@@ -54,13 +54,20 @@
@SmallTest
class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
private val dumpManager: DumpManager = mock()
- private val logFactory = TableLogBufferFactory(dumpManager, FakeSystemClock())
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
private val fakeNetworkEventFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
private val fakeWifiEventFlow = MutableStateFlow<FakeWifiEventModel?>(null)
+ private val logFactory =
+ TableLogBufferFactory(
+ dumpManager,
+ FakeSystemClock(),
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
private lateinit var underTest: DemoMobileConnectionsRepository
private lateinit var mobileDataSource: DemoModeMobileConnectionDataSource
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
index 9f77744..b701fbd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
@@ -66,7 +66,15 @@
private val systemClock = FakeSystemClock()
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
- private val tableLogBuffer = TableLogBuffer(maxSize = 100, name = "TestName", systemClock)
+ private val tableLogBuffer =
+ TableLogBuffer(
+ maxSize = 100,
+ name = "TestName",
+ systemClock,
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
private val mobileFactory = mock<MobileConnectionRepositoryImpl.Factory>()
private val carrierMergedFactory = mock<CarrierMergedConnectionRepository.Factory>()
@@ -294,7 +302,14 @@
@Test
fun factory_reusesLogBuffersForSameConnection() =
testScope.runTest {
- val realLoggerFactory = TableLogBufferFactory(mock(), FakeSystemClock())
+ val realLoggerFactory =
+ TableLogBufferFactory(
+ mock(),
+ FakeSystemClock(),
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
val factory =
FullMobileConnectionRepository.Factory(
@@ -329,7 +344,14 @@
@Test
fun factory_reusesLogBuffersForSameSubIDevenIfCarrierMerged() =
testScope.runTest {
- val realLoggerFactory = TableLogBufferFactory(mock(), FakeSystemClock())
+ val realLoggerFactory =
+ TableLogBufferFactory(
+ mock(),
+ FakeSystemClock(),
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
val factory =
FullMobileConnectionRepository.Factory(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
index c84c9c0..6e1ab58 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
@@ -61,6 +61,16 @@
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
+ private val tableLogBuffer =
+ TableLogBuffer(
+ 8,
+ "MobileIconsInteractorTest",
+ FakeSystemClock(),
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
+
@Mock private lateinit var carrierConfigTracker: CarrierConfigTracker
@Before
@@ -687,16 +697,14 @@
}
companion object {
- private val tableLogBuffer =
- TableLogBuffer(8, "MobileIconsInteractorTest", FakeSystemClock())
private const val SUB_1_ID = 1
private val SUB_1 = SubscriptionModel(subscriptionId = SUB_1_ID)
- private val CONNECTION_1 = FakeMobileConnectionRepository(SUB_1_ID, tableLogBuffer)
+ private val CONNECTION_1 = FakeMobileConnectionRepository(SUB_1_ID, mock())
private const val SUB_2_ID = 2
private val SUB_2 = SubscriptionModel(subscriptionId = SUB_2_ID)
- private val CONNECTION_2 = FakeMobileConnectionRepository(SUB_2_ID, tableLogBuffer)
+ private val CONNECTION_2 = FakeMobileConnectionRepository(SUB_2_ID, mock())
private const val SUB_3_ID = 3
private val SUB_3_OPP =
@@ -705,7 +713,7 @@
isOpportunistic = true,
groupUuid = ParcelUuid(UUID.randomUUID()),
)
- private val CONNECTION_3 = FakeMobileConnectionRepository(SUB_3_ID, tableLogBuffer)
+ private val CONNECTION_3 = FakeMobileConnectionRepository(SUB_3_ID, mock())
private const val SUB_4_ID = 4
private val SUB_4_OPP =
@@ -714,6 +722,6 @@
isOpportunistic = true,
groupUuid = ParcelUuid(UUID.randomUUID()),
)
- private val CONNECTION_4 = FakeMobileConnectionRepository(SUB_4_ID, tableLogBuffer)
+ private val CONNECTION_4 = FakeMobileConnectionRepository(SUB_4_ID, mock())
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java
index db50163..b8e4306 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java
@@ -1,6 +1,7 @@
package com.android.systemui.statusbar.policy;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -125,4 +126,20 @@
fail("Concurrent modification exception");
}
}
+
+ @Test
+ public void hasConnectedCastDevice_connected() {
+ CastController.CastDevice castDevice = new CastController.CastDevice();
+ castDevice.state = CastController.CastDevice.STATE_CONNECTED;
+ mController.startCasting(castDevice);
+ assertTrue(mController.hasConnectedCastDevice());
+ }
+
+ @Test
+ public void hasConnectedCastDevice_notConnected() {
+ CastController.CastDevice castDevice = new CastController.CastDevice();
+ castDevice.state = CastController.CastDevice.STATE_CONNECTING;
+ mController.startCasting(castDevice);
+ assertTrue(mController.hasConnectedCastDevice());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 1510ee8..47a86b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -380,7 +380,7 @@
mPositioner,
mock(DisplayController.class),
mOneHandedOptional,
- mock(DragAndDropController.class),
+ Optional.of(mock(DragAndDropController.class)),
syncExecutor,
mock(Handler.class),
mTaskViewTransitions,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
index c3bb771..14c3f3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
@@ -69,7 +69,7 @@
BubblePositioner positioner,
DisplayController displayController,
Optional<OneHandedController> oneHandedOptional,
- DragAndDropController dragAndDropController,
+ Optional<DragAndDropController> dragAndDropController,
ShellExecutor shellMainExecutor,
Handler shellMainHandler,
TaskViewTransitions taskViewTransitions,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFingerprintPropertyRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFingerprintPropertyRepository.kt
new file mode 100644
index 0000000..d9012a5
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFingerprintPropertyRepository.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.data.repository
+
+import android.hardware.biometrics.SensorLocationInternal
+import com.android.systemui.biometrics.shared.model.FingerprintSensorType
+import com.android.systemui.biometrics.shared.model.SensorStrength
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+class FakeFingerprintPropertyRepository : FingerprintPropertyRepository {
+
+ private val _isInitialized: MutableStateFlow<Boolean> = MutableStateFlow(false)
+ override val isInitialized = _isInitialized.asStateFlow()
+
+ private val _sensorId: MutableStateFlow<Int> = MutableStateFlow(-1)
+ override val sensorId: StateFlow<Int> = _sensorId.asStateFlow()
+
+ private val _strength: MutableStateFlow<SensorStrength> =
+ MutableStateFlow(SensorStrength.CONVENIENCE)
+ override val strength = _strength.asStateFlow()
+
+ private val _sensorType: MutableStateFlow<FingerprintSensorType> =
+ MutableStateFlow(FingerprintSensorType.UNKNOWN)
+ override val sensorType: StateFlow<FingerprintSensorType> = _sensorType.asStateFlow()
+
+ private val _sensorLocation: MutableStateFlow<SensorLocationInternal> =
+ MutableStateFlow(SensorLocationInternal.DEFAULT)
+ override val sensorLocation = _sensorLocation.asStateFlow()
+
+ fun setProperties(
+ sensorId: Int,
+ strength: SensorStrength,
+ sensorType: FingerprintSensorType,
+ sensorLocation: SensorLocationInternal
+ ) {
+ _sensorId.value = sensorId
+ _strength.value = strength
+ _sensorType.value = sensorType
+ _sensorLocation.value = sensorLocation
+ _isInitialized.value = true
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
index 2c0a8fd..492e542 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
@@ -21,13 +21,27 @@
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
-/** Fake implementation of [KeyguardRepository] */
+/** Fake implementation of [ShadeRepository] */
class FakeShadeRepository : ShadeRepository {
private val _shadeModel = MutableStateFlow(ShadeModel())
override val shadeModel: Flow<ShadeModel> = _shadeModel
+ private val _qsExpansion = MutableStateFlow(0f)
+ override val qsExpansion = _qsExpansion
+
+ private val _udfpsTransitionToFullShadeProgress = MutableStateFlow(0f)
+ override val udfpsTransitionToFullShadeProgress = _udfpsTransitionToFullShadeProgress
+
fun setShadeModel(model: ShadeModel) {
_shadeModel.value = model
}
+
+ override fun setQsExpansion(qsExpansion: Float) {
+ _qsExpansion.value = qsExpansion
+ }
+
+ override fun setUdfpsTransitionToFullShadeProgress(progress: Float) {
+ _udfpsTransitionToFullShadeProgress.value = progress
+ }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeCastController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeCastController.java
index f6b24da..84ace7c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeCastController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeCastController.java
@@ -51,4 +51,9 @@
public void stopCasting(CastDevice device) {
}
+
+ @Override
+ public boolean hasConnectedCastDevice() {
+ return false;
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index a3b4a0f..d36c959 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1012,8 +1012,7 @@
+ Binder.getCallingPid() + " for device id " + deviceId
+ " with package names " + Arrays.toString(client.mPackageNames));
}
- return IntPair.of(mProxyManager.getStateLocked(deviceId,
- mUiAutomationManager.isUiAutomationRunningLocked()),
+ return IntPair.of(mProxyManager.getStateLocked(deviceId),
client.mLastSentRelevantEventTypes);
}
mGlobalClients.register(callback, client);
@@ -1028,8 +1027,7 @@
+ Binder.getCallingPid() + " for device id " + deviceId
+ " with package names " + Arrays.toString(client.mPackageNames));
}
- return IntPair.of(mProxyManager.getStateLocked(deviceId,
- mUiAutomationManager.isUiAutomationRunningLocked()),
+ return IntPair.of(mProxyManager.getStateLocked(deviceId),
client.mLastSentRelevantEventTypes);
}
userState.mUserClients.register(callback, client);
@@ -4024,9 +4022,8 @@
final long identity = Binder.clearCallingIdentity();
try {
- mProxyManager.registerProxy(client, displayId, mContext,
- sIdCounter++, mMainHandler, mSecurityPolicy, this, getTraceManager(),
- mWindowManagerService);
+ mProxyManager.registerProxy(client, displayId, sIdCounter++, mSecurityPolicy,
+ this, getTraceManager(), mWindowManagerService);
synchronized (mLock) {
notifyClearAccessibilityCacheLocked();
diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
index d417197..6dc8fb3 100644
--- a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
@@ -61,7 +61,6 @@
* proxy connection will belong to a separate user state.
*
* TODO(241117292): Remove or cut down during simultaneous user refactoring.
- * TODO(262244375): Add unit tests.
*/
public class ProxyManager {
private static final boolean DEBUG = false;
@@ -128,7 +127,7 @@
RemoteCallbackList<IAccessibilityManagerClient> getCurrentUserClientsLocked();
}
- ProxyManager(Object lock, AccessibilityWindowManager awm,
+ public ProxyManager(Object lock, AccessibilityWindowManager awm,
Context context, Handler mainHandler, UiAutomationManager uiAutomationManager,
SystemSupport systemSupport) {
mLock = lock;
@@ -144,9 +143,7 @@
* Creates the service connection.
*/
public void registerProxy(IAccessibilityServiceClient client, int displayId,
- Context context,
- int id, Handler mainHandler,
- AccessibilitySecurityPolicy securityPolicy,
+ int id, AccessibilitySecurityPolicy securityPolicy,
AbstractAccessibilityServiceConnection.SystemSupport systemSupport,
AccessibilityTrace trace,
WindowManagerInternal windowManagerInternal) throws RemoteException {
@@ -169,8 +166,8 @@
info.setComponentName(new ComponentName(PROXY_COMPONENT_PACKAGE_NAME,
componentClassDisplayName));
ProxyAccessibilityServiceConnection connection =
- new ProxyAccessibilityServiceConnection(context, info.getComponentName(), info,
- id, mainHandler, mLock, securityPolicy, systemSupport, trace,
+ new ProxyAccessibilityServiceConnection(mContext, info.getComponentName(), info,
+ id, mMainHandler, mLock, securityPolicy, systemSupport, trace,
windowManagerInternal,
mA11yWindowManager, displayId, deviceId);
@@ -263,7 +260,7 @@
* When the connection is removed from tracking in ProxyManager, propagate changes to other a11y
* system components like the input filter and IAccessibilityManagerClients.
*/
- public void updateStateForRemovedDisplay(int displayId, int deviceId) {
+ private void updateStateForRemovedDisplay(int displayId, int deviceId) {
mA11yWindowManager.stopTrackingDisplayProxy(displayId);
// A11yInputFilter isn't thread-safe, so post on the system thread.
mMainHandler.post(
@@ -360,8 +357,9 @@
/**
* If there is at least one proxy, accessibility is enabled.
*/
- public int getStateLocked(int deviceId, boolean automationRunning) {
+ public int getStateLocked(int deviceId) {
int clientState = 0;
+ final boolean automationRunning = mUiAutomationManager.isUiAutomationRunningLocked();
if (automationRunning) {
clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
}
@@ -387,7 +385,7 @@
/**
* If there is at least one proxy, accessibility is enabled.
*/
- public int getStateForDisplayIdLocked(ProxyAccessibilityServiceConnection proxy) {
+ private int getStateForDisplayIdLocked(ProxyAccessibilityServiceConnection proxy) {
int clientState = 0;
if (proxy != null) {
clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
@@ -409,14 +407,14 @@
/**
* Gets the last state for a device.
*/
- public int getLastSentStateLocked(int deviceId) {
+ private int getLastSentStateLocked(int deviceId) {
return mLastStates.get(deviceId, 0);
}
/**
* Sets the last state for a device.
*/
- public void setLastStateLocked(int deviceId, int proxyState) {
+ private void setLastStateLocked(int deviceId, int proxyState) {
mLastStates.put(deviceId, proxyState);
}
@@ -429,7 +427,7 @@
* Virtual Device, the app clients will get the aggregated event types for all proxy-ed displays
* belonging to a VirtualDevice.
*/
- public void updateRelevantEventTypesLocked(int deviceId) {
+ private void updateRelevantEventTypesLocked(int deviceId) {
if (!isProxyedDeviceId(deviceId)) {
return;
}
@@ -452,7 +450,7 @@
/**
* Returns the relevant event types for a Client.
*/
- int computeRelevantEventTypesLocked(AccessibilityManagerService.Client client) {
+ public int computeRelevantEventTypesLocked(AccessibilityManagerService.Client client) {
int relevantEventTypes = 0;
for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
final ProxyAccessibilityServiceConnection proxy =
@@ -578,9 +576,8 @@
/**
* Updates the states of the app AccessibilityManagers.
*/
- public void scheduleUpdateProxyClientsIfNeededLocked(int deviceId) {
- final int proxyState = getStateLocked(deviceId,
- mUiAutomationManager.isUiAutomationRunningLocked());
+ private void scheduleUpdateProxyClientsIfNeededLocked(int deviceId) {
+ final int proxyState = getStateLocked(deviceId);
if (DEBUG) {
Slog.v(LOG_TAG, "State for device id " + deviceId + " is " + proxyState);
Slog.v(LOG_TAG, "Last state for device id " + deviceId + " is "
@@ -606,7 +603,7 @@
*
* @see AccessibilityManager.AccessibilityServicesStateChangeListener
*/
- public void scheduleNotifyProxyClientsOfServicesStateChangeLocked(int deviceId) {
+ private void scheduleNotifyProxyClientsOfServicesStateChangeLocked(int deviceId) {
if (DEBUG) {
Slog.v(LOG_TAG, "Notify services state change at device id " + deviceId);
}
@@ -625,7 +622,7 @@
/**
* Updates the focus appearance of AccessibilityManagerClients.
*/
- public void updateFocusAppearanceLocked(int deviceId) {
+ private void updateFocusAppearanceLocked(int deviceId) {
if (DEBUG) {
Slog.v(LOG_TAG, "Update proxy focus appearance at device id " + deviceId);
}
@@ -764,7 +761,7 @@
/**
* Sets a Client device id if the app uid belongs to the virtual device.
*/
- public void updateDeviceIdsIfNeededLocked(int deviceId) {
+ private void updateDeviceIdsIfNeededLocked(int deviceId) {
final RemoteCallbackList<IAccessibilityManagerClient> userClients =
mSystemSupport.getCurrentUserClientsLocked();
final RemoteCallbackList<IAccessibilityManagerClient> globalClients =
@@ -777,7 +774,7 @@
/**
* Updates the device ids of IAccessibilityManagerClients if needed.
*/
- public void updateDeviceIdsIfNeededLocked(int deviceId,
+ private void updateDeviceIdsIfNeededLocked(int deviceId,
@NonNull RemoteCallbackList<IAccessibilityManagerClient> clients) {
final VirtualDeviceManagerInternal localVdm = getLocalVdm();
if (localVdm == null) {
@@ -809,14 +806,17 @@
}
}
- void setAccessibilityInputFilter(AccessibilityInputFilter filter) {
+ /**
+ * Sets the input filter for enabling and disabling features for proxy displays.
+ */
+ public void setAccessibilityInputFilter(AccessibilityInputFilter filter) {
if (DEBUG) {
Slog.v(LOG_TAG, "Set proxy input filter to " + filter);
}
mA11yInputFilter = filter;
}
- VirtualDeviceManagerInternal getLocalVdm() {
+ private VirtualDeviceManagerInternal getLocalVdm() {
if (mLocalVdm == null) {
mLocalVdm = LocalServices.getService(VirtualDeviceManagerInternal.class);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
index a13df47..9747579 100644
--- a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
+++ b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
@@ -36,6 +36,7 @@
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import com.android.internal.R;
+import com.android.internal.accessibility.util.AccessibilityUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ScreenshotHelper;
@@ -302,8 +303,10 @@
case AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT:
return takeScreenshot();
case AccessibilityService.GLOBAL_ACTION_KEYCODE_HEADSETHOOK:
- sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HEADSETHOOK,
- InputDevice.SOURCE_KEYBOARD);
+ if (!AccessibilityUtils.interceptHeadsetHookForActiveCall(mContext)) {
+ sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HEADSETHOOK,
+ InputDevice.SOURCE_KEYBOARD);
+ }
return true;
case AccessibilityService.GLOBAL_ACTION_DPAD_UP:
sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_UP,
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index bc5d645..ac77043 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -16,13 +16,18 @@
package com.android.server.autofill;
+import static com.android.server.autofill.Helper.sDebug;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
import android.app.assist.AssistStructure.WindowNode;
import android.content.ComponentName;
+import android.content.Context;
+import android.hardware.display.DisplayManager;
import android.metrics.LogMaker;
+import android.os.UserManager;
import android.service.autofill.Dataset;
import android.service.autofill.InternalSanitizer;
import android.service.autofill.SaveInfo;
@@ -30,6 +35,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
+import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.view.autofill.AutofillId;
@@ -37,6 +43,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.ArrayUtils;
+import com.android.server.utils.Slogf;
import java.io.PrintWriter;
import java.util.ArrayDeque;
@@ -281,6 +288,38 @@
return true;
}
+ /**
+ * Gets a context with the proper display id.
+ *
+ * <p>For most cases it will return the provided context, but on devices that
+ * {@link UserManager#isVisibleBackgroundUsersEnabled() support visible background users}, it
+ * will return a context with the display pased as parameter.
+ */
+ static Context getDisplayContext(Context context, int displayId) {
+ if (!UserManager.isVisibleBackgroundUsersEnabled()) {
+ return context;
+ }
+ if (context.getDisplayId() == displayId) {
+ if (sDebug) {
+ Slogf.d(TAG, "getDisplayContext(): context %s already has displayId %d", context,
+ displayId);
+ }
+ return context;
+ }
+ if (sDebug) {
+ Slogf.d(TAG, "Creating context for display %d", displayId);
+ }
+ Display display = context.getSystemService(DisplayManager.class).getDisplay(displayId);
+ if (display == null) {
+ Slogf.wtf(TAG, "Could not get context with displayId %d, Autofill operations will "
+ + "probably fail)", displayId);
+ return context;
+ }
+
+ return context.createDisplayContext(display);
+ }
+
+
private interface ViewNodeFilter {
boolean matches(ViewNode node);
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 3ab5bca..f83d734 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -164,10 +164,12 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.ArrayUtils;
+import com.android.server.LocalServices;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.autofill.ui.InlineFillUi;
import com.android.server.autofill.ui.PendingUi;
import com.android.server.inputmethod.InputMethodManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -214,7 +216,12 @@
private final AutofillManagerServiceImpl mService;
private final Handler mHandler;
private final AutoFillUI mUi;
- @NonNull private final Context mContext;
+
+ /**
+ * Context associated with the session, it has the same {@link Context#getDisplayId() displayId}
+ * of the activity being autofilled.
+ */
+ private final Context mContext;
private final MetricsLogger mMetricsLogger = new MetricsLogger();
@@ -1352,7 +1359,9 @@
mHasCallback = hasCallback;
mUiLatencyHistory = uiLatencyHistory;
mWtfHistory = wtfHistory;
- mContext = context;
+ int displayId = LocalServices.getService(ActivityTaskManagerInternal.class)
+ .getDisplayId(activityToken);
+ mContext = Helper.getDisplayContext(context, displayId);
mComponentName = componentName;
mCompatMode = compatMode;
mSessionState = STATE_ACTIVE;
@@ -3401,7 +3410,7 @@
final long saveUiDisplayStartTimestamp = SystemClock.elapsedRealtime();
getUiForShowing().showSaveUi(serviceLabel, serviceIcon,
mService.getServicePackageName(), saveInfo, this,
- mComponentName, this, userId, mPendingSaveUi, isUpdate, mCompatMode,
+ mComponentName, this, mContext, mPendingSaveUi, isUpdate, mCompatMode,
response.getShowSaveDialogIcon());
mSaveEventLogger.maybeSetLatencySaveUiDisplayMillis(
SystemClock.elapsedRealtime()- saveUiDisplayStartTimestamp);
@@ -4272,7 +4281,7 @@
getUiForShowing().showFillUi(filledId, response, filterText,
mService.getServicePackageName(), mComponentName,
- targetLabel, targetIcon, this, userId, id, mCompatMode);
+ targetLabel, targetIcon, this, mContext, id, mCompatMode);
synchronized (mLock) {
mPresentationStatsEventLogger.maybeSetCountShown(
@@ -5453,6 +5462,7 @@
pw.print(prefix); pw.print("uid: "); pw.println(uid);
pw.print(prefix); pw.print("taskId: "); pw.println(taskId);
pw.print(prefix); pw.print("flags: "); pw.println(mFlags);
+ pw.print(prefix); pw.print("displayId: "); pw.println(mContext.getDisplayId());
pw.print(prefix); pw.print("state: "); pw.println(sessionStateAsString(mSessionState));
pw.print(prefix); pw.print("mComponentName: "); pw.println(mComponentName);
pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index cfd66f1..b3cbe45 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -23,7 +23,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -53,6 +52,7 @@
import com.android.server.UiModeManagerInternal;
import com.android.server.UiThread;
import com.android.server.autofill.Helper;
+import com.android.server.utils.Slogf;
import java.io.PrintWriter;
@@ -198,6 +198,7 @@
* @param serviceIcon icon of autofill service
* @param callback identifier for the caller
* @param userId the user associated wit the session
+ * @param context context with the proper state (like display id) to show the UI
* @param sessionId id of the autofill session
* @param compatMode whether the app is being autofilled in compatibility mode.
*/
@@ -205,11 +206,11 @@
@Nullable String filterText, @Nullable String servicePackageName,
@NonNull ComponentName componentName, @NonNull CharSequence serviceLabel,
@NonNull Drawable serviceIcon, @NonNull AutoFillUiCallback callback,
- @UserIdInt int userId, int sessionId, boolean compatMode) {
+ @NonNull Context context, int sessionId, boolean compatMode) {
if (sDebug) {
final int size = filterText == null ? 0 : filterText.length();
- Slog.d(TAG, "showFillUi(): id=" + focusedId + ", filter=" + size + " chars, userId="
- + userId);
+ Slogf.d(TAG, "showFillUi(): id=%s, filter=%d chars, displayId=%d", focusedId, size,
+ context.getDisplayId());
}
final LogMaker log = Helper
.newLogMaker(MetricsEvent.AUTOFILL_FILL_UI, componentName, servicePackageName,
@@ -224,10 +225,8 @@
return;
}
hideAllUiThread(callback);
- mFillUi = new FillUi(mContext, userId, response, focusedId,
- filterText, mOverlayControl, serviceLabel, serviceIcon,
- mUiModeMgr.isNightMode(),
- new FillUi.Callback() {
+ mFillUi = new FillUi(context, response, focusedId, filterText, mOverlayControl,
+ serviceLabel, serviceIcon, mUiModeMgr.isNightMode(), new FillUi.Callback() {
@Override
public void onResponsePicked(FillResponse response) {
log.setType(MetricsEvent.TYPE_DETAIL);
@@ -325,12 +324,12 @@
public void showSaveUi(@NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon,
@Nullable String servicePackageName, @NonNull SaveInfo info,
@NonNull ValueFinder valueFinder, @NonNull ComponentName componentName,
- @NonNull AutoFillUiCallback callback, @UserIdInt int userId,
+ @NonNull AutoFillUiCallback callback, @NonNull Context context,
@NonNull PendingUi pendingSaveUi, boolean isUpdate, boolean compatMode,
boolean showServiceIcon) {
if (sVerbose) {
- Slog.v(TAG, "showSaveUi(update=" + isUpdate + ") for " + componentName.toShortString()
- + " and user " + userId + ": " + info);
+ Slogf.v(TAG, "showSaveUi(update=%b) for %s and display %d: %s", isUpdate,
+ componentName.toShortString(), context.getDisplayId(), info);
}
int numIds = 0;
numIds += info.getRequiredIds() == null ? 0 : info.getRequiredIds().length;
@@ -350,7 +349,7 @@
}
hideAllUiThread(callback);
mSaveUiCallback = callback;
- mSaveUi = new SaveUi(mContext, userId, pendingSaveUi, serviceLabel, serviceIcon,
+ mSaveUi = new SaveUi(context, pendingSaveUi, serviceLabel, serviceIcon,
servicePackageName, componentName, info, valueFinder, mOverlayControl,
new SaveUi.OnSaveListener() {
@Override
diff --git a/services/autofill/java/com/android/server/autofill/ui/DisplayHelper.java b/services/autofill/java/com/android/server/autofill/ui/DisplayHelper.java
deleted file mode 100644
index 5353480..0000000
--- a/services/autofill/java/com/android/server/autofill/ui/DisplayHelper.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.autofill.ui;
-
-import static com.android.server.autofill.Helper.sDebug;
-
-import android.annotation.UserIdInt;
-import android.content.Context;
-import android.hardware.display.DisplayManager;
-import android.os.UserManager;
-import android.view.Display;
-
-import com.android.server.LocalServices;
-import com.android.server.pm.UserManagerInternal;
-import com.android.server.utils.Slogf;
-
-/**
- * Helper for display-related needs.
- */
-final class DisplayHelper {
-
- private static final String TAG = "AutofillDisplayHelper";
-
- private static final UserManagerInternal sUmi = LocalServices
- .getService(UserManagerInternal.class);
-
- /**
- * Gets a context with the proper display id set for the given user.
- *
- * <p>For most cases it will return the provided context, but on devices that
- * {@link UserManager#isVisibleBackgroundUsersEnabled() support visible background users}, it
- * will return a context with the display the user started visible on.
- */
- static Context getDisplayContext(Context context, @UserIdInt int userId) {
- if (!UserManager.isVisibleBackgroundUsersEnabled()) {
- return context;
- }
- int displayId = sUmi.getMainDisplayAssignedToUser(userId);
- if (sDebug) {
- Slogf.d(TAG, "Creating context for display %d for user %d", displayId, userId);
- }
- Display display = context.getSystemService(DisplayManager.class).getDisplay(displayId);
- if (display == null) {
- Slogf.wtf(TAG, "Could not get display with id %d (which is associated with user %d; "
- + "FillUi operations will probably fail", displayId, userId);
- return context;
- }
-
- return context.createDisplayContext(display);
- }
-
- private DisplayHelper() {
- throw new UnsupportedOperationException("Contains only static methods");
- }
-}
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index b651ae59..129ce72 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -22,7 +22,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UserIdInt;
import android.content.Context;
import android.content.IntentSender;
import android.content.pm.PackageManager;
@@ -61,6 +60,7 @@
import com.android.server.UiThread;
import com.android.server.autofill.AutofillManagerService;
import com.android.server.autofill.Helper;
+import com.android.server.utils.Slogf;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -134,14 +134,15 @@
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
}
- FillUi(@NonNull Context systemContext, @UserIdInt int userId, @NonNull FillResponse response,
+ FillUi(@NonNull Context context, @NonNull FillResponse response,
@NonNull AutofillId focusedViewId, @Nullable String filterText,
@NonNull OverlayControl overlayControl, @NonNull CharSequence serviceLabel,
@NonNull Drawable serviceIcon, boolean nightMode, @NonNull Callback callback) {
- if (sVerbose) Slog.v(TAG, "nightMode: " + nightMode);
+ if (sVerbose) {
+ Slogf.v(TAG, "nightMode: %b displayId: %d", nightMode, context.getDisplayId());
+ }
mThemeId = nightMode ? THEME_ID_DARK : THEME_ID_LIGHT;
mCallback = callback;
- Context context = DisplayHelper.getDisplayContext(systemContext, userId);
mFullScreen = isFullScreen(context);
mContext = new ContextThemeWrapper(context, mThemeId);
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index aec0bdf..1204259 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -21,7 +21,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UserIdInt;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.ComponentName;
@@ -71,6 +70,7 @@
import com.android.internal.util.ArrayUtils;
import com.android.server.UiThread;
import com.android.server.autofill.Helper;
+import com.android.server.utils.Slogf;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -173,14 +173,15 @@
private boolean mDestroyed;
- SaveUi(@NonNull Context systemContext, @UserIdInt int userId, @NonNull PendingUi pendingUi,
+ SaveUi(@NonNull Context context, @NonNull PendingUi pendingUi,
@NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon,
@Nullable String servicePackageName, @NonNull ComponentName componentName,
@NonNull SaveInfo info, @NonNull ValueFinder valueFinder,
@NonNull OverlayControl overlayControl, @NonNull OnSaveListener listener,
boolean nightMode, boolean isUpdate, boolean compatMode, boolean showServiceIcon) {
- Context context = DisplayHelper.getDisplayContext(systemContext, userId);
- if (sVerbose) Slog.v(TAG, "nightMode: " + nightMode);
+ if (sVerbose) {
+ Slogf.v(TAG, "nightMode: %b displayId: %d", nightMode, context.getDisplayId());
+ }
mThemeId = nightMode ? THEME_ID_DARK : THEME_ID_LIGHT;
mPendingUi = pendingUi;
mListener = new OneActionThenDestroyListener(listener);
diff --git a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceCall.java b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceCall.java
index dd0bbf2..ac981d4 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceCall.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceCall.java
@@ -16,12 +16,14 @@
package com.android.server.companion.datatransfer.contextsync;
+import android.annotation.NonNull;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.telecom.Call;
import android.telecom.CallAudioState;
import android.telecom.VideoProfile;
@@ -46,7 +48,7 @@
private static final AtomicLong sNextId = new AtomicLong(1);
private final long mId;
- private final Call mCall;
+ private Call mCall;
@VisibleForTesting boolean mIsEnterprise;
@VisibleForTesting boolean mIsOtt;
private final String mCallingAppPackageName;
@@ -58,17 +60,23 @@
private boolean mIsMuted;
private final Set<Integer> mControls = new HashSet<>();
- public CrossDeviceCall(PackageManager packageManager, Call call,
+ public CrossDeviceCall(PackageManager packageManager, @NonNull Call call,
+ CallAudioState callAudioState) {
+ this(packageManager, call.getDetails(), callAudioState);
+ mCall = call;
+ final Bundle extras = new Bundle();
+ extras.putLong(EXTRA_CALL_ID, mId);
+ call.putExtras(extras);
+ }
+
+ CrossDeviceCall(PackageManager packageManager, Call.Details callDetails,
CallAudioState callAudioState) {
mId = sNextId.getAndIncrement();
- mCall = call;
- mCallingAppPackageName = call != null
- ? call.getDetails().getAccountHandle().getComponentName().getPackageName() : null;
- mIsOtt = call != null
- && (call.getDetails().getCallCapabilities() & Call.Details.PROPERTY_SELF_MANAGED)
+ mCallingAppPackageName =
+ callDetails.getAccountHandle().getComponentName().getPackageName();
+ mIsOtt = (callDetails.getCallCapabilities() & Call.Details.PROPERTY_SELF_MANAGED)
== Call.Details.PROPERTY_SELF_MANAGED;
- mIsEnterprise = call != null
- && (call.getDetails().getCallProperties() & Call.Details.PROPERTY_ENTERPRISE_CALL)
+ mIsEnterprise = (callDetails.getCallProperties() & Call.Details.PROPERTY_ENTERPRISE_CALL)
== Call.Details.PROPERTY_ENTERPRISE_CALL;
try {
final ApplicationInfo applicationInfo = packageManager
@@ -81,9 +89,7 @@
Slog.e(TAG, "Could not get application info for package " + mCallingAppPackageName, e);
}
mIsMuted = callAudioState != null && callAudioState.isMuted();
- if (call != null) {
- updateCallDetails(call.getDetails());
- }
+ updateCallDetails(callDetails);
}
private byte[] renderDrawableToByteArray(Drawable drawable) {
@@ -108,10 +114,10 @@
final Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
drawable.draw(canvas);
+ return renderBitmapToByteArray(bitmap);
} finally {
bitmap.recycle();
}
- return renderBitmapToByteArray(bitmap);
}
private byte[] renderBitmapToByteArray(Bitmap bitmap) {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index e76b628..a641e85 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -3534,21 +3534,29 @@
// - Sanitized ServiceState sent to all other apps with READ_PHONE_STATE
// - Sanitized ServiceState sent to all other apps with READ_PRIVILEGED_PHONE_STATE but not
// READ_PHONE_STATE
- BroadcastOptions options = createServiceStateBroadcastOptions(subId, phoneId);
+ //
+ // Create a unique delivery group key for each variant for SERVICE_STATE broadcast so
+ // that a new broadcast only replaces the pending broadcasts of the same variant.
+ // In order to create a unique delivery group key, append tag of the form
+ // "I:Included-permissions[,E:Excluded-permissions][,lbp]"
+ // Note: Given that location-bypass-packages are static, we can just append "lbp" to the
+ // tag to create a unique delivery group but if location-bypass-packages become dynamic
+ // in the future, we would need to create a unique key for each group of
+ // location-bypass-packages.
if (LocationAccessPolicy.isLocationModeEnabled(mContext, mContext.getUserId())) {
Intent fullIntent = createServiceStateIntent(state, subId, phoneId, false);
mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
fullIntent,
new String[]{Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_FINE_LOCATION},
- options);
+ createServiceStateBroadcastOptions(subId, phoneId, "I:RA"));
mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
fullIntent,
new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
Manifest.permission.ACCESS_FINE_LOCATION},
new String[]{Manifest.permission.READ_PHONE_STATE},
null,
- options);
+ createServiceStateBroadcastOptions(subId, phoneId, "I:RPA,E:R"));
Intent sanitizedIntent = createServiceStateIntent(state, subId, phoneId, true);
mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
@@ -3556,14 +3564,14 @@
new String[]{Manifest.permission.READ_PHONE_STATE},
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
null,
- options);
+ createServiceStateBroadcastOptions(subId, phoneId, "I:R,E:A"));
mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
sanitizedIntent,
new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE},
new String[]{Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_FINE_LOCATION},
null,
- options);
+ createServiceStateBroadcastOptions(subId, phoneId, "I:RP,E:RA"));
} else {
String[] locationBypassPackages = Binder.withCleanCallingIdentity(() ->
LocationAccessPolicy.getLocationBypassPackages(mContext));
@@ -3573,13 +3581,13 @@
mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
fullIntent,
new String[]{Manifest.permission.READ_PHONE_STATE},
- options);
+ createServiceStateBroadcastOptions(subId, phoneId, "I:R"));
mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
fullIntent,
new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE},
new String[]{Manifest.permission.READ_PHONE_STATE},
null,
- options);
+ createServiceStateBroadcastOptions(subId, phoneId, "I:RP,E:R"));
}
Intent sanitizedIntent = createServiceStateIntent(state, subId, phoneId, true);
@@ -3588,13 +3596,13 @@
new String[]{Manifest.permission.READ_PHONE_STATE},
new String[]{/* no excluded permissions */},
locationBypassPackages,
- options);
+ createServiceStateBroadcastOptions(subId, phoneId, "I:R,lbp"));
mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
sanitizedIntent,
new String[]{Manifest.permission.READ_PRIVILEGED_PHONE_STATE},
new String[]{Manifest.permission.READ_PHONE_STATE},
locationBypassPackages,
- options);
+ createServiceStateBroadcastOptions(subId, phoneId, "I:RP,E:R,lbp"));
}
}
@@ -3616,12 +3624,14 @@
return intent;
}
- private BroadcastOptions createServiceStateBroadcastOptions(int subId, int phoneId) {
+ private BroadcastOptions createServiceStateBroadcastOptions(int subId, int phoneId,
+ String tag) {
return new BroadcastOptions()
.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
// Use a combination of subId and phoneId as the key so that older broadcasts
// with same subId and phoneId will get discarded.
- .setDeliveryGroupMatchingKey(Intent.ACTION_SERVICE_STATE, subId + "-" + phoneId)
+ .setDeliveryGroupMatchingKey(Intent.ACTION_SERVICE_STATE,
+ subId + "-" + phoneId + "-" + tag)
.setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE);
}
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 7c32627..55e805a 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -28,6 +28,7 @@
import static android.app.UiModeManager.PROJECTION_TYPE_AUTOMOTIVE;
import static android.app.UiModeManager.PROJECTION_TYPE_NONE;
import static android.os.UserHandle.USER_SYSTEM;
+import static android.os.UserHandle.getCallingUserId;
import static android.provider.Settings.Secure.CONTRAST_LEVEL;
import static android.util.TimeUtils.isTimeBetween;
@@ -199,8 +200,8 @@
private PowerManagerInternal mLocalPowerManager;
@GuardedBy("mLock")
- private final RemoteCallbackList<IUiModeManagerCallback> mUiModeManagerCallbacks =
- new RemoteCallbackList<IUiModeManagerCallback>();
+ private final SparseArray<RemoteCallbackList<IUiModeManagerCallback>> mUiModeManagerCallbacks =
+ new SparseArray<>();
@GuardedBy("mLock")
@Nullable
@@ -371,8 +372,9 @@
synchronized (mLock) {
if (updateContrastLocked()) {
float contrast = getContrastLocked();
- mUiModeManagerCallbacks.broadcast(ignoreRemoteException(callback ->
- callback.notifyContrastChanged(contrast)));
+ mUiModeManagerCallbacks.get(mCurrentUser, new RemoteCallbackList<>())
+ .broadcast(ignoreRemoteException(
+ callback -> callback.notifyContrastChanged(contrast)));
}
}
}
@@ -664,8 +666,12 @@
private final IUiModeManager.Stub mService = new IUiModeManager.Stub() {
@Override
public void addCallback(IUiModeManagerCallback callback) {
+ int userId = getCallingUserId();
synchronized (mLock) {
- mUiModeManagerCallbacks.register(callback);
+ if (!mUiModeManagerCallbacks.contains(userId)) {
+ mUiModeManagerCallbacks.put(userId, new RemoteCallbackList<>());
+ }
+ mUiModeManagerCallbacks.get(userId).register(callback);
}
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index df3c95b..678d582 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3866,7 +3866,7 @@
if (UserHandle.isCore(callingUid)) {
return;
}
- final int callingUserId = UserHandle.getCallingUserId();
+ final int callingUserId = UserHandle.getUserId(callingUid);
if (callingUserId == userId
|| !mAm.mUserController.isSameProfileGroup(callingUserId, userId)) {
return;
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index f29a2e1..c687184a 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -1199,6 +1199,9 @@
.sendToTarget();
}
+ mCachedAppsWatermarkData.updateCachedAppsHighWatermarkIfNecessaryLocked(
+ numCached + numEmpty, now);
+
if (mService.mConstants.USE_MODERN_TRIM) {
// Modern trim is not sent based on lowmem state
// Dispatch UI_HIDDEN to processes that need it
@@ -1316,8 +1319,6 @@
profile.setTrimMemoryLevel(0);
});
}
- mCachedAppsWatermarkData.updateCachedAppsHighWatermarkIfNecessaryLocked(
- numCached + numEmpty, now);
return allChanged;
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index d140403..6360e2a 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -167,7 +167,7 @@
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE)
.replaceWith("?");
- private static final int MAX_LOW_POWER_STATS_SIZE = 16384;
+ private static final int MAX_LOW_POWER_STATS_SIZE = 32768;
private static final int POWER_STATS_QUERY_TIMEOUT_MILLIS = 2000;
private static final String EMPTY = "Empty";
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index 0767218..5c68e67 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -242,8 +242,7 @@
*/
@Nullable
public BroadcastRecord enqueueOrReplaceBroadcast(@NonNull BroadcastRecord record,
- int recordIndex, boolean wouldBeSkipped,
- @NonNull BroadcastConsumer deferredStatesApplyConsumer) {
+ int recordIndex, @NonNull BroadcastConsumer deferredStatesApplyConsumer) {
// When updateDeferredStates() has already applied a deferred state to
// all pending items, apply to this new broadcast too
if (mLastDeferredStates && record.deferUntilActive
@@ -252,8 +251,7 @@
}
if (record.isReplacePending()) {
- final BroadcastRecord replacedBroadcastRecord = replaceBroadcast(record, recordIndex,
- wouldBeSkipped);
+ final BroadcastRecord replacedBroadcastRecord = replaceBroadcast(record, recordIndex);
if (replacedBroadcastRecord != null) {
return replacedBroadcastRecord;
}
@@ -264,14 +262,13 @@
SomeArgs newBroadcastArgs = SomeArgs.obtain();
newBroadcastArgs.arg1 = record;
newBroadcastArgs.argi1 = recordIndex;
- newBroadcastArgs.argi2 = (wouldBeSkipped ? 1 : 0);
// Cross-broadcast prioritization policy: some broadcasts might warrant being
// issued ahead of others that are already pending, for example if this new
// broadcast is in a different delivery class or is tied to a direct user interaction
// with implicit responsiveness expectations.
getQueueForBroadcast(record).addLast(newBroadcastArgs);
- onBroadcastEnqueued(record, recordIndex, wouldBeSkipped);
+ onBroadcastEnqueued(record, recordIndex);
return null;
}
@@ -285,10 +282,9 @@
* wasn't any broadcast that was replaced.
*/
@Nullable
- private BroadcastRecord replaceBroadcast(@NonNull BroadcastRecord record, int recordIndex,
- boolean wouldBeSkipped) {
+ private BroadcastRecord replaceBroadcast(@NonNull BroadcastRecord record, int recordIndex) {
final ArrayDeque<SomeArgs> queue = getQueueForBroadcast(record);
- return replaceBroadcastInQueue(queue, record, recordIndex, wouldBeSkipped);
+ return replaceBroadcastInQueue(queue, record, recordIndex);
}
/**
@@ -302,15 +298,13 @@
*/
@Nullable
private BroadcastRecord replaceBroadcastInQueue(@NonNull ArrayDeque<SomeArgs> queue,
- @NonNull BroadcastRecord record, int recordIndex,
- boolean wouldBeSkipped) {
+ @NonNull BroadcastRecord record, int recordIndex) {
final Iterator<SomeArgs> it = queue.descendingIterator();
final Object receiver = record.receivers.get(recordIndex);
while (it.hasNext()) {
final SomeArgs args = it.next();
final BroadcastRecord testRecord = (BroadcastRecord) args.arg1;
final int testRecordIndex = args.argi1;
- final boolean testWouldBeSkipped = (args.argi2 == 1);
final Object testReceiver = testRecord.receivers.get(testRecordIndex);
if ((record.callingUid == testRecord.callingUid)
&& (record.userId == testRecord.userId)
@@ -320,10 +314,9 @@
// Exact match found; perform in-place swap
args.arg1 = record;
args.argi1 = recordIndex;
- args.argi2 = (wouldBeSkipped ? 1 : 0);
record.copyEnqueueTimeFrom(testRecord);
- onBroadcastDequeued(testRecord, testRecordIndex, testWouldBeSkipped);
- onBroadcastEnqueued(record, recordIndex, wouldBeSkipped);
+ onBroadcastDequeued(testRecord, testRecordIndex);
+ onBroadcastEnqueued(record, recordIndex);
return testRecord;
}
}
@@ -383,13 +376,12 @@
final SomeArgs args = it.next();
final BroadcastRecord record = (BroadcastRecord) args.arg1;
final int recordIndex = args.argi1;
- final boolean recordWouldBeSkipped = (args.argi2 == 1);
if (predicate.test(record, recordIndex)) {
consumer.accept(record, recordIndex);
if (andRemove) {
args.recycle();
it.remove();
- onBroadcastDequeued(record, recordIndex, recordWouldBeSkipped);
+ onBroadcastDequeued(record, recordIndex);
} else {
// Even if we're leaving broadcast in queue, it may have
// been mutated in such a way to change our runnable time
@@ -539,12 +531,11 @@
final SomeArgs next = removeNextBroadcast();
mActive = (BroadcastRecord) next.arg1;
mActiveIndex = next.argi1;
- final boolean wouldBeSkipped = (next.argi2 == 1);
mActiveCountSinceIdle++;
mActiveViaColdStart = false;
mActiveWasStopped = false;
next.recycle();
- onBroadcastDequeued(mActive, mActiveIndex, wouldBeSkipped);
+ onBroadcastDequeued(mActive, mActiveIndex);
}
/**
@@ -561,8 +552,7 @@
/**
* Update summary statistics when the given record has been enqueued.
*/
- private void onBroadcastEnqueued(@NonNull BroadcastRecord record, int recordIndex,
- boolean wouldBeSkipped) {
+ private void onBroadcastEnqueued(@NonNull BroadcastRecord record, int recordIndex) {
mCountEnqueued++;
if (record.deferUntilActive) {
mCountDeferred++;
@@ -594,8 +584,7 @@
if (record.callerInstrumented) {
mCountInstrumented++;
}
- if (!wouldBeSkipped
- && (record.receivers.get(recordIndex) instanceof ResolveInfo)) {
+ if (record.receivers.get(recordIndex) instanceof ResolveInfo) {
mCountManifest++;
}
invalidateRunnableAt();
@@ -604,8 +593,7 @@
/**
* Update summary statistics when the given record has been dequeued.
*/
- private void onBroadcastDequeued(@NonNull BroadcastRecord record, int recordIndex,
- boolean wouldBeSkipped) {
+ private void onBroadcastDequeued(@NonNull BroadcastRecord record, int recordIndex) {
mCountEnqueued--;
if (record.deferUntilActive) {
mCountDeferred--;
@@ -637,8 +625,7 @@
if (record.callerInstrumented) {
mCountInstrumented--;
}
- if (!wouldBeSkipped
- && (record.receivers.get(recordIndex) instanceof ResolveInfo)) {
+ if (record.receivers.get(recordIndex) instanceof ResolveInfo) {
mCountManifest--;
}
invalidateRunnableAt();
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 8735f8a..96e1523 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -606,24 +606,18 @@
final BroadcastProcessQueue queue = getOrCreateProcessQueue(
getReceiverProcessName(receiver), getReceiverUid(receiver));
- boolean wouldBeSkipped = false;
- if (receiver instanceof ResolveInfo) {
- // If the app is running but would not have been started if the process weren't
- // running, we're going to deliver the broadcast but mark that it's not a manifest
- // broadcast that would have started the app. This allows BroadcastProcessQueue to
- // defer the broadcast as though it were a normal runtime receiver.
- wouldBeSkipped = (mSkipPolicy.shouldSkipMessage(r, receiver) != null);
- if (wouldBeSkipped && queue.app == null && !queue.getActiveViaColdStart()) {
- // Skip receiver if there's no running app, the app is not being started, and
- // the app wouldn't be launched for this broadcast
- setDeliveryState(null, null, r, i, receiver, BroadcastRecord.DELIVERY_SKIPPED,
- "skipped by policy to avoid cold start");
- continue;
- }
+ // If this receiver is going to be skipped, skip it now itself and don't even enqueue
+ // it.
+ final boolean wouldBeSkipped = (mSkipPolicy.shouldSkipMessage(r, receiver) != null);
+ if (wouldBeSkipped) {
+ setDeliveryState(null, null, r, i, receiver, BroadcastRecord.DELIVERY_SKIPPED,
+ "skipped by policy at enqueue");
+ continue;
}
+
enqueuedBroadcast = true;
final BroadcastRecord replacedBroadcast = queue.enqueueOrReplaceBroadcast(
- r, i, wouldBeSkipped, mBroadcastConsumerDeferApply);
+ r, i, mBroadcastConsumerDeferApply);
if (replacedBroadcast != null) {
replacedBroadcasts.add(replacedBroadcast);
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 13c42eb..ada92f5 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -957,6 +957,10 @@
}
}
+ /*package*/ void postSetA2dpSuspended(boolean enable, String eventSource) {
+ sendILMsgNoDelay(MSG_IL_SET_A2DP_SUSPENDED, SENDMSG_QUEUE, (enable ? 1 : 0), eventSource);
+ }
+
/*package*/ void setA2dpSuspended(boolean enable, boolean internal, String eventSource) {
if (AudioService.DEBUG_COMM_RTE) {
Log.v(TAG, "setA2dpSuspended source: " + eventSource + ", enable: "
@@ -985,6 +989,11 @@
}
}
+ /*package*/ void postSetLeAudioSuspended(boolean enable, String eventSource) {
+ sendILMsgNoDelay(
+ MSG_IL_SET_LEAUDIO_SUSPENDED, SENDMSG_QUEUE, (enable ? 1 : 0), eventSource);
+ }
+
/*package*/ void setLeAudioSuspended(boolean enable, boolean internal, String eventSource) {
if (AudioService.DEBUG_COMM_RTE) {
Log.v(TAG, "setLeAudioSuspended source: " + eventSource + ", enable: "
@@ -1795,6 +1804,12 @@
final int capturePreset = msg.arg1;
mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset);
} break;
+ case MSG_IL_SET_A2DP_SUSPENDED: {
+ setA2dpSuspended((msg.arg1 == 1), false /*internal*/, (String) msg.obj);
+ } break;
+ case MSG_IL_SET_LEAUDIO_SUSPENDED: {
+ setLeAudioSuspended((msg.arg1 == 1), false /*internal*/, (String) msg.obj);
+ } break;
default:
Log.wtf(TAG, "Invalid message " + msg.what);
}
@@ -1869,6 +1884,8 @@
private static final int MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY = 47;
private static final int MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY = 48;
private static final int MSG_IL_BTLEAUDIO_TIMEOUT = 49;
+ private static final int MSG_IL_SET_A2DP_SUSPENDED = 50;
+ private static final int MSG_IL_SET_LEAUDIO_SUSPENDED = 51;
private static boolean isMessageHandledUnderWakelock(int msgId) {
switch(msgId) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 3487fc2..2039325 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -6412,7 +6412,7 @@
final String eventSource = new StringBuilder("setA2dpSuspended(").append(enable)
.append(") from u/pid:").append(Binder.getCallingUid()).append("/")
.append(Binder.getCallingPid()).toString();
- mDeviceBroker.setA2dpSuspended(enable, false /*internal*/, eventSource);
+ mDeviceBroker.postSetA2dpSuspended(enable, eventSource);
}
/** @see AudioManager#setA2dpSuspended(boolean) */
@@ -6422,7 +6422,7 @@
final String eventSource = new StringBuilder("setLeAudioSuspended(").append(enable)
.append(") from u/pid:").append(Binder.getCallingUid()).append("/")
.append(Binder.getCallingPid()).toString();
- mDeviceBroker.setLeAudioSuspended(enable, false /*internal*/, eventSource);
+ mDeviceBroker.postSetLeAudioSuspended(enable, eventSource);
}
/** @see AudioManager#isBluetoothScoOn()
diff --git a/services/core/java/com/android/server/audio/SoundDoseHelper.java b/services/core/java/com/android/server/audio/SoundDoseHelper.java
index 7cdea8d..9429b4c 100644
--- a/services/core/java/com/android/server/audio/SoundDoseHelper.java
+++ b/services/core/java/com/android/server/audio/SoundDoseHelper.java
@@ -57,6 +57,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@@ -168,7 +169,7 @@
@NonNull private final AudioHandler mAudioHandler;
@NonNull private final ISafeHearingVolumeController mVolumeController;
- private final boolean mEnableCsd;
+ private final AtomicBoolean mEnableCsd = new AtomicBoolean(false);
private final Object mCsdStateLock = new Object();
@@ -195,7 +196,7 @@
private final ISoundDoseCallback.Stub mSoundDoseCallback = new ISoundDoseCallback.Stub() {
public void onMomentaryExposure(float currentMel, int deviceId) {
- if (!mEnableCsd) {
+ if (!mEnableCsd.get()) {
Log.w(TAG, "onMomentaryExposure: csd not supported, ignoring callback");
return;
}
@@ -222,7 +223,7 @@
}
public void onNewCsdValue(float currentCsd, SoundDoseRecord[] records) {
- if (!mEnableCsd) {
+ if (!mEnableCsd.get()) {
Log.w(TAG, "onNewCsdValue: csd not supported, ignoring value");
return;
}
@@ -272,8 +273,6 @@
mContext = context;
- mEnableCsd = mContext.getResources().getBoolean(R.bool.config_audio_csd_enabled_default);
- initCsd();
initSafeVolumes();
mSafeMediaVolumeState = mSettings.getGlobalInt(audioService.getContentResolver(),
@@ -285,6 +284,10 @@
mSafeMediaVolumeIndex = mContext.getResources().getInteger(
R.integer.config_safe_media_volume_index) * 10;
+ mSoundDose.set(AudioSystem.getSoundDoseInterface(mSoundDoseCallback));
+ // Csd will be initially disabled until the mcc is read in onConfigureSafeMedia()
+ initCsd();
+
mAlarmManager = (AlarmManager) mContext.getSystemService(
Context.ALARM_SERVICE);
}
@@ -310,7 +313,7 @@
}
float getOutputRs2UpperBound() {
- if (!mEnableCsd) {
+ if (!mEnableCsd.get()) {
return 0.f;
}
@@ -329,7 +332,7 @@
}
void setOutputRs2UpperBound(float rs2Value) {
- if (!mEnableCsd) {
+ if (!mEnableCsd.get()) {
return;
}
@@ -347,7 +350,7 @@
}
float getCsd() {
- if (!mEnableCsd) {
+ if (!mEnableCsd.get()) {
return -1.f;
}
@@ -366,7 +369,7 @@
}
void setCsd(float csd) {
- if (!mEnableCsd) {
+ if (!mEnableCsd.get()) {
return;
}
@@ -400,7 +403,7 @@
}
void resetCsdTimeouts() {
- if (!mEnableCsd) {
+ if (!mEnableCsd.get()) {
return;
}
@@ -416,7 +419,7 @@
}
void forceUseFrameworkMel(boolean useFrameworkMel) {
- if (!mEnableCsd) {
+ if (!mEnableCsd.get()) {
return;
}
@@ -434,7 +437,7 @@
}
void forceComputeCsdOnAllDevices(boolean computeCsdOnAllDevices) {
- if (!mEnableCsd) {
+ if (!mEnableCsd.get()) {
return;
}
@@ -454,7 +457,7 @@
}
boolean isCsdEnabled() {
- if (!mEnableCsd) {
+ if (!mEnableCsd.get()) {
return false;
}
@@ -697,8 +700,8 @@
}
/*package*/ void dump(PrintWriter pw) {
- pw.print(" mEnableCsd="); pw.println(mEnableCsd);
- if (mEnableCsd) {
+ pw.print(" mEnableCsd="); pw.println(mEnableCsd.get());
+ if (mEnableCsd.get()) {
synchronized (mCsdStateLock) {
pw.print(" mCurrentCsd="); pw.println(mCurrentCsd);
}
@@ -719,9 +722,11 @@
pw.println();
}
- /*package*/void reset() {
+ /*package*/void reset() {
Log.d(TAG, "Reset the sound dose helper");
- mSoundDose.set(AudioSystem.getSoundDoseInterface(mSoundDoseCallback));
+
+ mSoundDose.compareAndExchange(/*expectedValue=*/null,
+ AudioSystem.getSoundDoseInterface(mSoundDoseCallback));
synchronized (mCsdStateLock) {
try {
@@ -743,7 +748,7 @@
private void updateDoseAttenuation(int newIndex, int device, int streamType,
boolean isAbsoluteVolume) {
- if (!mEnableCsd) {
+ if (!mEnableCsd.get()) {
return;
}
@@ -775,17 +780,19 @@
}
private void initCsd() {
- if (!mEnableCsd) {
- final ISoundDose soundDose = AudioSystem.getSoundDoseInterface(mSoundDoseCallback);
- if (soundDose == null) {
- Log.w(TAG, "ISoundDose instance is null.");
- return;
- }
- try {
- soundDose.disableCsd();
- } catch (RemoteException e) {
- Log.e(TAG, "Cannot disable CSD", e);
- }
+ ISoundDose soundDose = mSoundDose.get();
+ if (soundDose == null) {
+ Log.w(TAG, "ISoundDose instance is null.");
+ return;
+ }
+
+ try {
+ soundDose.setCsdEnabled(mEnableCsd.get());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Cannot disable CSD", e);
+ }
+
+ if (!mEnableCsd.get()) {
return;
}
@@ -829,7 +836,6 @@
SystemProperties.getBoolean("audio.safemedia.force", false)
|| mContext.getResources().getBoolean(
com.android.internal.R.bool.config_safe_media_volume_enabled);
-
boolean safeMediaVolumeBypass =
SystemProperties.getBoolean("audio.safemedia.bypass", false);
@@ -860,6 +866,13 @@
mAudioHandler.obtainMessage(MSG_PERSIST_SAFE_VOLUME_STATE,
persistedState, /*arg2=*/0,
/*obj=*/null), /*delay=*/0);
+
+ boolean newEnableCsd = SystemProperties.getBoolean("audio.safemedia.force", false)
+ || mContext.getResources().getBoolean(
+ R.bool.config_safe_sound_dosage_enabled);
+ if (mEnableCsd.compareAndSet(!newEnableCsd, newEnableCsd)) {
+ initCsd();
+ }
}
}
}
@@ -913,7 +926,7 @@
// legacy implementation uses mSafeMediaVolumeIndex for wired HS/HP
// instead of computing it from the volume curves
if ((deviceType == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
- || deviceType == AudioSystem.DEVICE_OUT_WIRED_HEADSET) && !mEnableCsd) {
+ || deviceType == AudioSystem.DEVICE_OUT_WIRED_HEADSET) && !mEnableCsd.get()) {
return mSafeMediaVolumeIndex;
}
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index 5127d26..bf5e8ee 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -704,7 +704,8 @@
}
BiometricFrameworkStatsLogger.getInstance().authenticate(
- mBiometricContext.updateContext(new OperationContextExt(), isCrypto()),
+ mBiometricContext.updateContext(new OperationContextExt(true /* isBP */),
+ isCrypto()),
statsModality(),
BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
@@ -734,7 +735,8 @@
}
// Auth canceled
BiometricFrameworkStatsLogger.getInstance().error(
- mBiometricContext.updateContext(new OperationContextExt(), isCrypto()),
+ mBiometricContext.updateContext(new OperationContextExt(true /* isBP */),
+ isCrypto()),
statsModality(),
BiometricsProtoEnums.ACTION_AUTHENTICATE,
BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
diff --git a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
index d1de80b..4d821e9 100644
--- a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
+++ b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java
@@ -46,15 +46,17 @@
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
@Surface.Rotation private int mOrientation = Surface.ROTATION_0;
private int mFoldState = IBiometricContextListener.FoldState.UNKNOWN;
+ private final boolean mIsBP;
- /** Create a new empty context. */
- public OperationContextExt() {
- this(new OperationContext());
+ /** Create a context. */
+ public OperationContextExt(boolean isBP) {
+ this(new OperationContext(), isBP);
}
/** Create a wrapped context. */
- public OperationContextExt(@NonNull OperationContext context) {
+ public OperationContextExt(@NonNull OperationContext context, boolean isBP) {
mAidlContext = context;
+ mIsBP = isBP;
}
/**
@@ -268,18 +270,20 @@
}
private void setFirstSessionId(@NonNull BiometricContext biometricContext) {
- mSessionInfo = biometricContext.getKeyguardEntrySessionInfo();
- if (mSessionInfo != null) {
- mAidlContext.id = mSessionInfo.getId();
- mAidlContext.reason = OperationReason.KEYGUARD;
- return;
- }
-
- mSessionInfo = biometricContext.getBiometricPromptSessionInfo();
- if (mSessionInfo != null) {
- mAidlContext.id = mSessionInfo.getId();
- mAidlContext.reason = OperationReason.BIOMETRIC_PROMPT;
- return;
+ if (mIsBP) {
+ mSessionInfo = biometricContext.getBiometricPromptSessionInfo();
+ if (mSessionInfo != null) {
+ mAidlContext.id = mSessionInfo.getId();
+ mAidlContext.reason = OperationReason.BIOMETRIC_PROMPT;
+ return;
+ }
+ } else {
+ mSessionInfo = biometricContext.getKeyguardEntrySessionInfo();
+ if (mSessionInfo != null) {
+ mAidlContext.id = mSessionInfo.getId();
+ mAidlContext.reason = OperationReason.KEYGUARD;
+ return;
+ }
}
// no session
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 7b9fc36..05ca6e4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -133,10 +133,6 @@
binderDiedInternal(clearListener);
}
- public boolean isBiometricPrompt() {
- return getCookie() != 0;
- }
-
public long getOperationId() {
return mOperationId;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java
index d0a4807..03658ce 100644
--- a/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java
@@ -37,7 +37,7 @@
protected final Supplier<T> mLazyDaemon;
@NonNull
- private final OperationContextExt mOperationContext = new OperationContextExt();
+ private final OperationContextExt mOperationContext;
/**
* @param context system_server context
@@ -58,6 +58,7 @@
super(context, token, listener, userId, owner, cookie, sensorId,
biometricLogger, biometricContext);
mLazyDaemon = lazyDaemon;
+ mOperationContext = new OperationContextExt(isBiometricPrompt());
}
@Nullable
@@ -85,6 +86,10 @@
unsubscribeBiometricContext();
}
+ public boolean isBiometricPrompt() {
+ return getCookie() != 0;
+ }
+
protected OperationContextExt getOperationContext() {
return getBiometricContext().updateContext(mOperationContext, isCryptoOperation());
}
diff --git a/services/core/java/com/android/server/broadcastradio/RadioServiceUserController.java b/services/core/java/com/android/server/broadcastradio/RadioServiceUserController.java
index 38b3233..4b847a2 100644
--- a/services/core/java/com/android/server/broadcastradio/RadioServiceUserController.java
+++ b/services/core/java/com/android/server/broadcastradio/RadioServiceUserController.java
@@ -39,18 +39,24 @@
*/
public static boolean isCurrentOrSystemUser() {
int callingUser = Binder.getCallingUserHandle().getIdentifier();
+ return callingUser == getCurrentUser() || callingUser == UserHandle.USER_SYSTEM;
+ }
+
+ /**
+ * Get current foreground user for Broadcast Radio Service
+ *
+ * @return foreground user id.
+ */
+ public static int getCurrentUser() {
final long identity = Binder.clearCallingIdentity();
+ int userId = UserHandle.USER_NULL;
try {
- int currentUser = ActivityManager.getCurrentUser();
- if (callingUser != currentUser && callingUser != UserHandle.USER_SYSTEM) {
- return false;
- }
- return true;
+ userId = ActivityManager.getCurrentUser();
} catch (RuntimeException e) {
// Activity manager not running, nothing we can do assume user 0.
} finally {
Binder.restoreCallingIdentity(identity);
}
- return false;
+ return userId;
}
}
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
index aab815c..adea13f 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
@@ -102,6 +102,8 @@
return new UnsupportedOperationException(action + ": NOT_SUPPORTED");
case Result.TIMEOUT:
return new ParcelableException(new RuntimeException(action + ": TIMEOUT"));
+ case Result.CANCELED:
+ return new IllegalStateException(action + ": CANCELED");
default:
return new ParcelableException(new RuntimeException(
action + ": unknown error (" + result + ")"));
@@ -123,6 +125,8 @@
return RadioTuner.TUNER_RESULT_NOT_SUPPORTED;
case Result.TIMEOUT:
return RadioTuner.TUNER_RESULT_TIMEOUT;
+ case Result.CANCELED:
+ return RadioTuner.TUNER_RESULT_CANCELED;
case Result.UNKNOWN_ERROR:
default:
return RadioTuner.TUNER_RESULT_UNKNOWN_ERROR;
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java
index 132fb8e..7c87c6c 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java
@@ -36,11 +36,13 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.broadcastradio.RadioServiceUserController;
import com.android.server.utils.Slogf;
import java.util.ArrayList;
@@ -419,8 +421,13 @@
@GuardedBy("mLock")
private void fanoutAidlCallbackLocked(AidlCallbackRunnable runnable) {
+ int currentUserId = RadioServiceUserController.getCurrentUser();
List<TunerSession> deadSessions = null;
for (int i = 0; i < mAidlTunerSessions.size(); i++) {
+ if (mAidlTunerSessions.valueAt(i).mUserId != currentUserId
+ && mAidlTunerSessions.valueAt(i).mUserId != UserHandle.USER_SYSTEM) {
+ continue;
+ }
try {
runnable.run(mAidlTunerSessions.valueAt(i).mCallback,
mAidlTunerSessions.valueAt(i).getUid());
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java
index 0a3823f..beff7bd 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java
@@ -46,6 +46,7 @@
private final RadioLogger mLogger;
private final RadioModule mModule;
+ final int mUserId;
final android.hardware.radio.ITunerCallback mCallback;
private final int mUid;
private final IBroadcastRadio mService;
@@ -65,6 +66,7 @@
android.hardware.radio.ITunerCallback callback) {
mModule = Objects.requireNonNull(radioModule, "radioModule cannot be null");
mService = Objects.requireNonNull(service, "service cannot be null");
+ mUserId = Binder.getCallingUserHandle().getIdentifier();
mCallback = Objects.requireNonNull(callback, "callback cannot be null");
mUid = Binder.getCallingUid();
mLogger = new RadioLogger(TAG, TUNER_EVENT_LOGGER_QUEUE_SIZE);
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
index 59a8154..7b5cb898 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
@@ -38,12 +38,14 @@
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.IndentingPrintWriter;
import android.util.MutableInt;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.broadcastradio.RadioServiceUserController;
import java.util.ArrayList;
import java.util.HashSet;
@@ -374,8 +376,13 @@
@GuardedBy("mLock")
private void fanoutAidlCallbackLocked(AidlCallbackRunnable runnable) {
+ int currentUserId = RadioServiceUserController.getCurrentUser();
List<TunerSession> deadSessions = null;
for (TunerSession tunerSession : mAidlTunerSessions) {
+ if (tunerSession.mUserId != currentUserId && tunerSession.mUserId
+ != UserHandle.USER_SYSTEM) {
+ continue;
+ }
try {
runnable.run(tunerSession.mCallback);
} catch (DeadObjectException ex) {
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index 204b964..1efc4a5 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -26,6 +26,7 @@
import android.hardware.radio.ProgramList;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
+import android.os.Binder;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
@@ -52,6 +53,7 @@
private final RadioModule mModule;
private final ITunerSession mHwSession;
+ final int mUserId;
final android.hardware.radio.ITunerCallback mCallback;
@GuardedBy("mLock")
@@ -68,6 +70,7 @@
@NonNull android.hardware.radio.ITunerCallback callback) {
mModule = Objects.requireNonNull(module);
mHwSession = Objects.requireNonNull(hwSession);
+ mUserId = Binder.getCallingUserHandle().getIdentifier();
mCallback = Objects.requireNonNull(callback);
mEventLogger = new RadioEventLogger(TAG, TUNER_EVENT_LOGGER_QUEUE_SIZE);
}
diff --git a/services/core/java/com/android/server/cpu/CpuMonitorService.java b/services/core/java/com/android/server/cpu/CpuMonitorService.java
index df8cfad..7ea2c1b 100644
--- a/services/core/java/com/android/server/cpu/CpuMonitorService.java
+++ b/services/core/java/com/android/server/cpu/CpuMonitorService.java
@@ -653,8 +653,17 @@
}
public int getAverageAvailableCpuFreqPercent() {
- return (int) ((totalNormalizedAvailableCpuFreqKHz * 100.0)
+ int percent = (int) ((totalNormalizedAvailableCpuFreqKHz * 100.0)
/ totalOnlineMaxCpuFreqKHz);
+ if (percent < 0) {
+ // TODO(b/279478586): This case should never happen. But this case happens
+ // rarely on certain hardware, which indicates a deeper issue. Once this
+ // issue is reproduced, use this log to debug the issue and fix it.
+ Slogf.wtf(TAG, "Computed negative CPU availability percent(%d) for %s ",
+ percent, toString());
+ return 0;
+ }
+ return percent;
}
@Override
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 378363c..774087c 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -366,7 +366,12 @@
return getAutomaticScreenBrightness(null);
}
- float getAutomaticScreenBrightness(BrightnessEvent brightnessEvent) {
+ /**
+ * @return The current brightness recommendation calculated from the current conditions.
+ * @param brightnessEvent Event object to populate with details about why the specific
+ * brightness was chosen.
+ */
+ public float getAutomaticScreenBrightness(BrightnessEvent brightnessEvent) {
if (brightnessEvent != null) {
brightnessEvent.setLux(
mAmbientLuxValid ? mAmbientLux : PowerManager.BRIGHTNESS_INVALID_FLOAT);
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index a4bd6a6..46cd496 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -191,7 +191,7 @@
}
if (!(createEglContext(isProtected) && createEglSurface(isProtected, isWideColor)
- && setScreenshotTextureAndSetViewport(hardwareBuffer))) {
+ && setScreenshotTextureAndSetViewport(hardwareBuffer, displayInfo.rotation))) {
dismiss();
return false;
}
@@ -500,7 +500,8 @@
}
private boolean setScreenshotTextureAndSetViewport(
- ScreenCapture.ScreenshotHardwareBuffer screenshotBuffer) {
+ ScreenCapture.ScreenshotHardwareBuffer screenshotBuffer,
+ @Surface.Rotation int rotation) {
if (!attachEglContext()) {
return false;
}
@@ -525,14 +526,22 @@
s.release();
st.release();
}
+ // if screen is rotated, map texture starting different corner
+ int indexDelta = (rotation == Surface.ROTATION_90) ? 2
+ : (rotation == Surface.ROTATION_180) ? 4
+ : (rotation == Surface.ROTATION_270) ? 6 : 0;
// Set up texture coordinates for a quad.
// We might need to change this if the texture ends up being
// a different size from the display for some reason.
- mTexCoordBuffer.put(0, 0f); mTexCoordBuffer.put(1, 0f);
- mTexCoordBuffer.put(2, 0f); mTexCoordBuffer.put(3, 1f);
- mTexCoordBuffer.put(4, 1f); mTexCoordBuffer.put(5, 1f);
- mTexCoordBuffer.put(6, 1f); mTexCoordBuffer.put(7, 0f);
+ mTexCoordBuffer.put(indexDelta, 0f);
+ mTexCoordBuffer.put(indexDelta + 1, 0f);
+ mTexCoordBuffer.put((indexDelta + 2) % 8, 0f);
+ mTexCoordBuffer.put((indexDelta + 3) % 8, 1f);
+ mTexCoordBuffer.put((indexDelta + 4) % 8, 1f);
+ mTexCoordBuffer.put((indexDelta + 5) % 8, 1f);
+ mTexCoordBuffer.put((indexDelta + 6) % 8, 1f);
+ mTexCoordBuffer.put((indexDelta + 7) % 8, 0f);
// Set up our viewport.
GLES20.glViewport(0, 0, mDisplayWidth, mDisplayHeight);
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 26b6cb0..5771a04 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -2548,7 +2548,6 @@
final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked();
captureArgs = new ScreenCapture.DisplayCaptureArgs.Builder(token)
.setSize(displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight())
- .setUseIdentityTransform(true)
.setCaptureSecureLayers(true)
.setAllowProtected(true)
.build();
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 33f0552..0861cb5 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -83,6 +83,7 @@
import com.android.server.policy.WindowManagerPolicy;
import java.io.PrintWriter;
+import java.util.Objects;
/**
* Controls the power state of the display.
@@ -167,6 +168,51 @@
private static final int RINGBUFFER_MAX = 100;
+ private static final float[] BRIGHTNESS_RANGE_BOUNDARIES = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80,
+ 90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200,
+ 1400, 1600, 1800, 2000, 2250, 2500, 2750, 3000};
+ private static final int[] BRIGHTNESS_RANGE_INDEX = {
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_UNKNOWN,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_0_1,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1_2,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2_3,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_3_4,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_4_5,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_5_6,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_6_7,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_7_8,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_8_9,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_9_10,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_10_20,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_20_30,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_30_40,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_40_50,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_50_60,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_60_70,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_70_80,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_80_90,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_90_100,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_100_200,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_200_300,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_300_400,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_400_500,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_500_600,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_600_700,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_700_800,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_800_900,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_900_1000,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1000_1200,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1200_1400,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1400_1600,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1600_1800,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1800_2000,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2000_2250,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2250_2500,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2500_2750,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2750_3000,
+ };
+
private final String mTag;
private final Object mLock = new Object();
@@ -560,7 +606,7 @@
mLastBrightnessEvent = new BrightnessEvent(mDisplayId);
mTempBrightnessEvent = new BrightnessEvent(mDisplayId);
mThermalBrightnessThrottlingDataId =
- logicalDisplay.getThermalBrightnessThrottlingDataIdLocked();
+ logicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId;
if (mDisplayId == Display.DEFAULT_DISPLAY) {
mBatteryStats = BatteryStatsService.getService();
@@ -910,7 +956,7 @@
&& mLogicalDisplay.getPrimaryDisplayDeviceLocked()
.getDisplayDeviceInfoLocked().type == Display.TYPE_INTERNAL;
final String thermalBrightnessThrottlingDataId =
- mLogicalDisplay.getThermalBrightnessThrottlingDataIdLocked();
+ mLogicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId;
mHandler.postAtTime(() -> {
boolean changed = false;
if (mDisplayDevice != device) {
@@ -927,8 +973,8 @@
// last command that was sent to change it's state. Let's assume it is unknown so
// that we trigger a change immediately.
mPowerState.resetScreenState();
- } else if (
- !mThermalBrightnessThrottlingDataId.equals(thermalBrightnessThrottlingDataId)) {
+ } else if (!Objects.equals(mThermalBrightnessThrottlingDataId,
+ thermalBrightnessThrottlingDataId)) {
changed = true;
mThermalBrightnessThrottlingDataId = thermalBrightnessThrottlingDataId;
mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig(
@@ -1937,8 +1983,9 @@
? BrightnessEvent.FLAG_USER_SET : 0));
Slog.i(mTag, newEvent.toString(/* includeTime= */ false));
- if (userSetBrightnessChanged) {
- logManualBrightnessEvent(newEvent);
+ if (userSetBrightnessChanged
+ || newEvent.getReason().getReason() != BrightnessReason.REASON_TEMPORARY) {
+ logBrightnessEvent(newEvent, unthrottledBrightnessState);
}
if (mBrightnessEventRingBuffer != null) {
mBrightnessEventRingBuffer.append(newEvent);
@@ -2143,7 +2190,8 @@
() -> {
sendUpdatePowerState();
postBrightnessChangeRunnable();
- }, mUniqueDisplayId, mLogicalDisplay.getThermalBrightnessThrottlingDataIdLocked(),
+ }, mUniqueDisplayId,
+ mLogicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId,
ddConfig.getThermalBrightnessThrottlingDataMapByThrottlingId());
}
@@ -3091,7 +3139,63 @@
}
}
- private void logManualBrightnessEvent(BrightnessEvent event) {
+ // Return bucket index of range_[left]_[right] where
+ // left <= nits < right
+ private int nitsToRangeIndex(float nits) {
+ for (int i = 0; i < BRIGHTNESS_RANGE_BOUNDARIES.length; i++) {
+ if (nits < BRIGHTNESS_RANGE_BOUNDARIES[i]) {
+ return BRIGHTNESS_RANGE_INDEX[i];
+ }
+ }
+ return FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_3000_INF;
+ }
+
+ private int convertBrightnessReasonToStatsEnum(int brightnessReason) {
+ switch(brightnessReason) {
+ case BrightnessReason.REASON_UNKNOWN:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_UNKNOWN;
+ case BrightnessReason.REASON_MANUAL:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_MANUAL;
+ case BrightnessReason.REASON_DOZE:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_DOZE;
+ case BrightnessReason.REASON_DOZE_DEFAULT:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_DOZE_DEFAULT;
+ case BrightnessReason.REASON_AUTOMATIC:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_AUTOMATIC;
+ case BrightnessReason.REASON_SCREEN_OFF:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_SCREEN_OFF;
+ case BrightnessReason.REASON_OVERRIDE:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_OVERRIDE;
+ case BrightnessReason.REASON_TEMPORARY:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_TEMPORARY;
+ case BrightnessReason.REASON_BOOST:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_BOOST;
+ case BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_SCREEN_OFF_BRIGHTNESS_SENSOR;
+ case BrightnessReason.REASON_FOLLOWER:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_FOLLOWER;
+ }
+ return FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_UNKNOWN;
+ }
+
+ private void logBrightnessEvent(BrightnessEvent event, float unmodifiedBrightness) {
+ int modifier = event.getReason().getModifier();
+ int flags = event.getFlags();
+ // It's easier to check if the brightness is at maximum level using the brightness
+ // value untouched by any modifiers
+ boolean brightnessIsMax = unmodifiedBrightness == event.getHbmMax();
+ float brightnessInNits = convertToAdjustedNits(event.getBrightness());
float appliedLowPowerMode = event.isLowPowerModeSet() ? event.getPowerFactor() : -1f;
int appliedRbcStrength = event.isRbcEnabled() ? event.getRbcStrength() : -1;
float appliedHbmMaxNits =
@@ -3105,7 +3209,7 @@
if (mIsDisplayInternal) {
FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED,
convertToAdjustedNits(event.getInitialBrightness()),
- convertToAdjustedNits(event.getBrightness()),
+ brightnessInNits,
event.getLux(),
event.getPhysicalDisplayId(),
event.wasShortTermModelActive(),
@@ -3114,7 +3218,21 @@
appliedHbmMaxNits,
appliedThermalCapNits,
event.isAutomaticBrightnessEnabled(),
- FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__REASON__REASON_MANUAL);
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__REASON__REASON_MANUAL,
+ convertBrightnessReasonToStatsEnum(event.getReason().getReason()),
+ nitsToRangeIndex(brightnessInNits),
+ brightnessIsMax,
+ event.getHbmMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
+ event.getHbmMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR,
+ (modifier & BrightnessReason.MODIFIER_LOW_POWER) > 0,
+ mBrightnessThrottler.getBrightnessMaxReason(),
+ (modifier & BrightnessReason.MODIFIER_DIMMED) > 0,
+ event.isRbcEnabled(),
+ (flags & BrightnessEvent.FLAG_INVALID_LUX) > 0,
+ (flags & BrightnessEvent.FLAG_DOZE_SCALE) > 0,
+ (flags & BrightnessEvent.FLAG_USER_SET) > 0,
+ (flags & BrightnessEvent.FLAG_IDLE_CURVE) > 0,
+ (flags & BrightnessEvent.FLAG_LOW_POWER_MODE) > 0);
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index f96b58e..3b3d5da 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -85,6 +85,7 @@
import com.android.server.policy.WindowManagerPolicy;
import java.io.PrintWriter;
+import java.util.Objects;
/**
* Controls the power state of the display.
@@ -157,6 +158,51 @@
private static final int RINGBUFFER_MAX = 100;
+ private static final float[] BRIGHTNESS_RANGE_BOUNDARIES = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 60, 70, 80,
+ 90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200,
+ 1400, 1600, 1800, 2000, 2250, 2500, 2750, 3000};
+ private static final int[] BRIGHTNESS_RANGE_INDEX = {
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_UNKNOWN,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_0_1,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1_2,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2_3,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_3_4,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_4_5,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_5_6,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_6_7,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_7_8,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_8_9,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_9_10,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_10_20,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_20_30,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_30_40,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_40_50,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_50_60,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_60_70,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_70_80,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_80_90,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_90_100,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_100_200,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_200_300,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_300_400,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_400_500,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_500_600,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_600_700,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_700_800,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_800_900,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_900_1000,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1000_1200,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1200_1400,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1400_1600,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1600_1800,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_1800_2000,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2000_2250,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2250_2500,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2500_2750,
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_2750_3000,
+ };
+
private final String mTag;
private final Object mLock = new Object();
@@ -443,7 +489,7 @@
mAutomaticBrightnessStrategy = new AutomaticBrightnessStrategy(context, mDisplayId);
mTag = "DisplayPowerController2[" + mDisplayId + "]";
mThermalBrightnessThrottlingDataId =
- logicalDisplay.getThermalBrightnessThrottlingDataIdLocked();
+ logicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId;
mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
@@ -715,7 +761,7 @@
&& mLogicalDisplay.getPrimaryDisplayDeviceLocked()
.getDisplayDeviceInfoLocked().type == Display.TYPE_INTERNAL;
final String thermalBrightnessThrottlingDataId =
- mLogicalDisplay.getThermalBrightnessThrottlingDataIdLocked();
+ mLogicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId;
mHandler.postAtTime(() -> {
boolean changed = false;
@@ -733,8 +779,8 @@
// last command that was sent to change it's state. Let's assume it is unknown so
// that we trigger a change immediately.
mPowerState.resetScreenState();
- } else if (
- !mThermalBrightnessThrottlingDataId.equals(thermalBrightnessThrottlingDataId)) {
+ } else if (!Objects.equals(mThermalBrightnessThrottlingDataId,
+ thermalBrightnessThrottlingDataId)) {
changed = true;
mThermalBrightnessThrottlingDataId = thermalBrightnessThrottlingDataId;
mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig(
@@ -1256,7 +1302,8 @@
int brightnessAdjustmentFlags = 0;
if (Float.isNaN(brightnessState)) {
if (mAutomaticBrightnessStrategy.isAutoBrightnessEnabled()) {
- brightnessState = mAutomaticBrightnessStrategy.getAutomaticScreenBrightness();
+ brightnessState = mAutomaticBrightnessStrategy.getAutomaticScreenBrightness(
+ mTempBrightnessEvent);
if (BrightnessUtils.isValidBrightnessValue(brightnessState)
|| brightnessState == PowerManager.BRIGHTNESS_OFF_FLOAT) {
rawBrightnessState = mAutomaticBrightnessController
@@ -1570,8 +1617,9 @@
? BrightnessEvent.FLAG_USER_SET : 0));
Slog.i(mTag, newEvent.toString(/* includeTime= */ false));
- if (userSetBrightnessChanged) {
- logManualBrightnessEvent(newEvent);
+ if (userSetBrightnessChanged
+ || newEvent.getReason().getReason() != BrightnessReason.REASON_TEMPORARY) {
+ logBrightnessEvent(newEvent, unthrottledBrightnessState);
}
if (mBrightnessEventRingBuffer != null) {
mBrightnessEventRingBuffer.append(newEvent);
@@ -1774,7 +1822,8 @@
() -> {
sendUpdatePowerState();
postBrightnessChangeRunnable();
- }, mUniqueDisplayId, mLogicalDisplay.getThermalBrightnessThrottlingDataIdLocked(),
+ }, mUniqueDisplayId,
+ mLogicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId,
ddConfig.getThermalBrightnessThrottlingDataMapByThrottlingId());
}
@@ -2448,7 +2497,64 @@
}
}
- private void logManualBrightnessEvent(BrightnessEvent event) {
+ // Return bucket index of range_[left]_[right] where
+ // left <= nits < right
+ private int nitsToRangeIndex(float nits) {
+ for (int i = 0; i < BRIGHTNESS_RANGE_BOUNDARIES.length; i++) {
+ if (nits < BRIGHTNESS_RANGE_BOUNDARIES[i]) {
+ return BRIGHTNESS_RANGE_INDEX[i];
+ }
+ }
+ return FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__BUCKET_INDEX__RANGE_3000_INF;
+ }
+
+ private int convertBrightnessReasonToStatsEnum(int brightnessReason) {
+ switch(brightnessReason) {
+ case BrightnessReason.REASON_UNKNOWN:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_UNKNOWN;
+ case BrightnessReason.REASON_MANUAL:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_MANUAL;
+ case BrightnessReason.REASON_DOZE:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_DOZE;
+ case BrightnessReason.REASON_DOZE_DEFAULT:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_DOZE_DEFAULT;
+ case BrightnessReason.REASON_AUTOMATIC:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_AUTOMATIC;
+ case BrightnessReason.REASON_SCREEN_OFF:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_SCREEN_OFF;
+ case BrightnessReason.REASON_OVERRIDE:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_OVERRIDE;
+ case BrightnessReason.REASON_TEMPORARY:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_TEMPORARY;
+ case BrightnessReason.REASON_BOOST:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_BOOST;
+ case BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_SCREEN_OFF_BRIGHTNESS_SENSOR;
+ case BrightnessReason.REASON_FOLLOWER:
+ return FrameworkStatsLog
+ .DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_FOLLOWER;
+ }
+ return FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__ENTIRE_REASON__REASON_UNKNOWN;
+ }
+
+ private void logBrightnessEvent(BrightnessEvent event, float unmodifiedBrightness) {
+ int modifier = event.getReason().getModifier();
+ int flags = event.getFlags();
+ // It's easier to check if the brightness is at maximum level using the brightness
+ // value untouched by any modifiers
+ boolean brightnessIsMax = unmodifiedBrightness == event.getHbmMax();
+ float brightnessInNits =
+ mDisplayBrightnessController.convertToAdjustedNits(event.getBrightness());
float appliedLowPowerMode = event.isLowPowerModeSet() ? event.getPowerFactor() : -1f;
int appliedRbcStrength = event.isRbcEnabled() ? event.getRbcStrength() : -1;
float appliedHbmMaxNits =
@@ -2462,7 +2568,7 @@
FrameworkStatsLog.write(FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED,
mDisplayBrightnessController
.convertToAdjustedNits(event.getInitialBrightness()),
- mDisplayBrightnessController.convertToAdjustedNits(event.getBrightness()),
+ brightnessInNits,
event.getLux(),
event.getPhysicalDisplayId(),
event.wasShortTermModelActive(),
@@ -2471,7 +2577,21 @@
appliedHbmMaxNits,
appliedThermalCapNits,
event.isAutomaticBrightnessEnabled(),
- FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__REASON__REASON_MANUAL);
+ FrameworkStatsLog.DISPLAY_BRIGHTNESS_CHANGED__REASON__REASON_MANUAL,
+ convertBrightnessReasonToStatsEnum(event.getReason().getReason()),
+ nitsToRangeIndex(brightnessInNits),
+ brightnessIsMax,
+ event.getHbmMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
+ event.getHbmMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR,
+ (modifier & BrightnessReason.MODIFIER_LOW_POWER) > 0,
+ mBrightnessThrottler.getBrightnessMaxReason(),
+ (modifier & BrightnessReason.MODIFIER_DIMMED) > 0,
+ event.isRbcEnabled(),
+ (flags & BrightnessEvent.FLAG_INVALID_LUX) > 0,
+ (flags & BrightnessEvent.FLAG_DOZE_SCALE) > 0,
+ (flags & BrightnessEvent.FLAG_USER_SET) > 0,
+ (flags & BrightnessEvent.FLAG_IDLE_CURVE) > 0,
+ (flags & BrightnessEvent.FLAG_LOW_POWER_MODE) > 0);
}
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 0b6d1c8..e5c50e6 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -203,6 +203,7 @@
mIsEnabled = true;
mIsInTransition = false;
mThermalBrightnessThrottlingDataId = DisplayDeviceConfig.DEFAULT_ID;
+ mBaseDisplayInfo.thermalBrightnessThrottlingDataId = mThermalBrightnessThrottlingDataId;
}
public void setDevicePositionLocked(int position) {
@@ -514,6 +515,7 @@
mBaseDisplayInfo.layoutLimitedRefreshRate = mLayoutLimitedRefreshRate;
mBaseDisplayInfo.thermalRefreshRateThrottling = mThermalRefreshRateThrottling;
+ mBaseDisplayInfo.thermalBrightnessThrottlingDataId = mThermalBrightnessThrottlingDataId;
mPrimaryDisplayDeviceInfo = deviceInfo;
mInfo.set(null);
@@ -886,19 +888,14 @@
}
/**
- * @return The ID of the brightness throttling data that this display should use.
- */
- public String getThermalBrightnessThrottlingDataIdLocked() {
- return mThermalBrightnessThrottlingDataId;
- }
-
- /**
* @param brightnessThrottlingDataId The ID of the brightness throttling data that this
* display should use.
*/
public void setThermalBrightnessThrottlingDataIdLocked(String brightnessThrottlingDataId) {
- mThermalBrightnessThrottlingDataId =
- brightnessThrottlingDataId;
+ if (!Objects.equals(brightnessThrottlingDataId, mThermalBrightnessThrottlingDataId)) {
+ mThermalBrightnessThrottlingDataId = brightnessThrottlingDataId;
+ mDirty = true;
+ }
}
/**
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
index a3f8c4d..7574de8 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -437,6 +437,7 @@
* persist the nit value, the nit value for the default display will be loaded.
*/
private void loadNitBasedBrightnessSetting() {
+ float currentBrightnessSetting = Float.NaN;
if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
float brightnessNitsForDefaultDisplay =
mBrightnessSetting.getBrightnessNitsForDefaultDisplay();
@@ -445,15 +446,17 @@
brightnessNitsForDefaultDisplay);
if (BrightnessUtils.isValidBrightnessValue(brightnessForDefaultDisplay)) {
mBrightnessSetting.setBrightness(brightnessForDefaultDisplay);
- synchronized (mLock) {
- mCurrentScreenBrightness = brightnessForDefaultDisplay;
- }
- return;
+ currentBrightnessSetting = brightnessForDefaultDisplay;
}
}
}
+
+ if (Float.isNaN(currentBrightnessSetting)) {
+ currentBrightnessSetting = getScreenBrightnessSetting();
+ }
+
synchronized (mLock) {
- mCurrentScreenBrightness = getScreenBrightnessSetting();
+ mCurrentScreenBrightness = currentBrightnessSetting;
}
}
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
index f6cf866..95cbf98 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
@@ -25,6 +25,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.AutomaticBrightnessController;
+import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
@@ -252,10 +253,12 @@
/**
* Evaluates the target automatic brightness of the associated display.
+ * @param brightnessEvent Event object to populate with details about why the specific
+ * brightness was chosen.
*/
- public float getAutomaticScreenBrightness() {
+ public float getAutomaticScreenBrightness(BrightnessEvent brightnessEvent) {
float brightness = (mAutomaticBrightnessController != null)
- ? mAutomaticBrightnessController.getAutomaticScreenBrightness()
+ ? mAutomaticBrightnessController.getAutomaticScreenBrightness(brightnessEvent)
: PowerManager.BRIGHTNESS_INVALID_FLOAT;
adjustAutomaticBrightnessStateIfValid(brightness);
return brightness;
diff --git a/services/core/java/com/android/server/infra/ServiceNameBaseResolver.java b/services/core/java/com/android/server/infra/ServiceNameBaseResolver.java
index 76ea05e..66ce5c7 100644
--- a/services/core/java/com/android/server/infra/ServiceNameBaseResolver.java
+++ b/services/core/java/com/android/server/infra/ServiceNameBaseResolver.java
@@ -268,7 +268,7 @@
}
if (enabled) {
Slog.i(TAG, "disabling default service for user " + userId);
- mDefaultServicesDisabled.removeAt(userId);
+ mDefaultServicesDisabled.delete(userId);
} else {
Slog.i(TAG, "enabling default service for user " + userId);
mDefaultServicesDisabled.put(userId, true);
diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java
index 5b21669..153e9c1 100644
--- a/services/core/java/com/android/server/input/InputSettingsObserver.java
+++ b/services/core/java/com/android/server/input/InputSettingsObserver.java
@@ -52,25 +52,27 @@
mHandler = handler;
mNative = nativeIms;
mObservers = Map.ofEntries(
- Map.entry(Settings.System.getUriFor(Settings.System.POINTER_SPEED),
- (reason) -> updateMousePointerSpeed()),
- Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_POINTER_SPEED),
- (reason) -> updateTouchpadPointerSpeed()),
- Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_NATURAL_SCROLLING),
- (reason) -> updateTouchpadNaturalScrollingEnabled()),
- Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_TAP_TO_CLICK),
- (reason) -> updateTouchpadTapToClickEnabled()),
- Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE),
- (reason) -> updateTouchpadRightClickZoneEnabled()),
- Map.entry(Settings.System.getUriFor(Settings.System.SHOW_TOUCHES),
- (reason) -> updateShowTouches()),
- Map.entry(Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON),
- (reason) -> updateAccessibilityLargePointer()),
- Map.entry(Settings.Secure.getUriFor(Settings.Secure.LONG_PRESS_TIMEOUT),
- (reason) -> updateDeepPressStatus(reason)),
- Map.entry(
- Settings.Global.getUriFor(Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH),
- (reason) -> updateMaximumObscuringOpacityForTouch()));
+ Map.entry(Settings.System.getUriFor(Settings.System.POINTER_SPEED),
+ (reason) -> updateMousePointerSpeed()),
+ Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_POINTER_SPEED),
+ (reason) -> updateTouchpadPointerSpeed()),
+ Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_NATURAL_SCROLLING),
+ (reason) -> updateTouchpadNaturalScrollingEnabled()),
+ Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_TAP_TO_CLICK),
+ (reason) -> updateTouchpadTapToClickEnabled()),
+ Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE),
+ (reason) -> updateTouchpadRightClickZoneEnabled()),
+ Map.entry(Settings.System.getUriFor(Settings.System.SHOW_TOUCHES),
+ (reason) -> updateShowTouches()),
+ Map.entry(
+ Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON),
+ (reason) -> updateAccessibilityLargePointer()),
+ Map.entry(Settings.Secure.getUriFor(Settings.Secure.LONG_PRESS_TIMEOUT),
+ (reason) -> updateLongPressTimeout(reason)),
+ Map.entry(
+ Settings.Global.getUriFor(
+ Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH),
+ (reason) -> updateMaximumObscuringOpacityForTouch()));
}
/**
@@ -151,8 +153,13 @@
mNative.reloadPointerIcons();
}
- private void updateDeepPressStatus(String reason) {
- // Not using ViewConfiguration.getLongPressTimeout here because it may return a stale value
+ private void updateLongPressTimeout(String reason) {
+ // Some key gesture timeouts are based on the long press timeout, so update key gesture
+ // timeouts when the value changes. See ViewConfiguration#getKeyRepeatTimeout().
+ mNative.notifyKeyGestureTimeoutsChanged();
+
+ // Update the deep press status.
+ // Not using ViewConfiguration.getLongPressTimeout here because it may return a stale value.
final int timeout = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.LONG_PRESS_TIMEOUT, ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT,
UserHandle.USER_CURRENT);
diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java
index aeb2477..363bc94 100644
--- a/services/core/java/com/android/server/input/NativeInputManagerService.java
+++ b/services/core/java/com/android/server/input/NativeInputManagerService.java
@@ -28,6 +28,7 @@
import android.view.InputEvent;
import android.view.PointerIcon;
import android.view.VerifiedInputEvent;
+import android.view.ViewConfiguration;
import java.util.List;
@@ -198,8 +199,6 @@
void changeKeyboardLayoutAssociation();
- void notifyPointerDisplayIdChanged();
-
void setDisplayEligibilityForPointerCapture(int displayId, boolean enabled);
void setMotionClassifierEnabled(boolean enabled);
@@ -243,6 +242,15 @@
*/
void sysfsNodeChanged(String sysfsNodePath);
+ /**
+ * Notify there is a change in any of the key gesture timeouts, such as the key
+ * repeat timeout or key repeat delay.
+ *
+ * @see ViewConfiguration#getKeyRepeatTimeout()
+ * @see ViewConfiguration#getKeyRepeatDelay()
+ */
+ void notifyKeyGestureTimeoutsChanged();
+
/** The native implementation of InputManagerService methods. */
class NativeImpl implements NativeInputManagerService {
/** Pointer to native input manager service object, used by native code. */
@@ -452,9 +460,6 @@
public native void changeKeyboardLayoutAssociation();
@Override
- public native void notifyPointerDisplayIdChanged();
-
- @Override
public native void setDisplayEligibilityForPointerCapture(int displayId, boolean enabled);
@Override
@@ -493,5 +498,8 @@
@Override
public native void sysfsNodeChanged(String sysfsNodePath);
+
+ @Override
+ public native void notifyKeyGestureTimeoutsChanged();
}
}
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 7a51126..377b8cf 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -395,8 +395,8 @@
synchronized (mLock) {
final boolean consentGranted =
consentResult == RECORD_CONTENT_DISPLAY || consentResult == RECORD_CONTENT_TASK;
- if (consentGranted && projection == null || !isCurrentProjection(
- projection.asBinder())) {
+ if (consentGranted && !isCurrentProjection(
+ projection == null ? null : projection.asBinder())) {
Slog.v(TAG, "Reusing token: Ignore consent result of " + consentResult + " for a "
+ "token that isn't current");
return;
diff --git a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
index 48ee64f..8a28888 100644
--- a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
+++ b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
@@ -437,6 +437,16 @@
.addCategory(Intent.CATEGORY_DEFAULT)
.build();
+ private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_PHOTOPICKER_SELECTION =
+ new DefaultCrossProfileIntentFilter.Builder(
+ DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
+ /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
+ // and FLAG_ALLOW_CHAINED_RESOLUTION set
+ /* letsPersonalDataIntoProfile= */ false)
+ .addAction(MediaStore.ACTION_USER_SELECT_IMAGES_FOR_APP)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .build();
+
/*
Allowing send action from clone to parent profile to share content from clone apps to parent
apps
@@ -611,7 +621,8 @@
CLONE_TO_PARENT_VIEW_ACTION,
CLONE_TO_PARENT_PICK_INSERT_ACTION,
CLONE_TO_PARENT_DIAL_DATA,
- CLONE_TO_PARENT_SMS_MMS
+ CLONE_TO_PARENT_SMS_MMS,
+ CLONE_TO_PARENT_PHOTOPICKER_SELECTION
);
}
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 1e0c95c..a267e8a 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -118,6 +118,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
+import android.content.pm.ResolveInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.Signature;
import android.content.pm.SigningDetails;
@@ -3975,6 +3976,24 @@
mPm.mSettings.disableSystemPackageLPw(parsedPackage.getPackageName(), true);
}
}
+
+ // If this is a system app we hadn't seen before, and this is a first boot or OTA,
+ // we need to unstop it if it doesn't have a launcher entry.
+ if (mPm.mShouldStopSystemPackagesByDefault && scanResult.mRequest.mPkgSetting == null
+ && ((scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0)
+ && ((scanFlags & SCAN_AS_SYSTEM) != 0)) {
+ final Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
+ launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ launcherIntent.setPackage(parsedPackage.getPackageName());
+ final List<ResolveInfo> launcherActivities =
+ mPm.snapshotComputer().queryIntentActivitiesInternal(launcherIntent, null,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 0);
+ if (launcherActivities.isEmpty()) {
+ scanResult.mPkgSetting.setStopped(false, 0);
+ }
+ }
+
if (mIncrementalManager != null && isIncrementalPath(parsedPackage.getPath())) {
if (scanResult.mPkgSetting != null && scanResult.mPkgSetting.isLoading()) {
// Continue monitoring loading progress of active incremental packages
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 402fb30..9b1a80be 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -1120,12 +1120,12 @@
return shortcutOverridesInfo;
}
- List<String> packagesToOverride =
+ Map<String, String> packagesToOverride =
DevicePolicyCache.getInstance().getLauncherShortcutOverrides();
- for (String packageName : packagesToOverride) {
+ for (Map.Entry<String, String> packageNames : packagesToOverride.entrySet()) {
Intent intent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_LAUNCHER)
- .setPackage(packageName);
+ .setPackage(packageNames.getValue());
List<LauncherActivityInfoInternal> possibleShortcutOverrides =
queryIntentLauncherActivities(
@@ -1135,7 +1135,8 @@
);
if (!possibleShortcutOverrides.isEmpty()) {
- shortcutOverridesInfo.put(packageName, possibleShortcutOverrides.get(0));
+ shortcutOverridesInfo.put(packageNames.getKey(),
+ possibleShortcutOverrides.get(0));
}
}
return shortcutOverridesInfo;
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index ef7d413..f78b611 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -928,6 +928,7 @@
boolean showUid = false;
boolean showVersionCode = false;
boolean listApexOnly = false;
+ boolean showStopped = false;
int uid = -1;
int defaultUserId = UserHandle.USER_ALL;
try {
@@ -985,6 +986,9 @@
case "--match-libraries":
getFlags |= PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES;
break;
+ case "--show-stopped":
+ showStopped = true;
+ break;
default:
pw.println("Error: Unknown option: " + opt);
return -1;
@@ -1077,6 +1081,12 @@
stringBuilder.append(info.getLongVersionCode());
}
}
+ if (showStopped) {
+ stringBuilder.append(" stopped=");
+ stringBuilder.append(
+ ((info.applicationInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0)
+ ? "true" : "false");
+ }
if (listInstaller) {
stringBuilder.append(" installer=");
stringBuilder.append(mInterface.getInstallerPackageName(info.packageName));
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index c54b111..e0dbcbf 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4293,10 +4293,23 @@
// Non-Apex system apps, that are not included in the allowlist in
// initialNonStoppedSystemPackages, should be marked as stopped by default.
- final boolean shouldBeStopped = service.mShouldStopSystemPackagesByDefault
+ boolean shouldBeStopped = service.mShouldStopSystemPackagesByDefault
&& ps.isSystem()
&& !ps.isApex()
&& !service.mInitialNonStoppedSystemPackages.contains(ps.getPackageName());
+ if (shouldBeStopped) {
+ final Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
+ launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ launcherIntent.setPackage(ps.getPackageName());
+ final List<ResolveInfo> launcherActivities =
+ service.snapshotComputer().queryIntentActivitiesInternal(launcherIntent,
+ null,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 0);
+ if (launcherActivities.isEmpty()) {
+ shouldBeStopped = false;
+ }
+ }
ps.setStopped(shouldBeStopped, userHandle);
// If userTypeInstallablePackages is the *only* reason why we're not installing,
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index b669ba2..84a9888 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1716,6 +1716,11 @@
if (si == null) {
return;
}
+
+ if (isCallerSystem()) {
+ return; // no check
+ }
+
if (!Objects.equals(callerPackage, si.getPackage())) {
android.util.EventLog.writeEvent(0x534e4554, "109824443", -1, "");
throw new SecurityException("Shortcut package name mismatch");
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 8433c47..79eed64 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1004,7 +1004,7 @@
return;
}
- final boolean interactive = Display.isOnState(mDefaultDisplay.getState());
+ final boolean interactive = mDefaultDisplayPolicy.isAwake();
Slog.d(TAG, "powerPress: eventTime=" + eventTime + " interactive=" + interactive
+ " count=" + count + " beganFromNonInteractive=" + beganFromNonInteractive
@@ -2201,8 +2201,10 @@
// Match current screen state.
if (!mPowerManager.isInteractive()) {
- startedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
- finishedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+ startedGoingToSleep(Display.DEFAULT_DISPLAY_GROUP,
+ PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+ finishedGoingToSleep(Display.DEFAULT_DISPLAY_GROUP,
+ PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
}
mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
@@ -4095,7 +4097,7 @@
// This could prevent some wrong state in multi-displays environment,
// the default display may turned off but interactive is true.
- final boolean isDefaultDisplayOn = Display.isOnState(mDefaultDisplay.getState());
+ final boolean isDefaultDisplayOn = mDefaultDisplayPolicy.isAwake();
final boolean interactiveAndOn = interactive && isDefaultDisplayOn;
if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
handleKeyGesture(event, interactiveAndOn);
@@ -4795,17 +4797,40 @@
}
};
+ @Override
+ public void startedWakingUpGlobal(@WakeReason int reason) {
+
+ }
+
+ @Override
+ public void finishedWakingUpGlobal(@WakeReason int reason) {
+
+ }
+
+ @Override
+ public void startedGoingToSleepGlobal(@PowerManager.GoToSleepReason int reason) {
+ mDeviceGoingToSleep = true;
+ }
+
+ @Override
+ public void finishedGoingToSleepGlobal(@PowerManager.GoToSleepReason int reason) {
+ mDeviceGoingToSleep = false;
+ }
+
// Called on the PowerManager's Notifier thread.
@Override
- public void startedGoingToSleep(@PowerManager.GoToSleepReason int pmSleepReason) {
+ public void startedGoingToSleep(int displayGroupId,
+ @PowerManager.GoToSleepReason int pmSleepReason) {
if (DEBUG_WAKEUP) {
- Slog.i(TAG, "Started going to sleep... (why="
+ Slog.i(TAG, "Started going to sleep... (groupId=" + displayGroupId + " why="
+ WindowManagerPolicyConstants.offReasonToString(
WindowManagerPolicyConstants.translateSleepReasonToOffReason(
pmSleepReason)) + ")");
}
+ if (displayGroupId != Display.DEFAULT_DISPLAY_GROUP) {
+ return;
+ }
- mDeviceGoingToSleep = true;
mRequestedOrSleepingDefaultDisplay = true;
if (mKeyguardDelegate != null) {
@@ -4815,17 +4840,20 @@
// Called on the PowerManager's Notifier thread.
@Override
- public void finishedGoingToSleep(@PowerManager.GoToSleepReason int pmSleepReason) {
+ public void finishedGoingToSleep(int displayGroupId,
+ @PowerManager.GoToSleepReason int pmSleepReason) {
+ if (displayGroupId != Display.DEFAULT_DISPLAY_GROUP) {
+ return;
+ }
EventLogTags.writeScreenToggled(0);
if (DEBUG_WAKEUP) {
- Slog.i(TAG, "Finished going to sleep... (why="
+ Slog.i(TAG, "Finished going to sleep... (groupId=" + displayGroupId + " why="
+ WindowManagerPolicyConstants.offReasonToString(
WindowManagerPolicyConstants.translateSleepReasonToOffReason(
pmSleepReason)) + ")");
}
MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);
- mDeviceGoingToSleep = false;
mRequestedOrSleepingDefaultDisplay = false;
mDefaultDisplayPolicy.setAwake(false);
@@ -4850,26 +4878,18 @@
// Called on the PowerManager's Notifier thread.
@Override
- public void onPowerGroupWakefulnessChanged(int groupId, int wakefulness,
- @PowerManager.GoToSleepReason int pmSleepReason, int globalWakefulness) {
- if (wakefulness != globalWakefulness
- && wakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE
- && groupId == Display.DEFAULT_DISPLAY_GROUP
- && mKeyguardDelegate != null) {
- mKeyguardDelegate.doKeyguardTimeout(null);
- }
- }
-
- // Called on the PowerManager's Notifier thread.
- @Override
- public void startedWakingUp(@PowerManager.WakeReason int pmWakeReason) {
- EventLogTags.writeScreenToggled(1);
+ public void startedWakingUp(int displayGroupId, @WakeReason int pmWakeReason) {
if (DEBUG_WAKEUP) {
- Slog.i(TAG, "Started waking up... (why="
+ Slog.i(TAG, "Started waking up... (groupId=" + displayGroupId + " why="
+ WindowManagerPolicyConstants.onReasonToString(
- WindowManagerPolicyConstants.translateWakeReasonToOnReason(
- pmWakeReason)) + ")");
+ WindowManagerPolicyConstants.translateWakeReasonToOnReason(
+ pmWakeReason)) + ")");
}
+ if (displayGroupId != Display.DEFAULT_DISPLAY_GROUP) {
+ return;
+ }
+ EventLogTags.writeScreenToggled(1);
+
mDefaultDisplayPolicy.setAwake(true);
@@ -4892,13 +4912,16 @@
// Called on the PowerManager's Notifier thread.
@Override
- public void finishedWakingUp(@PowerManager.WakeReason int pmWakeReason) {
+ public void finishedWakingUp(int displayGroupId, @WakeReason int pmWakeReason) {
if (DEBUG_WAKEUP) {
- Slog.i(TAG, "Finished waking up... (why="
+ Slog.i(TAG, "Finished waking up... (groupId=" + displayGroupId + " why="
+ WindowManagerPolicyConstants.onReasonToString(
WindowManagerPolicyConstants.translateWakeReasonToOnReason(
pmWakeReason)) + ")");
}
+ if (displayGroupId != Display.DEFAULT_DISPLAY_GROUP) {
+ return;
+ }
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onFinishedWakingUp();
@@ -5378,8 +5401,8 @@
}
}
mSideFpsEventHandler.onFingerprintSensorReady();
- startedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);
- finishedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);
+ startedWakingUp(Display.DEFAULT_DISPLAY_GROUP, PowerManager.WAKE_REASON_UNKNOWN);
+ finishedWakingUp(Display.DEFAULT_DISPLAY_GROUP, PowerManager.WAKE_REASON_UNKNOWN);
int defaultDisplayState = mDisplayManager.getDisplay(DEFAULT_DISPLAY).getState();
boolean defaultDisplayOn = defaultDisplayState == Display.STATE_ON;
diff --git a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
index 92f00113..9c3b38a 100644
--- a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
+++ b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
@@ -395,7 +395,7 @@
private class KeyHandler extends Handler {
KeyHandler() {
- super(Looper.getMainLooper());
+ super(Looper.myLooper());
}
@Override
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 7c3f1aa..887f946 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -67,10 +67,12 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.companion.virtual.VirtualDevice;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.hardware.display.VirtualDisplay;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
@@ -762,50 +764,84 @@
void setAllowLockscreenWhenOn(int displayId, boolean allow);
/**
+ * Called when the global wakefulness is becoming awake.
+ *
+ * @param reason One of PowerManager.WAKE_REASON_*, detailing the reason for the change.
+ */
+ void startedWakingUpGlobal(@PowerManager.WakeReason int reason);
+
+ /**
+ * Called when the global wakefulness has finished becoming awake.
+ *
+ * @param reason One of PowerManager.WAKE_REASON_*, detailing the reason for the change.
+ */
+ void finishedWakingUpGlobal(@PowerManager.WakeReason int reason);
+
+ /**
+ * Called when the global wakefulness has started going to sleep.
+ *
+ * @param reason One of PowerManager.WAKE_REASON_*, detailing the reason for the change.
+ */
+ void startedGoingToSleepGlobal(@PowerManager.GoToSleepReason int reason);
+
+ /**
+ * Called when the global wakefulness has finished going to sleep.
+ *
+ * @param reason One of PowerManager.WAKE_REASON_*, detailing the reason for the change.
+ */
+ void finishedGoingToSleepGlobal(@PowerManager.GoToSleepReason int reason);
+
+ /**
* Called when the device has started waking up.
*
- * @param pmWakeReason One of PowerManager.WAKE_REASON_*, detailing the specific reason we're
- * waking up, such as WAKE_REASON_POWER_BUTTON or WAKE_REASON_GESTURE.
+ * @param displayGroupId The id of the display group that has started waking up. This will often
+ * be {@link Display#DEFAULT_DISPLAY_GROUP}, but it is possible for other
+ * display groups to exist, for example when there is a
+ * {@link VirtualDevice} with one or more {@link VirtualDisplay}s.
+ * @param pmWakeReason One of PowerManager.WAKE_REASON_*, detailing the specific reason this
+ * display group is waking up, such as WAKE_REASON_POWER_BUTTON or
+ * WAKE_REASON_GESTURE.
*/
- void startedWakingUp(@PowerManager.WakeReason int pmWakeReason);
+ void startedWakingUp(int displayGroupId, @PowerManager.WakeReason int pmWakeReason);
/**
* Called when the device has finished waking up.
*
- * @param pmWakeReason One of PowerManager.WAKE_REASON_*, detailing the specific reason we're
- * waking up, such as WAKE_REASON_POWER_BUTTON or WAKE_REASON_GESTURE.
+ * @param displayGroupId The id of the display group that has finished waking. This will often
+ * be {@link Display#DEFAULT_DISPLAY_GROUP}, but it is possible for other
+ * display groups to exist, for example when there is a
+ * {@link VirtualDevice} with one or more {@link VirtualDisplay}s.
+ * @param pmWakeReason One of PowerManager.WAKE_REASON_*, detailing the specific reason this
+ * display group is waking up, such as WAKE_REASON_POWER_BUTTON or
+ * WAKE_REASON_GESTURE.
*/
- void finishedWakingUp(@PowerManager.WakeReason int pmWakeReason);
+ void finishedWakingUp(int displayGroupId, @PowerManager.WakeReason int pmWakeReason);
/**
* Called when the device has started going to sleep.
*
+ * @param displayGroupId The id of the display group that has started going to sleep. This
+ * will often be {@link Display#DEFAULT_DISPLAY_GROUP}, but it is
+ * possible for other display groups to exist, for example when there is a
+ * {@link VirtualDevice} with one or more {@link VirtualDisplay}s.
* @param pmSleepReason One of PowerManager.GO_TO_SLEEP_REASON_*, detailing the specific reason
- * we're going to sleep, such as GO_TO_SLEEP_REASON_POWER_BUTTON or GO_TO_SLEEP_REASON_TIMEOUT.
+ * this display group is going to sleep, such as
+ * GO_TO_SLEEP_REASON_POWER_BUTTON or GO_TO_SLEEP_REASON_TIMEOUT.
*/
- public void startedGoingToSleep(@PowerManager.GoToSleepReason int pmSleepReason);
+ void startedGoingToSleep(int displayGroupId, @PowerManager.GoToSleepReason int pmSleepReason);
/**
* Called when the device has finished going to sleep.
*
+ * @param displayGroupId The id of the display group that has finished going to sleep. This
+ * will often be {@link Display#DEFAULT_DISPLAY_GROUP}, but it is
+ * possible for other display groups to exist, for example when there is a
+ * {@link VirtualDevice} with one or more {@link VirtualDisplay}s.
* @param pmSleepReason One of PowerManager.GO_TO_SLEEP_REASON_*, detailing the specific reason
- * we're going to sleep, such as GO_TO_SLEEP_REASON_POWER_BUTTON or GO_TO_SLEEP_REASON_TIMEOUT.
+ * we're going to sleep, such as GO_TO_SLEEP_REASON_POWER_BUTTON or
+ * GO_TO_SLEEP_REASON_TIMEOUT.
*/
- public void finishedGoingToSleep(@PowerManager.GoToSleepReason int pmSleepReason);
-
- /**
- * Called when a particular PowerGroup has changed wakefulness.
- *
- * @param groupId The id of the PowerGroup.
- * @param wakefulness One of PowerManagerInternal.WAKEFULNESS_* indicating the wake state for
- * the group
- * @param pmSleepReason One of PowerManager.GO_TO_SLEEP_REASON_*, detailing the reason this
- * group is going to sleep.
- * @param globalWakefulness The global wakefulness, which may or may not match that of this
- * group. One of PowerManagerInternal.WAKEFULNESS_*
- */
- void onPowerGroupWakefulnessChanged(int groupId, int wakefulness,
- @PowerManager.GoToSleepReason int pmSleepReason, int globalWakefulness);
+ void finishedGoingToSleep(int displayGroupId, @PowerManager.GoToSleepReason int pmSleepReason);
/**
* Called when the display is about to turn on to show content.
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index d0ed9bf..9bc0ee22 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -51,6 +51,7 @@
import android.telephony.TelephonyManager;
import android.util.EventLog;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.WindowManagerPolicyConstants;
import com.android.internal.annotations.VisibleForTesting;
@@ -87,7 +88,7 @@
* tell the system when we go to sleep so that it can lock the keyguard if needed.
* </p>
*/
-@VisibleForTesting
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
public class Notifier {
private static final String TAG = "PowerManagerNotifier";
@@ -150,14 +151,21 @@
// begins charging wirelessly
private final boolean mShowWirelessChargingAnimationConfig;
- // The current interactive state. This is set as soon as an interactive state
+ // Encapsulates interactivity information about a particular display group.
+ private static class Interactivity {
+ public boolean isInteractive = true;
+ public int changeReason;
+ public long changeStartTime; // In SystemClock.uptimeMillis()
+ public boolean isChanging;
+ }
+
+ private final SparseArray<Interactivity> mInteractivityByGroupId = new SparseArray<>();
+
+ // The current global interactive state. This is set as soon as an interactive state
// transition begins so as to capture the reason that it happened. At some point
// this state will propagate to the pending state then eventually to the
// broadcasted state over the course of reporting the transition asynchronously.
- private boolean mInteractive = true;
- private int mInteractiveChangeReason;
- private long mInteractiveChangeStartTime; // In SystemClock.uptimeMillis()
- private boolean mInteractiveChanging;
+ private Interactivity mGlobalInteractivity = new Interactivity();
// The pending interactive state that we will eventually want to broadcast.
// This is designed so that we can collapse redundant sequences of awake/sleep
@@ -438,7 +446,8 @@
* which case it will assume that the state did not fully converge before the
* next transition began and will recover accordingly.
*/
- public void onWakefulnessChangeStarted(final int wakefulness, int reason, long eventTime) {
+ public void onGlobalWakefulnessChangeStarted(final int wakefulness, int reason,
+ long eventTime) {
final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
if (DEBUG) {
Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness
@@ -456,10 +465,10 @@
// Handle any early interactive state changes.
// Finish pending incomplete ones from a previous cycle.
- if (mInteractive != interactive) {
+ if (mGlobalInteractivity.isInteractive != interactive) {
// Finish up late behaviors if needed.
- if (mInteractiveChanging) {
- handleLateInteractiveChange();
+ if (mGlobalInteractivity.isChanging) {
+ handleLateGlobalInteractiveChange();
}
// Start input as soon as we start waking up or going to sleep.
@@ -475,11 +484,11 @@
FrameworkStatsLog.INTERACTIVE_STATE_CHANGED__STATE__OFF);
// Handle early behaviors.
- mInteractive = interactive;
- mInteractiveChangeReason = reason;
- mInteractiveChangeStartTime = eventTime;
- mInteractiveChanging = true;
- handleEarlyInteractiveChange();
+ mGlobalInteractivity.isInteractive = interactive;
+ mGlobalInteractivity.isChanging = true;
+ mGlobalInteractivity.changeReason = reason;
+ mGlobalInteractivity.changeStartTime = eventTime;
+ handleEarlyGlobalInteractiveChange();
}
}
@@ -490,10 +499,34 @@
if (DEBUG) {
Slog.d(TAG, "onWakefulnessChangeFinished");
}
+ for (int i = 0; i < mInteractivityByGroupId.size(); i++) {
+ int groupId = mInteractivityByGroupId.keyAt(i);
+ Interactivity interactivity = mInteractivityByGroupId.valueAt(i);
+ if (interactivity.isChanging) {
+ interactivity.isChanging = false;
+ handleLateInteractiveChange(groupId);
+ }
+ }
+ if (mGlobalInteractivity.isChanging) {
+ mGlobalInteractivity.isChanging = false;
+ handleLateGlobalInteractiveChange();
+ }
+ }
- if (mInteractiveChanging) {
- mInteractiveChanging = false;
- handleLateInteractiveChange();
+
+ private void handleEarlyInteractiveChange(int groupId) {
+ synchronized (mLock) {
+ Interactivity interactivity = mInteractivityByGroupId.get(groupId);
+ if (interactivity == null) {
+ Slog.e(TAG, "no Interactivity entry for groupId:" + groupId);
+ return;
+ }
+ final int changeReason = interactivity.changeReason;
+ if (interactivity.isInteractive) {
+ mHandler.post(() -> mPolicy.startedWakingUp(groupId, changeReason));
+ } else {
+ mHandler.post(() -> mPolicy.startedGoingToSleep(groupId, changeReason));
+ }
}
}
@@ -501,13 +534,13 @@
* Handle early interactive state changes such as getting applications or the lock
* screen running and ready for the user to see (such as when turning on the screen).
*/
- private void handleEarlyInteractiveChange() {
+ private void handleEarlyGlobalInteractiveChange() {
synchronized (mLock) {
- if (mInteractive) {
+ if (mGlobalInteractivity.isInteractive) {
// Waking up...
mHandler.post(() -> {
- mPolicy.startedWakingUp(mInteractiveChangeReason);
mDisplayManagerInternal.onEarlyInteractivityChange(true /*isInteractive*/);
+ mPolicy.startedWakingUpGlobal(mGlobalInteractivity.changeReason);
});
// Send interactive broadcast.
@@ -516,37 +549,36 @@
updatePendingBroadcastLocked();
} else {
// Going to sleep...
- // Tell the policy that we started going to sleep.
mHandler.post(() -> {
- mPolicy.startedGoingToSleep(mInteractiveChangeReason);
mDisplayManagerInternal.onEarlyInteractivityChange(false /*isInteractive*/);
+ mPolicy.startedGoingToSleepGlobal(mGlobalInteractivity.changeReason);
});
}
}
}
/**
- * Handle late interactive state changes once they are finished so that the system can
- * finish pending transitions (such as turning the screen off) before causing
- * applications to change state visibly.
+ * Handle late global interactive state changes. Also see
+ * {@link #handleLateInteractiveChange(int)}.
*/
- private void handleLateInteractiveChange() {
+ private void handleLateGlobalInteractiveChange() {
synchronized (mLock) {
final int interactiveChangeLatency =
- (int) (SystemClock.uptimeMillis() - mInteractiveChangeStartTime);
- if (mInteractive) {
+ (int) (SystemClock.uptimeMillis() - mGlobalInteractivity.changeStartTime);
+ if (mGlobalInteractivity.isInteractive) {
// Finished waking up...
mHandler.post(() -> {
LogMaker log = new LogMaker(MetricsEvent.SCREEN);
log.setType(MetricsEvent.TYPE_OPEN);
log.setSubtype(WindowManagerPolicyConstants.translateWakeReasonToOnReason(
- mInteractiveChangeReason));
+ mGlobalInteractivity.changeReason));
log.setLatency(interactiveChangeLatency);
- log.addTaggedData(
- MetricsEvent.FIELD_SCREEN_WAKE_REASON, mInteractiveChangeReason);
+ log.addTaggedData(MetricsEvent.FIELD_SCREEN_WAKE_REASON,
+ mGlobalInteractivity.changeReason);
MetricsLogger.action(log);
EventLogTags.writePowerScreenState(1, 0, 0, 0, interactiveChangeLatency);
- mPolicy.finishedWakingUp(mInteractiveChangeReason);
+
+ mPolicy.finishedWakingUpGlobal(mGlobalInteractivity.changeReason);
});
} else {
// Finished going to sleep...
@@ -563,18 +595,19 @@
// Tell the policy we finished going to sleep.
final int offReason = WindowManagerPolicyConstants.translateSleepReasonToOffReason(
- mInteractiveChangeReason);
+ mGlobalInteractivity.changeReason);
mHandler.post(() -> {
LogMaker log = new LogMaker(MetricsEvent.SCREEN);
log.setType(MetricsEvent.TYPE_CLOSE);
log.setSubtype(offReason);
log.setLatency(interactiveChangeLatency);
- log.addTaggedData(
- MetricsEvent.FIELD_SCREEN_SLEEP_REASON, mInteractiveChangeReason);
+ log.addTaggedData(MetricsEvent.FIELD_SCREEN_SLEEP_REASON,
+ mGlobalInteractivity.changeReason);
MetricsLogger.action(log);
EventLogTags.writePowerScreenState(
0, offReason, 0, 0, interactiveChangeLatency);
- mPolicy.finishedGoingToSleep(mInteractiveChangeReason);
+
+ mPolicy.finishedGoingToSleepGlobal(mGlobalInteractivity.changeReason);
});
// Send non-interactive broadcast.
@@ -586,12 +619,62 @@
}
/**
+ * Handle late interactive state changes once they are finished so that the system can
+ * finish pending transitions (such as turning the screen off) before causing
+ * applications to change state visibly.
+ */
+ private void handleLateInteractiveChange(int groupId) {
+ synchronized (mLock) {
+ Interactivity interactivity = mInteractivityByGroupId.get(groupId);
+ if (interactivity == null) {
+ Slog.e(TAG, "no Interactivity entry for groupId:" + groupId);
+ return;
+ }
+ final int changeReason = interactivity.changeReason;
+ if (interactivity.isInteractive) {
+ mHandler.post(() -> mPolicy.finishedWakingUp(groupId, changeReason));
+ } else {
+ mHandler.post(() -> mPolicy.finishedGoingToSleep(groupId, changeReason));
+ }
+ }
+ }
+
+ /**
* Called when an individual PowerGroup changes wakefulness.
*/
- public void onPowerGroupWakefulnessChanged(int groupId, int groupWakefulness, int changeReason,
- int globalWakefulness) {
- mHandler.post(() -> mPolicy.onPowerGroupWakefulnessChanged(groupId, groupWakefulness,
- changeReason, globalWakefulness));
+ public void onGroupWakefulnessChangeStarted(int groupId, int wakefulness, int changeReason,
+ long eventTime) {
+ final boolean isInteractive = PowerManagerInternal.isInteractive(wakefulness);
+
+ boolean isNewGroup = false;
+ Interactivity interactivity = mInteractivityByGroupId.get(groupId);
+ if (interactivity == null) {
+ isNewGroup = true;
+ interactivity = new Interactivity();
+ mInteractivityByGroupId.put(groupId, interactivity);
+ }
+ if (isNewGroup || interactivity.isInteractive != isInteractive) {
+ // Finish up late behaviors if needed.
+ if (interactivity.isChanging) {
+ handleLateInteractiveChange(groupId);
+ }
+
+ // Handle early behaviors.
+ interactivity.isInteractive = isInteractive;
+ interactivity.changeReason = changeReason;
+ interactivity.changeStartTime = eventTime;
+ interactivity.isChanging = true;
+ handleEarlyInteractiveChange(groupId);
+ }
+ }
+
+ /**
+ * Called when a PowerGroup has been removed.
+ *
+ * @param groupId which group was removed
+ */
+ public void onGroupRemoved(int groupId) {
+ mInteractivityByGroupId.remove(groupId);
}
/**
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index e392c24..9ff98be 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -686,6 +686,8 @@
@Override
public void onWakefulnessChangedLocked(int groupId, int wakefulness, long eventTime,
int reason, int uid, int opUid, String opPackageName, String details) {
+ mWakefulnessChanging = true;
+ mDirty |= DIRTY_WAKEFULNESS;
if (wakefulness == WAKEFULNESS_AWAKE) {
// Kick user activity to prevent newly awake group from timing out instantly.
// The dream may end without user activity if the dream app crashes / is updated,
@@ -696,9 +698,8 @@
PowerManager.USER_ACTIVITY_EVENT_OTHER, flags, uid);
}
mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS;
+ mNotifier.onGroupWakefulnessChangeStarted(groupId, wakefulness, reason, eventTime);
updateGlobalWakefulnessLocked(eventTime, reason, uid, opUid, opPackageName, details);
- mNotifier.onPowerGroupWakefulnessChanged(groupId, wakefulness, reason,
- getGlobalWakefulnessLocked());
updatePowerStateLocked();
}
}
@@ -2152,7 +2153,7 @@
mDozeStartInProgress &= (newWakefulness == WAKEFULNESS_DOZING);
if (mNotifier != null) {
- mNotifier.onWakefulnessChangeStarted(newWakefulness, reason, eventTime);
+ mNotifier.onGlobalWakefulnessChangeStarted(newWakefulness, reason, eventTime);
}
mAttentionDetector.onWakefulnessChangeStarted(newWakefulness);
@@ -2163,15 +2164,6 @@
if (sQuiescent) {
mDirty |= DIRTY_QUIESCENT;
}
- PowerGroup defaultGroup = mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP);
- if (defaultGroup.getWakefulnessLocked() == WAKEFULNESS_DOZING) {
- // Workaround for b/187231320 where the AOD can get stuck in a "half on /
- // half off" state when a non-default-group VirtualDisplay causes the global
- // wakefulness to change to awake, even though the default display is
- // dozing. We set sandman summoned to restart dreaming to get it unstuck.
- // TODO(b/255688811) - fix this so that AOD never gets interrupted at all.
- defaultGroup.setSandmanSummonedLocked(true);
- }
break;
case WAKEFULNESS_ASLEEP:
@@ -2248,6 +2240,8 @@
@GuardedBy("mLock")
void onPowerGroupEventLocked(int event, PowerGroup powerGroup) {
+ mWakefulnessChanging = true;
+ mDirty |= DIRTY_WAKEFULNESS;
final int groupId = powerGroup.getGroupId();
if (event == DisplayGroupPowerChangeListener.DISPLAY_GROUP_REMOVED) {
mPowerGroups.delete(groupId);
@@ -2260,6 +2254,11 @@
// Kick user activity to prevent newly added group from timing out instantly.
userActivityNoUpdateLocked(powerGroup, mClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_OTHER, /* flags= */ 0, Process.SYSTEM_UID);
+ mNotifier.onGroupWakefulnessChangeStarted(groupId,
+ powerGroup.getWakefulnessLocked(), WAKE_REASON_DISPLAY_GROUP_ADDED,
+ mClock.uptimeMillis());
+ } else if (event == DisplayGroupPowerChangeListener.DISPLAY_GROUP_REMOVED) {
+ mNotifier.onGroupRemoved(groupId);
}
if (oldWakefulness != newWakefulness) {
diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java
index b6ab351..4bbca33 100644
--- a/services/core/java/com/android/server/tv/TvInputHal.java
+++ b/services/core/java/com/android/server/tv/TvInputHal.java
@@ -27,9 +27,6 @@
import android.util.SparseIntArray;
import android.view.Surface;
-import java.util.LinkedList;
-import java.util.Queue;
-
/**
* Provides access to the low-level TV input hardware abstraction layer.
*/
@@ -64,6 +61,8 @@
private static native TvStreamConfig[] nativeGetStreamConfigs(long ptr, int deviceId,
int generation);
private static native void nativeClose(long ptr);
+ private static native int nativeSetTvMessageEnabled(long ptr, int deviceId, int streamId,
+ int type, boolean enabled);
private final Object mLock = new Object();
private long mPtr = 0;
@@ -100,6 +99,25 @@
}
}
+ public int setTvMessageEnabled(int deviceId, TvStreamConfig streamConfig, int type,
+ boolean enabled) {
+ synchronized (mLock) {
+ if (mPtr == 0) {
+ return ERROR_NO_INIT;
+ }
+ int generation = mStreamConfigGenerations.get(deviceId, 0);
+ if (generation != streamConfig.getGeneration()) {
+ return ERROR_STALE_CONFIG;
+ }
+ if (nativeSetTvMessageEnabled(mPtr, deviceId, streamConfig.getStreamId(), type,
+ enabled) == 0) {
+ return SUCCESS;
+ } else {
+ return ERROR_UNKNOWN;
+ }
+ }
+ }
+
public int removeStream(int deviceId, TvStreamConfig streamConfig) {
synchronized (mLock) {
if (mPtr == 0) {
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 98dfb00..077f8d5 100755
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -459,9 +459,11 @@
private int findDeviceIdForInputIdLocked(String inputId) {
for (int i = 0; i < mConnections.size(); ++i) {
- Connection connection = mConnections.get(i);
- if (connection.getInfoLocked().getId().equals(inputId)) {
- return i;
+ int key = mConnections.keyAt(i);
+ Connection connection = mConnections.get(key);
+ if (connection != null && connection.getInfoLocked() != null
+ && connection.getInfoLocked().getId().equals(inputId)) {
+ return key;
}
}
return -1;
@@ -489,6 +491,27 @@
return configsList;
}
+ public boolean setTvMessageEnabled(String inputId, int type,
+ boolean enabled) {
+ synchronized (mLock) {
+ int deviceId = findDeviceIdForInputIdLocked(inputId);
+ if (deviceId < 0) {
+ Slog.e(TAG, "Invalid inputId : " + inputId);
+ return false;
+ }
+
+ Connection connection = mConnections.get(deviceId);
+ boolean success = true;
+ for (TvStreamConfig config : connection.getConfigsLocked()) {
+ success = success
+ && mHal.setTvMessageEnabled(deviceId, config, type, enabled)
+ == TvInputHal.SUCCESS;
+ }
+
+ return success;
+ }
+ }
+
/**
* Take a snapshot of the given TV input into the provided Surface.
*/
@@ -764,6 +787,7 @@
+ " mHardwareInfo: " + mHardwareInfo
+ ", mInfo: " + mInfo
+ ", mCallback: " + mCallback
+ + ", mHardware: " + mHardware
+ ", mConfigs: " + Arrays.toString(mConfigs)
+ ", mCallingUid: " + mCallingUid
+ ", mResolvedUserId: " + mResolvedUserId
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index fd203bb..88c9042 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -2154,6 +2154,9 @@
try {
synchronized (mLock) {
try {
+ final String inputId =
+ getSessionStateLocked(sessionToken, callingUid, userId).inputId;
+ mTvInputHardwareManager.setTvMessageEnabled(inputId, type, enabled);
getSessionLocked(sessionToken, callingUid, resolvedUserId)
.setTvMessageEnabled(type, enabled);
} catch (RemoteException | SessionNotFoundException e) {
@@ -2711,7 +2714,10 @@
.audioAddress("0")
.hdmiPortId(0)
.build();
- mTvInputHardwareManager.onDeviceAvailable(info, null);
+ TvStreamConfig[] configs = {
+ new TvStreamConfig.Builder().streamId(19001)
+ .generation(1).maxHeight(600).maxWidth(800).type(1).build()};
+ mTvInputHardwareManager.onDeviceAvailable(info, configs);
}
/**
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 51872b3..98d2d3d 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -803,6 +803,20 @@
protected WallpaperData mLastLockWallpaper;
private IWallpaperManagerCallback mKeyguardListener;
private boolean mWaitingForUnlock;
+
+ /**
+ * Flag set to true after reboot if the home wallpaper is waiting for the device to be unlocked.
+ * This happens for wallpapers that are not direct-boot aware; they can only be rendered after
+ * the user unlocks the device for the first time after a reboot. In the meantime, the default
+ * wallpaper is shown instead.
+ */
+ private boolean mHomeWallpaperWaitingForUnlock;
+
+ /**
+ * Flag set to true after reboot if the lock wallpaper is waiting for the device to be unlocked.
+ */
+ private boolean mLockWallpaperWaitingForUnlock;
+
private boolean mShuttingDown;
/**
@@ -1790,7 +1804,23 @@
public void onUnlockUser(final int userId) {
synchronized (mLock) {
if (mCurrentUserId == userId) {
- if (mWaitingForUnlock) {
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ if (mHomeWallpaperWaitingForUnlock) {
+ final WallpaperData systemWallpaper =
+ getWallpaperSafeLocked(userId, FLAG_SYSTEM);
+ switchWallpaper(systemWallpaper, null);
+ // TODO(b/278261563): call notifyCallbacksLocked inside switchWallpaper
+ notifyCallbacksLocked(systemWallpaper);
+ }
+ if (mLockWallpaperWaitingForUnlock) {
+ final WallpaperData lockWallpaper =
+ getWallpaperSafeLocked(userId, FLAG_LOCK);
+ switchWallpaper(lockWallpaper, null);
+ notifyCallbacksLocked(lockWallpaper);
+ }
+ }
+
+ if (mWaitingForUnlock && !mIsLockscreenLiveWallpaperEnabled) {
// the desired wallpaper is not direct-boot aware, load it now
final WallpaperData systemWallpaper =
getWallpaperSafeLocked(userId, FLAG_SYSTEM);
@@ -1845,13 +1875,23 @@
}
mCurrentUserId = userId;
systemWallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
- final WallpaperData tmpLockWallpaper = mLockWallpaperMap.get(userId);
- lockWallpaper = tmpLockWallpaper == null ? systemWallpaper : tmpLockWallpaper;
+
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ lockWallpaper = systemWallpaper.mWhich == (FLAG_LOCK | FLAG_SYSTEM)
+ ? systemWallpaper : getWallpaperSafeLocked(userId, FLAG_LOCK);
+ } else {
+ final WallpaperData tmpLockWallpaper = mLockWallpaperMap.get(userId);
+ lockWallpaper = tmpLockWallpaper == null ? systemWallpaper : tmpLockWallpaper;
+ }
+
// Not started watching yet, in case wallpaper data was loaded for other reasons.
if (systemWallpaper.wallpaperObserver == null) {
systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
systemWallpaper.wallpaperObserver.startWatching();
}
+ if (mIsLockscreenLiveWallpaperEnabled && lockWallpaper != systemWallpaper) {
+ switchWallpaper(lockWallpaper, null);
+ }
switchWallpaper(systemWallpaper, reply);
}
@@ -1870,6 +1910,11 @@
void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
synchronized (mLock) {
mWaitingForUnlock = false;
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ if ((wallpaper.mWhich & FLAG_SYSTEM) != 0) mHomeWallpaperWaitingForUnlock = false;
+ if ((wallpaper.mWhich & FLAG_LOCK) != 0) mLockWallpaperWaitingForUnlock = false;
+ }
+
final ComponentName cname = wallpaper.wallpaperComponent != null ?
wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
if (!bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
@@ -1882,6 +1927,11 @@
} catch (RemoteException ignored) {
}
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ onSwitchWallpaperFailLocked(wallpaper, reply, si);
+ return;
+ }
+
if (si == null) {
Slog.w(TAG, "Failure starting previous wallpaper; clearing");
clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, reply);
@@ -1899,6 +1949,43 @@
}
}
+ /**
+ * Fallback method if a wallpaper fails to load on boot or after a user switch.
+ * Only called if mIsLockscreenLiveWallpaperEnabled is true.
+ */
+ private void onSwitchWallpaperFailLocked(
+ WallpaperData wallpaper, IRemoteCallback reply, ServiceInfo serviceInfo) {
+
+ if (serviceInfo == null) {
+ Slog.w(TAG, "Failure starting previous wallpaper; clearing");
+
+ if (wallpaper.mWhich == (FLAG_LOCK | FLAG_SYSTEM)) {
+ clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
+ clearWallpaperLocked(false, FLAG_LOCK, wallpaper.userId, reply);
+ } else {
+ clearWallpaperLocked(false, wallpaper.mWhich, wallpaper.userId, reply);
+ }
+ return;
+ }
+ Slog.w(TAG, "Wallpaper isn't direct boot aware; using fallback until unlocked");
+ // We might end up persisting the current wallpaper data
+ // while locked, so pretend like the component was actually
+ // bound into place
+ wallpaper.wallpaperComponent = wallpaper.nextWallpaperComponent;
+ final WallpaperData fallback = new WallpaperData(wallpaper.userId, wallpaper.mWhich);
+
+ // files from the previous static wallpaper may still be stored in memory.
+ // delete them in order to show the default wallpaper.
+ if (wallpaper.wallpaperFile.exists()) {
+ wallpaper.wallpaperFile.delete();
+ wallpaper.cropFile.delete();
+ }
+
+ bindWallpaperComponentLocked(mImageWallpaper, true, false, fallback, reply);
+ if ((wallpaper.mWhich & FLAG_SYSTEM) != 0) mHomeWallpaperWaitingForUnlock = true;
+ if ((wallpaper.mWhich & FLAG_LOCK) != 0) mLockWallpaperWaitingForUnlock = true;
+ }
+
@Override
public void clearWallpaper(String callingPackage, int which, int userId) {
if (DEBUG) Slog.v(TAG, "clearWallpaper");
diff --git a/services/core/java/com/android/server/wm/AbsAppSnapshotController.java b/services/core/java/com/android/server/wm/AbsAppSnapshotController.java
index 32f7b96..5c929a9 100644
--- a/services/core/java/com/android/server/wm/AbsAppSnapshotController.java
+++ b/services/core/java/com/android/server/wm/AbsAppSnapshotController.java
@@ -239,7 +239,17 @@
}
return null;
}
- source.getBounds(mTmpRect);
+ mTmpRect.setEmpty();
+ if (source.mTransitionController.inFinishingTransition(source)) {
+ final Transition.ChangeInfo changeInfo = source.mTransitionController
+ .mFinishingTransition.mChanges.get(source);
+ if (changeInfo != null) {
+ mTmpRect.set(changeInfo.mAbsoluteBounds);
+ }
+ }
+ if (mTmpRect.isEmpty()) {
+ source.getBounds(mTmpRect);
+ }
mTmpRect.offsetTo(0, 0);
SurfaceControl[] excludeLayers;
final WindowState imeWindow = source.getDisplayContent().mInputMethodWindow;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f843b7c..78c066b 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -5296,6 +5296,10 @@
if (isCollecting) {
mTransitionController.collect(this);
} else {
+ // Failsafe to make sure that we show any activities that were incorrectly hidden
+ // during a transition. If this vis-change is a result of finishing, ignore it.
+ // Finish should only ever commit visibility=false, so we can check full containment
+ // rather than just direct membership.
inFinishingTransition = mTransitionController.inFinishingTransition(this);
if (!inFinishingTransition && !mDisplayContent.isSleeping()) {
Slog.e(TAG, "setVisibility=" + visible
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 4949ebc..3f4a775 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -755,4 +755,10 @@
/** Unregister a task stack listener so that it stops receiving callbacks. */;
public abstract void unregisterTaskStackListener(ITaskStackListener listener);
+
+ /**
+ * Gets the id of the display the activity was launched on.
+ * @param token The activity token.
+ */
+ public abstract int getDisplayId(IBinder token);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index b377032..1f4606b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5816,6 +5816,18 @@
}
@Override
+ public int getDisplayId(IBinder token) {
+ synchronized (mGlobalLock) {
+ ActivityRecord r = ActivityRecord.forTokenLocked(token);
+ if (r == null) {
+ throw new IllegalArgumentException(
+ "setFocusedActivity: No activity record matching token=" + token);
+ }
+ return r.getDisplayId();
+ }
+ }
+
+ @Override
public void registerScreenObserver(ScreenObserver observer) {
mScreenObservers.add(observer);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ef38e89..8bca106 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -6045,7 +6045,7 @@
static boolean alwaysCreateRootTask(int windowingMode, int activityType) {
// Always create a root task for fullscreen, freeform, and multi windowing
// modes so that we can manage visual ordering and return types correctly.
- return activityType == ACTIVITY_TYPE_STANDARD
+ return (activityType == ACTIVITY_TYPE_STANDARD || activityType == ACTIVITY_TYPE_RECENTS)
&& (windowingMode == WINDOWING_MODE_FULLSCREEN
|| windowingMode == WINDOWING_MODE_FREEFORM
|| windowingMode == WINDOWING_MODE_PINNED
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 747819e9..ce43628 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1882,6 +1882,12 @@
static final int DECOR_TYPES = Type.displayCutout() | Type.navigationBars();
+ /**
+ * The types that may affect display configuration. This excludes cutout because it is
+ * known from display info.
+ */
+ static final int CONFIG_TYPES = Type.statusBars() | Type.navigationBars();
+
private final DisplayContent mDisplayContent;
private final Info[] mInfoForRotation = new Info[4];
final Info mTmpInfo = new Info();
@@ -1921,7 +1927,7 @@
final DecorInsets.Info newInfo = mDecorInsets.mTmpInfo;
newInfo.update(mDisplayContent, rotation, dw, dh);
final DecorInsets.Info currentInfo = getDecorInsetsInfo(rotation, dw, dh);
- if (newInfo.mNonDecorFrame.equals(currentInfo.mNonDecorFrame)) {
+ if (newInfo.mConfigFrame.equals(currentInfo.mConfigFrame)) {
return false;
}
mDecorInsets.invalidate();
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index a5e652c..a3d233d 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -123,6 +123,7 @@
public final boolean isDefaultDisplay;
private final boolean mSupportAutoRotation;
+ private final boolean mAllowRotationResolver;
private final int mLidOpenRotation;
private final int mCarDockRotation;
private final int mDeskDockRotation;
@@ -272,6 +273,8 @@
mSupportAutoRotation =
mContext.getResources().getBoolean(R.bool.config_supportAutoRotation);
+ mAllowRotationResolver =
+ mContext.getResources().getBoolean(R.bool.config_allowRotationResolver);
mLidOpenRotation = readRotation(R.integer.config_lidOpenRotation);
mCarDockRotation = readRotation(R.integer.config_carDockRotation);
mDeskDockRotation = readRotation(R.integer.config_deskDockRotation);
@@ -2041,7 +2044,8 @@
@Override
public boolean isRotationResolverEnabled() {
- return mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
+ return mAllowRotationResolver
+ && mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
&& mCameraRotationMode == CAMERA_ROTATION_ENABLED
&& !mService.mPowerManager.isPowerSaveMode();
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
index 1fb97f9..2fb9869 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
@@ -114,7 +114,7 @@
* @see DisplayWindowPolicyController#keepActivityOnWindowFlagsChanged(ActivityInfo, int, int)
*/
boolean keepActivityOnWindowFlagsChanged(ActivityInfo aInfo, int flagChanges,
- int privateFlagChanges) {
+ int privateFlagChanges, int flagValues, int privateFlagValues) {
if (mDisplayWindowPolicyController == null) {
return true;
}
@@ -125,7 +125,7 @@
}
return mDisplayWindowPolicyController.keepActivityOnWindowFlagsChanged(
- aInfo, flagChanges, privateFlagChanges);
+ aInfo, flagValues, privateFlagValues);
}
/** Update the top activity and the uids of non-finishing activity */
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index b879d1a..eb639b6 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -362,15 +362,8 @@
private void invokeAnimationCancelled(String reason) {
ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "cancelAnimation(): reason=%s", reason);
- final boolean isKeyguardOccluded = mDisplayContent.isKeyguardOccluded();
-
try {
- EventLogTags.writeWmSetKeyguardOccluded(
- isKeyguardOccluded ? 1 : 0,
- 0 /* animate */,
- 0 /* transit */,
- "onAnimationCancelled");
- mRemoteAnimationAdapter.getRunner().onAnimationCancelled(isKeyguardOccluded);
+ mRemoteAnimationAdapter.getRunner().onAnimationCancelled();
} catch (RemoteException e) {
Slog.e(TAG, "Failed to notify cancel", e);
}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index abc9f8a..d531ad1 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -244,6 +244,16 @@
private IContainerFreezer mContainerFreezer = null;
private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
+ /**
+ * {@code true} if some other operation may have caused the originally-recorded state (in
+ * mChanges) to be dirty. This is usually due to finishTransition being called mid-collect;
+ * and, the reason that finish can alter the "start" state of other transitions is because
+ * setVisible(false) is deferred until then.
+ * Instead of adding this conditional, we could re-check always; but, this situation isn't
+ * common so it'd be wasted work.
+ */
+ boolean mPriorVisibilityMightBeDirty = false;
+
final TransitionController.Logger mLogger = new TransitionController.Logger();
/** Whether this transition was forced to play early (eg for a SLEEP signal). */
@@ -966,28 +976,30 @@
mController.mFinishingTransition = this;
if (mTransientHideTasks != null && !mTransientHideTasks.isEmpty()) {
- // Record all the now-hiding activities so that they are committed after
- // recalculating visibilities. We just use mParticipants because we can and it will
- // ensure proper reporting of `isInFinishTransition`.
- for (int i = 0; i < mTransientHideTasks.size(); ++i) {
- mTransientHideTasks.get(i).forAllActivities(r -> {
- // Only check leaf-tasks that were collected
- if (!mParticipants.contains(r.getTask())) return;
- // Only concern ourselves with anything that can become invisible
- if (!r.isVisible()) return;
- mParticipants.add(r);
- });
- }
// The transient hide tasks could be occluded now, e.g. returning to home. So trigger
// the update to make the activities in the tasks invisible-requested, then the next
// step can continue to commit the visibility.
mController.mAtm.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
0 /* configChanges */, true /* preserveWindows */);
+ // Record all the now-hiding activities so that they are committed. Just use
+ // mParticipants because we can avoid a new list this way.
+ for (int i = 0; i < mTransientHideTasks.size(); ++i) {
+ // Only worry about tasks that were actually hidden. Otherwise, we could end-up
+ // committing visibility for activity-level changes that aren't part of this
+ // transition.
+ if (mTransientHideTasks.get(i).isVisibleRequested()) continue;
+ mTransientHideTasks.get(i).forAllActivities(r -> {
+ // Only check leaf-tasks that were collected
+ if (!mParticipants.contains(r.getTask())) return;
+ mParticipants.add(r);
+ });
+ }
}
boolean hasParticipatedDisplay = false;
boolean hasVisibleTransientLaunch = false;
boolean enterAutoPip = false;
+ boolean committedSomeInvisible = false;
// Commit all going-invisible containers
for (int i = 0; i < mParticipants.size(); ++i) {
final WindowContainer<?> participant = mParticipants.valueAt(i);
@@ -1023,6 +1035,7 @@
}
ar.commitVisibility(false /* visible */, false /* performLayout */,
true /* fromTransition */);
+ committedSomeInvisible = true;
} else {
enterAutoPip = true;
}
@@ -1081,6 +1094,9 @@
}
}
}
+ if (committedSomeInvisible) {
+ mController.onCommittedInvisibles();
+ }
if (hasVisibleTransientLaunch) {
// Notify the change about the transient-below task if entering auto-pip.
@@ -1293,6 +1309,9 @@
// leftover order changes.
collectOrderChanges(mController.mWaitingTransitions.isEmpty());
+ if (mPriorVisibilityMightBeDirty) {
+ updatePriorVisibility();
+ }
// Resolve the animating targets from the participants.
mTargets = calculateTargets(mParticipants, mChanges);
// Check whether the participants were animated from back navigation.
@@ -1806,6 +1825,20 @@
}
}
+ private void updatePriorVisibility() {
+ for (int i = 0; i < mChanges.size(); ++i) {
+ final ChangeInfo chg = mChanges.valueAt(i);
+ // For task/activity, recalculate the current "real" visibility.
+ if (chg.mContainer.asActivityRecord() == null && chg.mContainer.asTask() == null) {
+ continue;
+ }
+ // This ONLY works in the visible -> invisible case (and is only needed for this case)
+ // because commitVisible(false) is deferred until finish.
+ if (!chg.mVisible) continue;
+ chg.mVisible = chg.mContainer.isVisible();
+ }
+ }
+
/**
* Under some conditions (eg. all visible targets within a parent container are transitioning
* the same way) the transition can be "promoted" to the parent container. This means an
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index b0feefe..7950eda 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -408,9 +408,9 @@
return false;
}
- /** Returns {@code true} if the `wc` is a participant of the finishing transition. */
+ /** Returns {@code true} if the finishing transition contains `wc`. */
boolean inFinishingTransition(WindowContainer<?> wc) {
- return mFinishingTransition != null && mFinishingTransition.mParticipants.contains(wc);
+ return mFinishingTransition != null && mFinishingTransition.isInTransition(wc);
}
/** @return {@code true} if a transition is running */
@@ -827,6 +827,16 @@
}
}
+ /** Called by {@link Transition#finishTransition} if it committed invisible to any activities */
+ void onCommittedInvisibles() {
+ if (mCollectingTransition != null) {
+ mCollectingTransition.mPriorVisibilityMightBeDirty = true;
+ }
+ for (int i = mWaitingTransitions.size() - 1; i >= 0; --i) {
+ mWaitingTransitions.get(i).mPriorVisibilityMightBeDirty = true;
+ }
+ }
+
private void validateStates() {
for (int i = 0; i < mStateValidators.size(); ++i) {
mStateValidators.get(i).run();
@@ -964,6 +974,7 @@
if (sync) {
info.setFlags(info.getFlags() | TransitionInfo.FLAG_SYNC);
}
+ transition.mAnimationTrack = track;
info.setTrack(track);
mTrackCount = Math.max(mTrackCount, track + 1);
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index f4a1765d..a5cdd0b 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -3594,8 +3594,11 @@
&& !mTransitionController.useShellTransitionsRotation()) {
if (deltaRotation != Surface.ROTATION_0) {
updateSurfaceRotation(t, deltaRotation, null /* positionLeash */);
+ t.setFixedTransformHint(mSurfaceControl,
+ getWindowConfiguration().getDisplayRotation());
} else if (deltaRotation != mLastDeltaRotation) {
t.setMatrix(mSurfaceControl, 1, 0, 0, 1);
+ t.unsetFixedTransformHint(mSurfaceControl);
}
}
mLastDeltaRotation = deltaRotation;
@@ -3839,7 +3842,8 @@
// This can still happen if WMCore starts a new transition when there is ongoing
// sync transaction from Shell. Please file a bug if it happens.
throw new IllegalStateException("Can't sync on 2 groups simultaneously"
- + " currentSyncId=" + mSyncGroup.mSyncId + " newSyncId=" + group.mSyncId);
+ + " currentSyncId=" + mSyncGroup.mSyncId + " newSyncId=" + group.mSyncId
+ + " wc=" + this);
}
mSyncGroup = group;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 40b8274..f9b6fc1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1831,7 +1831,7 @@
boolean needToSendNewConfiguration =
win.isVisibleRequestedOrAdding() && displayContent.updateOrientation();
- if (win.providesNonDecorInsets()) {
+ if (win.providesDisplayDecorInsets()) {
needToSendNewConfiguration |= displayPolicy.updateDecorInsetsInfo();
}
if (needToSendNewConfiguration) {
@@ -2274,7 +2274,7 @@
& WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED) != 0) {
win.mLayoutNeeded = true;
}
- if (layoutChanged && win.providesNonDecorInsets()) {
+ if (layoutChanged && win.providesDisplayDecorInsets()) {
configChanged = displayPolicy.updateDecorInsetsInfo();
}
if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
@@ -2290,14 +2290,24 @@
winAnimator.setColorSpaceAgnosticLocked((win.mAttrs.privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
}
- if (win.mActivityRecord != null
- && !displayContent.mDwpcHelper.keepActivityOnWindowFlagsChanged(
- win.mActivityRecord.info, flagChanges, privateFlagChanges)) {
- mH.sendMessage(mH.obtainMessage(H.REPARENT_TASK_TO_DEFAULT_DISPLAY,
- win.mActivityRecord.getTask()));
- Slog.w(TAG_WM, "Activity " + win.mActivityRecord + " window flag changed,"
- + " can't remain on display " + displayContent.getDisplayId());
- return 0;
+ // See if the DisplayWindowPolicyController wants to keep the activity on the window
+ if (displayContent.mDwpcHelper.hasController()
+ && win.mActivityRecord != null && (!win.mRelayoutCalled || flagChanges != 0
+ || privateFlagChanges != 0)) {
+ int newOrChangedFlags = !win.mRelayoutCalled ? win.mAttrs.flags : flagChanges;
+ int newOrChangedPrivateFlags =
+ !win.mRelayoutCalled ? win.mAttrs.privateFlags : privateFlagChanges;
+
+ if (!displayContent.mDwpcHelper.keepActivityOnWindowFlagsChanged(
+ win.mActivityRecord.info, newOrChangedFlags, newOrChangedPrivateFlags,
+ win.mAttrs.flags,
+ win.mAttrs.privateFlags)) {
+ mH.sendMessage(mH.obtainMessage(H.REPARENT_TASK_TO_DEFAULT_DISPLAY,
+ win.mActivityRecord.getTask()));
+ Slog.w(TAG_WM, "Activity " + win.mActivityRecord + " window flag changed,"
+ + " can't remain on display " + displayContent.getDisplayId());
+ return 0;
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 2920652..032f08a 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1834,13 +1834,13 @@
return (mPolicyVisibility & POLICY_VISIBILITY_ALL) == POLICY_VISIBILITY_ALL;
}
- boolean providesNonDecorInsets() {
+ boolean providesDisplayDecorInsets() {
if (mInsetsSourceProviders == null) {
return false;
}
for (int i = mInsetsSourceProviders.size() - 1; i >= 0; i--) {
final InsetsSource source = mInsetsSourceProviders.valueAt(i).getSource();
- if (source.getType() == WindowInsets.Type.navigationBars()) {
+ if ((source.getType() & DisplayPolicy.DecorInsets.CONFIG_TYPES) != 0) {
return true;
}
}
@@ -1980,19 +1980,16 @@
/**
* Like isOnScreen(), but we don't return true if the window is part
- * of a transition but has not yet started animating.
+ * of a transition that has not yet been started.
*/
boolean isReadyForDisplay() {
- if (!mHasSurface || mDestroying || !isVisibleByPolicy()) {
- return false;
- }
- if (mToken.waitingToShow && getDisplayContent().mAppTransition.isTransitionSet()
- && !isAnimating(TRANSITION | PARENTS, ANIMATION_TYPE_APP_TRANSITION)) {
+ if (mToken.waitingToShow && getDisplayContent().mAppTransition.isTransitionSet()) {
return false;
}
final boolean parentAndClientVisible = !isParentWindowHidden()
&& mViewVisibility == View.VISIBLE && mToken.isVisible();
- return parentAndClientVisible || isAnimating(TRANSITION | PARENTS, ANIMATION_TYPE_ALL);
+ return mHasSurface && isVisibleByPolicy() && !mDestroying
+ && (parentAndClientVisible || isAnimating(TRANSITION | PARENTS));
}
boolean isFullyTransparent() {
@@ -2507,13 +2504,13 @@
}
// Check if window provides non decor insets before clearing its provided insets.
- final boolean windowProvidesNonDecorInsets = providesNonDecorInsets();
+ final boolean windowProvidesDisplayDecorInsets = providesDisplayDecorInsets();
removeImmediately();
// Removing a visible window may affect the display orientation so just update it if
// needed. Also recompute configuration if it provides screen decor insets.
boolean needToSendNewConfiguration = wasVisible && displayContent.updateOrientation();
- if (windowProvidesNonDecorInsets) {
+ if (windowProvidesDisplayDecorInsets) {
needToSendNewConfiguration |=
displayContent.getDisplayPolicy().updateDecorInsetsInfo();
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index da54b15..4c5efef 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -596,6 +596,7 @@
.build();
t.setPosition(leash, mLastSurfacePosition.x, mLastSurfacePosition.y);
t.reparent(getSurfaceControl(), leash);
+ t.setFixedTransformHint(leash, getWindowConfiguration().getDisplayRotation());
mFixedRotationTransformLeash = leash;
updateSurfaceRotation(t, rotation, mFixedRotationTransformLeash);
return mFixedRotationTransformLeash;
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index cf57b33..369c974 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -2567,6 +2567,11 @@
im->setStylusPointerIconEnabled(enabled);
}
+static void nativeNotifyKeyGestureTimeoutsChanged(JNIEnv* env, jobject nativeImplObj) {
+ NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
+ im->getInputManager()->getDispatcher().requestRefreshConfiguration();
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod gInputManagerMethods[] = {
@@ -2663,6 +2668,7 @@
(void*)nativeSetStylusButtonMotionEventsEnabled},
{"getMouseCursorPosition", "()[F", (void*)nativeGetMouseCursorPosition},
{"setStylusPointerIconEnabled", "(Z)V", (void*)nativeSetStylusPointerIconEnabled},
+ {"notifyKeyGestureTimeoutsChanged", "()V", (void*)nativeNotifyKeyGestureTimeoutsChanged},
};
#define FIND_CLASS(var, className) \
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index a8d2f4e..a8806b5 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -84,23 +84,26 @@
return result;
}
+static int nativeSetTvMessageEnabled(JNIEnv* env, jclass clazz, jlong ptr, jint deviceId,
+ jint streamId, jint type, jboolean enabled) {
+ JTvInputHal* tvInputHal = (JTvInputHal*)ptr;
+ return tvInputHal->setTvMessageEnabled(deviceId, streamId, type, enabled);
+}
+
static void nativeClose(JNIEnv* env, jclass clazz, jlong ptr) {
JTvInputHal* tvInputHal = (JTvInputHal*)ptr;
delete tvInputHal;
}
static const JNINativeMethod gTvInputHalMethods[] = {
- /* name, signature, funcPtr */
- { "nativeOpen", "(Landroid/os/MessageQueue;)J",
- (void*) nativeOpen },
- { "nativeAddOrUpdateStream", "(JIILandroid/view/Surface;)I",
- (void*) nativeAddOrUpdateStream },
- { "nativeRemoveStream", "(JII)I",
- (void*) nativeRemoveStream },
- { "nativeGetStreamConfigs", "(JII)[Landroid/media/tv/TvStreamConfig;",
- (void*) nativeGetStreamConfigs },
- { "nativeClose", "(J)V",
- (void*) nativeClose },
+ /* name, signature, funcPtr */
+ {"nativeOpen", "(Landroid/os/MessageQueue;)J", (void*)nativeOpen},
+ {"nativeAddOrUpdateStream", "(JIILandroid/view/Surface;)I", (void*)nativeAddOrUpdateStream},
+ {"nativeRemoveStream", "(JII)I", (void*)nativeRemoveStream},
+ {"nativeGetStreamConfigs", "(JII)[Landroid/media/tv/TvStreamConfig;",
+ (void*)nativeGetStreamConfigs},
+ {"nativeSetTvMessageEnabled", "(JIIIZ)I", (void*)nativeSetTvMessageEnabled},
+ {"nativeClose", "(J)V", (void*)nativeClose},
};
#define FIND_CLASS(var, className) \
diff --git a/services/core/jni/tvinput/JTvInputHal.cpp b/services/core/jni/tvinput/JTvInputHal.cpp
index 98e6b19..6bb5217 100644
--- a/services/core/jni/tvinput/JTvInputHal.cpp
+++ b/services/core/jni/tvinput/JTvInputHal.cpp
@@ -144,6 +144,17 @@
return NO_ERROR;
}
+int JTvInputHal::setTvMessageEnabled(int deviceId, int streamId, int type, bool enabled) {
+ Mutex::Autolock autoLock(&mLock);
+ if (!mTvInput->setTvMessageEnabled(deviceId, streamId,
+ static_cast<AidlTvMessageEventType>(type), enabled)
+ .isOk()) {
+ ALOGE("Error in setTvMessageEnabled. device id:%d stream id:%d", deviceId, streamId);
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+}
+
const std::vector<AidlTvStreamConfig> JTvInputHal::getStreamConfigs(int deviceId) {
std::vector<AidlTvStreamConfig> list;
::ndk::ScopedAStatus status = mTvInput->getStreamConfigurations(deviceId, &list);
@@ -384,4 +395,15 @@
}
}
+::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::setTvMessageEnabled(int32_t deviceId,
+ int32_t streamId,
+ TvMessageEventType in_type,
+ bool enabled) {
+ if (mIsHidl) {
+ return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ } else {
+ return mAidlTvInput->setTvMessageEnabled(deviceId, streamId, in_type, enabled);
+ }
+}
+
} // namespace android
diff --git a/services/core/jni/tvinput/JTvInputHal.h b/services/core/jni/tvinput/JTvInputHal.h
index 984407a..e29da79 100644
--- a/services/core/jni/tvinput/JTvInputHal.h
+++ b/services/core/jni/tvinput/JTvInputHal.h
@@ -44,6 +44,8 @@
using ::aidl::android::hardware::tv::input::CableConnectionStatus;
using ::aidl::android::hardware::tv::input::TvInputEventType;
using ::aidl::android::hardware::tv::input::TvInputType;
+using ::aidl::android::hardware::tv::input::TvMessageEvent;
+using ::aidl::android::hardware::tv::input::TvMessageEventType;
using AidlAudioDevice = ::aidl::android::media::audio::common::AudioDevice;
using AidlAudioDeviceAddress = ::aidl::android::media::audio::common::AudioDeviceAddress;
@@ -53,6 +55,7 @@
using AidlTvInputDeviceInfo = ::aidl::android::hardware::tv::input::TvInputDeviceInfo;
using AidlTvInputEvent = ::aidl::android::hardware::tv::input::TvInputEvent;
using AidlTvMessageEvent = ::aidl::android::hardware::tv::input::TvMessageEvent;
+using AidlTvMessageEventType = ::aidl::android::hardware::tv::input::TvMessageEventType;
using AidlTvStreamConfig = ::aidl::android::hardware::tv::input::TvStreamConfig;
extern gTvInputHalClassInfoType gTvInputHalClassInfo;
@@ -69,6 +72,7 @@
static JTvInputHal* createInstance(JNIEnv* env, jobject thiz, const sp<Looper>& looper);
int addOrUpdateStream(int deviceId, int streamId, const sp<Surface>& surface);
+ int setTvMessageEnabled(int deviceId, int streamId, int type, bool enabled);
int removeStream(int deviceId, int streamId);
const std::vector<AidlTvStreamConfig> getStreamConfigs(int deviceId);
@@ -150,6 +154,8 @@
::ndk::ScopedAStatus openStream(int32_t in_deviceId, int32_t in_streamId,
AidlNativeHandle* _aidl_return);
::ndk::ScopedAStatus closeStream(int32_t in_deviceId, int32_t in_streamId);
+ ::ndk::ScopedAStatus setTvMessageEnabled(int32_t deviceId, int32_t streamId,
+ TvMessageEventType in_type, bool enabled);
private:
::ndk::ScopedAStatus hidlSetCallback(const std::shared_ptr<TvInputCallback>& in_callback);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
index 80100a9..c681b88 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
@@ -19,13 +19,13 @@
import android.app.admin.DevicePolicyCache;
import android.app.admin.DevicePolicyManager;
import android.os.UserHandle;
+import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -55,8 +55,7 @@
private final SparseIntArray mPermissionPolicy = new SparseIntArray();
@GuardedBy("mLock")
- private List<String> mLauncherShortcutOverrides =
- new ArrayList<>();
+ private ArrayMap<String, String> mLauncherShortcutOverrides = new ArrayMap<>();
/** Maps to {@code ActiveAdmin.mAdminCanGrantSensorsPermissions}. */
@@ -130,18 +129,20 @@
}
@Override
- public List<String> getLauncherShortcutOverrides() {
+ public Map<String, String> getLauncherShortcutOverrides() {
synchronized (mLock) {
- return new ArrayList<>(mLauncherShortcutOverrides);
+ return new ArrayMap<>(mLauncherShortcutOverrides);
}
}
/**
- * Sets a list of packages for which shortcuts should be replaced by their badged version.
+ * Sets a map of packages names to package names, for which all launcher shortcuts which
+ * match a key package name should be modified to launch the corresponding value package
+ * name in the managed profile. The overridden shortcut should be badged accordingly.
*/
- public void setLauncherShortcutOverrides(List<String> launcherShortcutOverrides) {
+ public void setLauncherShortcutOverrides(ArrayMap<String, String> launcherShortcutOverrides) {
synchronized (mLock) {
- mLauncherShortcutOverrides = new ArrayList<>(launcherShortcutOverrides);
+ mLauncherShortcutOverrides = new ArrayMap<>(launcherShortcutOverrides);
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index 415440b..cf49dcf 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -130,12 +130,11 @@
<V> void setLocalPolicy(
@NonNull PolicyDefinition<V> policyDefinition,
@NonNull EnforcingAdmin enforcingAdmin,
- @NonNull PolicyValue<V> value,
+ @Nullable PolicyValue<V> value,
int userId,
boolean skipEnforcePolicy) {
Objects.requireNonNull(policyDefinition);
Objects.requireNonNull(enforcingAdmin);
- Objects.requireNonNull(value);
synchronized (mLock) {
PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 40024f1..3908777 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -39,7 +39,6 @@
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_DISPLAY;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_FACTORY_RESET;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_FUN;
-import static android.Manifest.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCALE;
@@ -80,6 +79,7 @@
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WINDOWS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA;
import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS;
+import static android.Manifest.permission.MASTER_CLEAR;
import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.Manifest.permission.SET_TIME;
@@ -520,6 +520,7 @@
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.time.LocalDate;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -532,6 +533,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
+import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@@ -567,7 +569,15 @@
private static final int REQUEST_PROFILE_OFF_DEADLINE = 5572;
+ // Binary XML serializer doesn't support longer strings
+ private static final int MAX_POLICY_STRING_LENGTH = 65535;
+ // FrameworkParsingPackageUtils#MAX_FILE_NAME_SIZE, Android packages are used in dir names.
+ private static final int MAX_PACKAGE_NAME_LENGTH = 223;
+
private static final int MAX_PROFILE_NAME_LENGTH = 200;
+ private static final int MAX_LONG_SUPPORT_MESSAGE_LENGTH = 20000;
+ private static final int MAX_SHORT_SUPPORT_MESSAGE_LENGTH = 200;
+ private static final int MAX_ORG_NAME_LENGTH = 200;
private static final long MS_PER_DAY = TimeUnit.DAYS.toMillis(1);
@@ -863,7 +873,7 @@
// TODO(b/265683382) remove the flag after rollout.
private static final String KEEP_PROFILES_RUNNING_FLAG = "enable_keep_profiles_running";
- private static final boolean DEFAULT_KEEP_PROFILES_RUNNING_FLAG = false;
+ private static final boolean DEFAULT_KEEP_PROFILES_RUNNING_FLAG = true;
private static final String ENABLE_WORK_PROFILE_TELEPHONY_FLAG =
"enable_work_profile_telephony";
@@ -6040,7 +6050,7 @@
@Override
public void lockNow(int flags, String callerPackageName, boolean parent) {
CallerIdentity caller;
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
caller = getCallerIdentity(callerPackageName);
} else {
caller = getCallerIdentity();
@@ -6052,7 +6062,7 @@
ActiveAdmin admin;
// Make sure the caller has any active admin with the right policy or
// the required permission.
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
admin = enforcePermissionAndGetEnforcingAdmin(
/* admin= */ null,
/* permission= */ MANAGE_DEVICE_POLICY_LOCK,
@@ -7552,9 +7562,9 @@
boolean calledByProfileOwnerOnOrgOwnedDevice =
isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId());
if (isPolicyEngineForFinanceFlagEnabled()) {
- EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+ EnforcingAdmin enforcingAdmin = enforcePermissionsAndGetEnforcingAdmin(
/*admin=*/ null,
- /*permission= */ MANAGE_DEVICE_POLICY_WIPE_DATA,
+ /*permission=*/ new String[]{MANAGE_DEVICE_POLICY_WIPE_DATA, MASTER_CLEAR},
USES_POLICY_WIPE_DATA,
caller.getPackageName(),
factoryReset ? UserHandle.USER_ALL : getAffectedUser(calledOnParentInstance));
@@ -7576,12 +7586,13 @@
admin = getActiveAdminWithPolicyForUidLocked(/* who= */ null,
DeviceAdminInfo.USES_POLICY_WIPE_DATA, caller.getUid());
}
+ Preconditions.checkCallAuthorization(
+ (admin != null) || hasCallingOrSelfPermission(permission.MASTER_CLEAR),
+ "No active admin for user %d and caller %d does not hold MASTER_CLEAR "
+ + "permission",
+ caller.getUserId(), caller.getUid());
}
- Preconditions.checkCallAuthorization(
- (admin != null) || hasCallingOrSelfPermission(permission.MASTER_CLEAR),
- "No active admin for user %d and caller %d does not hold MASTER_CLEAR permission",
- caller.getUserId(), caller.getUid());
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_WIPE_DATA);
if (TextUtils.isEmpty(wipeReasonForUser)) {
@@ -7721,7 +7732,7 @@
}
private void clearLauncherShortcutOverrides() {
- mPolicyCache.setLauncherShortcutOverrides(new ArrayList<>());
+ mPolicyCache.setLauncherShortcutOverrides(new ArrayMap<>());
}
private void updateTelephonyCrossProfileIntentFilters(int parentUserId, int profileUserId,
@@ -7836,15 +7847,14 @@
} else {
// Explicit behaviour
if (factoryReset) {
- // TODO(b/254031494) Replace with new factory reset permission checks
- if (!isPermissionCheckFlagEnabled()) {
- boolean hasPermission = isDeviceOwnerUserId(userId)
- || (isOrganizationOwnedDeviceWithManagedProfile()
- && calledOnParentInstance);
- Preconditions.checkCallAuthorization(hasPermission,
- "Admin %s does not have permission to factory reset the device.",
- userId);
- }
+ EnforcingAdmin enforcingAdmin = enforcePermissionsAndGetEnforcingAdmin(
+ /*admin=*/ null,
+ /*permission=*/ new String[]{MANAGE_DEVICE_POLICY_WIPE_DATA,
+ MASTER_CLEAR},
+ USES_POLICY_WIPE_DATA,
+ adminPackage,
+ factoryReset ? UserHandle.USER_ALL :
+ getAffectedUser(calledOnParentInstance));
wipeDevice = true;
} else {
Preconditions.checkCallAuthorization(!isSystemUser,
@@ -8906,13 +8916,13 @@
}
CallerIdentity caller;
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
} else {
caller = getCallerIdentity(who);
}
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
// The effect of this policy is device-wide.
enforcePermission(SET_TIME, caller.getPackageName(), UserHandle.USER_ALL);
} else {
@@ -8940,13 +8950,13 @@
return false;
}
CallerIdentity caller;
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
} else {
caller = getCallerIdentity(who);
}
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
enforceCanQuery(SET_TIME, caller.getPackageName(), UserHandle.USER_ALL);
} else {
Objects.requireNonNull(who, "ComponentName is null");
@@ -8975,7 +8985,7 @@
caller = getCallerIdentity(who);
}
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
// The effect of this policy is device-wide.
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
who,
@@ -9015,13 +9025,13 @@
}
CallerIdentity caller;
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
} else {
caller = getCallerIdentity(who);
}
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
// The effect of this policy is device-wide.
enforceCanQuery(SET_TIME_ZONE, caller.getPackageName(), UserHandle.USER_ALL);
} else {
@@ -9324,7 +9334,7 @@
}
CallerIdentity caller;
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
} else {
caller = getCallerIdentity(who);
@@ -9334,7 +9344,7 @@
final int userHandle = caller.getUserId();
int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle;
synchronized (getLockObject()) {
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
// SUPPORT USES_POLICY_DISABLE_KEYGUARD_FEATURES
EnforcingAdmin admin = enforcePermissionAndGetEnforcingAdmin(
who, MANAGE_DEVICE_POLICY_KEYGUARD, caller.getPackageName(),
@@ -9413,7 +9423,7 @@
synchronized (getLockObject()) {
if (who != null) {
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
EnforcingAdmin admin = getEnforcingAdminForCaller(
who, who.getPackageName());
Integer features = mDevicePolicyEngine.getLocalPolicySetByAdmin(
@@ -9427,7 +9437,7 @@
}
}
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
Integer features = mDevicePolicyEngine.getResolvedPolicy(
PolicyDefinition.KEYGUARD_DISABLED_FEATURES,
affectedUserId);
@@ -11624,7 +11634,7 @@
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_APPLICATION_RESTRICTIONS);
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
who,
MANAGE_DEVICE_POLICY_APP_RESTRICTIONS,
@@ -11729,7 +11739,15 @@
}
Objects.requireNonNull(agent, "agent is null");
- int userHandle = UserHandle.getCallingUserId();
+
+ enforceMaxPackageNameLength(agent.getPackageName());
+ final String agentAsString = agent.flattenToString();
+ enforceMaxStringLength(agentAsString, "agent name");
+ if (args != null) {
+ enforceMaxStringLength(args, "args");
+ }
+
+ int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap;
if (isPermissionCheckFlagEnabled()) {
@@ -11746,7 +11764,7 @@
checkCanExecuteOrThrowUnsafe(
DevicePolicyManager.OPERATION_SET_TRUST_AGENT_CONFIGURATION);
- ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args));
+ ap.trustAgentInfos.put(agentAsString, new TrustAgentInfo(args));
saveSettingsLocked(userHandle);
}
}
@@ -12016,6 +12034,10 @@
isDeviceOwner(caller) || isProfileOwner(caller));
if (packageList != null) {
+ for (String pkg : packageList) {
+ enforceMaxPackageNameLength(pkg);
+ }
+
int userId = caller.getUserId();
final List<AccessibilityServiceInfo> enabledServices;
long id = mInjector.binderClearCallingIdentity();
@@ -12197,6 +12219,10 @@
}
if (packageList != null) {
+ for (String pkg : packageList) {
+ enforceMaxPackageNameLength(pkg);
+ }
+
List<InputMethodInfo> enabledImes = mInjector.binderWithCleanCallingIdentity(() ->
InputMethodManagerInternal.get().getEnabledInputMethodListAsUser(userId));
if (enabledImes != null) {
@@ -12214,17 +12240,22 @@
}
synchronized (getLockObject()) {
- ActiveAdmin admin;
- if (isPermissionCheckFlagEnabled()) {
- admin = enforcePermissionAndGetEnforcingAdmin(
- who, MANAGE_DEVICE_POLICY_INPUT_METHODS,
- caller.getPackageName(), userId).getActiveAdmin();
+ if (isPolicyEngineForFinanceFlagEnabled()) {
+ EnforcingAdmin admin = getEnforcingAdminForCaller(who, callerPackageName);
+ mDevicePolicyEngine.setLocalPolicy(
+ PolicyDefinition.PERMITTED_INPUT_METHODS,
+ admin,
+ packageList == null
+ ? null
+ : new StringSetPolicyValue(new HashSet<>(packageList)),
+ userId);
} else {
- admin = getParentOfAdminIfRequired(
- getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), calledOnParentInstance);
+ ActiveAdmin admin = getParentOfAdminIfRequired(
+ getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()),
+ calledOnParentInstance);
+ admin.permittedInputMethods = packageList;
+ saveSettingsLocked(caller.getUserId());
}
- admin.permittedInputMethods = packageList;
- saveSettingsLocked(caller.getUserId());
}
DevicePolicyEventLogger
@@ -12272,19 +12303,18 @@
}
synchronized (getLockObject()) {
- ActiveAdmin admin;
- if (isPermissionCheckFlagEnabled()) {
+ if (isPolicyEngineForFinanceFlagEnabled()) {
int affectedUser = calledOnParentInstance ? getProfileParentId(
caller.getUserId()) : caller.getUserId();
- admin = enforcePermissionAndGetEnforcingAdmin(
- who, MANAGE_DEVICE_POLICY_INPUT_METHODS, caller.getPackageName(),
- affectedUser).getActiveAdmin();
+ Set<String> policy = mDevicePolicyEngine.getResolvedPolicy(
+ PolicyDefinition.PERMITTED_INPUT_METHODS, affectedUser);
+ return policy == null ? null : new ArrayList<>(policy);
} else {
- admin = getParentOfAdminIfRequired(
+ ActiveAdmin admin = getParentOfAdminIfRequired(
getProfileOwnerOrDeviceOwnerLocked(
caller.getUserId()), calledOnParentInstance);
+ return admin.permittedInputMethods;
}
- return admin.permittedInputMethods;
}
}
@@ -12302,37 +12332,45 @@
}
private @Nullable List<String> getPermittedInputMethodsUnchecked(@UserIdInt int userId) {
- synchronized (getLockObject()) {
- List<String> result = null;
- // Only device or profile owners can have permitted lists set.
- List<ActiveAdmin> admins = getActiveAdminsForAffectedUserInclPermissionBasedAdminLocked(userId);
- for (ActiveAdmin admin: admins) {
- List<String> fromAdmin = admin.permittedInputMethods;
- if (fromAdmin != null) {
- if (result == null) {
- result = new ArrayList<String>(fromAdmin);
- } else {
- result.retainAll(fromAdmin);
- }
- }
- }
-
- // If we have a permitted list add all system input methods.
- if (result != null) {
- List<InputMethodInfo> imes = InputMethodManagerInternal
- .get().getInputMethodListAsUser(userId);
- if (imes != null) {
- for (InputMethodInfo ime : imes) {
- ServiceInfo serviceInfo = ime.getServiceInfo();
- ApplicationInfo applicationInfo = serviceInfo.applicationInfo;
- if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
- result.add(serviceInfo.packageName);
+ List<String> result = null;
+ if (isPolicyEngineForFinanceFlagEnabled()) {
+ Set<String> policy = mDevicePolicyEngine.getResolvedPolicy(
+ PolicyDefinition.PERMITTED_INPUT_METHODS, userId);
+ result = policy == null ? null : new ArrayList<>(policy);
+ } else {
+ synchronized (getLockObject()) {
+ // Only device or profile owners can have permitted lists set.
+ List<ActiveAdmin> admins =
+ getActiveAdminsForAffectedUserInclPermissionBasedAdminLocked(
+ userId);
+ for (ActiveAdmin admin : admins) {
+ List<String> fromAdmin = admin.permittedInputMethods;
+ if (fromAdmin != null) {
+ if (result == null) {
+ result = new ArrayList<String>(fromAdmin);
+ } else {
+ result.retainAll(fromAdmin);
}
}
}
}
- return result;
}
+
+ // If we have a permitted list add all system input methods.
+ if (result != null) {
+ List<InputMethodInfo> imes = InputMethodManagerInternal
+ .get().getInputMethodListAsUser(userId);
+ if (imes != null) {
+ for (InputMethodInfo ime : imes) {
+ ServiceInfo serviceInfo = ime.getServiceInfo();
+ ApplicationInfo applicationInfo = serviceInfo.applicationInfo;
+ if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ result.add(serviceInfo.packageName);
+ }
+ }
+ }
+ }
+ return result;
}
@Override
@@ -12347,17 +12385,38 @@
String.format(NOT_SYSTEM_CALLER_MSG,
"query if an input method is disabled by admin"));
- synchronized (getLockObject()) {
- ActiveAdmin admin = getParentOfAdminIfRequired(
- getActiveAdminUncheckedLocked(who, userHandle), calledOnParentInstance);
- if (admin == null) {
- return false;
+ if (isPolicyEngineForFinanceFlagEnabled()) {
+ int affectedUser = calledOnParentInstance ? getProfileParentId(userHandle) : userHandle;
+ Map<EnforcingAdmin, PolicyValue<Set<String>>> policies =
+ mDevicePolicyEngine.getLocalPoliciesSetByAdmins(
+ PolicyDefinition.PERMITTED_INPUT_METHODS, affectedUser);
+ EnforcingAdmin admin = null;
+ for (EnforcingAdmin a : policies.keySet()) {
+ if (a.getPackageName().equals(who.getPackageName())) {
+ if (policies.get(a).getValue() == null) {
+ return true;
+ } else {
+ return checkPackagesInPermittedListOrSystem(
+ Collections.singletonList(packageName),
+ new ArrayList<>(policies.get(a).getValue()), affectedUser);
+ }
+ }
}
- if (admin.permittedInputMethods == null) {
- return true;
+ // Admin didn't set a policy
+ return false;
+ } else {
+ synchronized (getLockObject()) {
+ ActiveAdmin admin = getParentOfAdminIfRequired(
+ getActiveAdminUncheckedLocked(who, userHandle), calledOnParentInstance);
+ if (admin == null) {
+ return false;
+ }
+ if (admin.permittedInputMethods == null) {
+ return true;
+ }
+ return checkPackagesInPermittedListOrSystem(Collections.singletonList(packageName),
+ admin.permittedInputMethods, userHandle);
}
- return checkPackagesInPermittedListOrSystem(Collections.singletonList(packageName),
- admin.permittedInputMethods, userHandle);
}
}
@@ -13000,7 +13059,7 @@
String packageName) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
EnforcingAdmin enforcingAdmin = enforceCanQueryAndGetEnforcingAdmin(
who,
MANAGE_DEVICE_POLICY_APP_RESTRICTIONS,
@@ -13070,7 +13129,7 @@
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
ActiveAdmin admin;
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
who,
MANAGE_DEVICE_POLICY_PACKAGE_STATE,
@@ -13167,7 +13226,7 @@
public boolean isPackageSuspended(ComponentName who, String callerPackage, String packageName) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
enforcePermission(
MANAGE_DEVICE_POLICY_PACKAGE_STATE,
caller.getPackageName(),
@@ -13773,7 +13832,7 @@
boolean hidden, boolean parent) {
CallerIdentity caller = getCallerIdentity(who, callerPackage);
final int userId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId();
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
// TODO: We need to ensure the delegate with DELEGATION_PACKAGE_ACCESS can do this
enforcePermission(MANAGE_DEVICE_POLICY_PACKAGE_STATE, caller.getPackageName(), userId);
} else {
@@ -13792,7 +13851,7 @@
boolean result;
synchronized (getLockObject()) {
if (parent) {
- if (!isPolicyEngineForFinanceFlagEnabled()) {
+ if (!isPermissionCheckFlagEnabled()) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(
caller.getUserId()) && isManagedProfile(caller.getUserId()));
@@ -13809,7 +13868,7 @@
Slogf.v(LOG_TAG, "calling pm.setApplicationHiddenSettingAsUser(%s, %b, %d)",
packageName, hidden, userId);
}
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
EnforcingAdmin admin = getEnforcingAdminForCaller(who, callerPackage);
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.APPLICATION_HIDDEN(packageName),
@@ -13848,7 +13907,7 @@
String packageName, boolean parent) {
CallerIdentity caller = getCallerIdentity(who, callerPackage);
int userId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId();
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
// TODO: Also support DELEGATION_PACKAGE_ACCESS
enforcePermission(MANAGE_DEVICE_POLICY_PACKAGE_STATE, caller.getPackageName(), userId);
} else {
@@ -13860,7 +13919,7 @@
synchronized (getLockObject()) {
if (parent) {
- if (!isPolicyEngineForFinanceFlagEnabled()) {
+ if (!isPermissionCheckFlagEnabled()) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId())
&& isManagedProfile(caller.getUserId()));
@@ -14048,14 +14107,17 @@
if (!mHasFeature) {
return;
}
+
+ enforceMaxStringLength(accountType, "account type");
+
CallerIdentity caller;
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
} else {
caller = getCallerIdentity(who);
}
synchronized (getLockObject()) {
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
int affectedUser = getAffectedUser(parent);
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
who,
@@ -14118,7 +14180,7 @@
CallerIdentity caller;
Preconditions.checkArgumentNonnegative(userId, "Invalid userId");
final ArraySet<String> resultSet = new ArraySet<>();
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
int affectedUser = parent ? getProfileParentId(userId) : userId;
caller = getCallerIdentity(callerPackageName);
if (!hasPermission(MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT,
@@ -14738,6 +14800,10 @@
public void setLockTaskPackages(ComponentName who, String callerPackageName, String[] packages)
throws SecurityException {
Objects.requireNonNull(packages, "packages is null");
+ for (String pkg : packages) {
+ enforceMaxPackageNameLength(pkg);
+ }
+
CallerIdentity caller;
if (isPolicyEngineForFinanceFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
@@ -15485,12 +15551,12 @@
public boolean setStatusBarDisabled(ComponentName who, String callerPackageName,
boolean disabled) {
CallerIdentity caller;
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
} else {
caller = getCallerIdentity(who);
}
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
enforcePermission(MANAGE_DEVICE_POLICY_STATUS_BAR, caller.getPackageName(),
UserHandle.USER_ALL);
} else {
@@ -15501,7 +15567,7 @@
int userId = caller.getUserId();
synchronized (getLockObject()) {
- if (!isPolicyEngineForFinanceFlagEnabled()) {
+ if (!isPermissionCheckFlagEnabled()) {
Preconditions.checkCallAuthorization(isUserAffiliatedWithDeviceLocked(userId),
"Admin " + who + " is neither the device owner or affiliated "
+ "user's profile owner.");
@@ -15560,7 +15626,7 @@
@Override
public boolean isStatusBarDisabled(String callerPackage) {
final CallerIdentity caller = getCallerIdentity(callerPackage);
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
enforceCanQuery(
MANAGE_DEVICE_POLICY_STATUS_BAR, caller.getPackageName(), caller.getUserId());
} else {
@@ -15570,7 +15636,7 @@
int userId = caller.getUserId();
synchronized (getLockObject()) {
- if (!isPolicyEngineForFinanceFlagEnabled()) {
+ if (!isPermissionCheckFlagEnabled()) {
Preconditions.checkCallAuthorization(isUserAffiliatedWithDeviceLocked(userId),
"Admin " + callerPackage
+ " is neither the device owner or affiliated user's profile owner.");
@@ -16730,7 +16796,7 @@
}
}
EnforcingAdmin enforcingAdmin;
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
admin,
MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
@@ -16901,7 +16967,7 @@
public int getPermissionGrantState(ComponentName admin, String callerPackage,
String packageName, String permission) throws RemoteException {
final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
enforceCanQuery(MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, caller.getPackageName(),
caller.getUserId());
} else {
@@ -17340,6 +17406,8 @@
CallerIdentity caller;
ActiveAdmin admin;
+ message = truncateIfLonger(message, MAX_SHORT_SUPPORT_MESSAGE_LENGTH);
+
if (isPermissionCheckFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
@@ -17400,6 +17468,9 @@
if (!mHasFeature) {
return;
}
+
+ message = truncateIfLonger(message, MAX_LONG_SUPPORT_MESSAGE_LENGTH);
+
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
synchronized (getLockObject()) {
@@ -17564,6 +17635,8 @@
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
}
+ text = truncateIfLonger(text, MAX_ORG_NAME_LENGTH);
+
synchronized (getLockObject()) {
if (!isPermissionCheckFlagEnabled()) {
admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
@@ -17844,9 +17917,8 @@
throw new IllegalArgumentException("ids must not be null");
}
for (String id : ids) {
- if (TextUtils.isEmpty(id)) {
- throw new IllegalArgumentException("ids must not contain empty string");
- }
+ Preconditions.checkArgument(!TextUtils.isEmpty(id), "ids must not have empty string");
+ enforceMaxStringLength(id, "affiliation id");
}
final Set<String> affiliationIds = new ArraySet<>(ids);
@@ -19033,14 +19105,14 @@
throw new IllegalArgumentException("token must be at least 32-byte long");
}
CallerIdentity caller;
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
caller = getCallerIdentity(admin, callerPackageName);
} else {
caller = getCallerIdentity(admin);
}
final int userId = caller.getUserId();
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
admin,
MANAGE_DEVICE_POLICY_RESET_PASSWORD,
@@ -19096,7 +19168,7 @@
return false;
}
CallerIdentity caller;
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
caller = getCallerIdentity(admin, callerPackageName);
} else {
caller = getCallerIdentity(admin);
@@ -19104,7 +19176,7 @@
final int userId = caller.getUserId();
boolean result = false;
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
admin,
MANAGE_DEVICE_POLICY_RESET_PASSWORD,
@@ -19143,14 +19215,14 @@
return false;
}
CallerIdentity caller;
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
caller = getCallerIdentity(admin, callerPackageName);
} else {
caller = getCallerIdentity(admin);
}
int userId = caller.getUserId();
- if (isPolicyEngineForFinanceFlagEnabled()) {
+ if (isPermissionCheckFlagEnabled()) {
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
admin,
MANAGE_DEVICE_POLICY_RESET_PASSWORD,
@@ -19359,6 +19431,9 @@
"Provided administrator and target are the same object.");
Preconditions.checkArgument(!admin.getPackageName().equals(target.getPackageName()),
"Provided administrator and target have the same package name.");
+ if (bundle != null) {
+ enforceMaxStringLength(bundle, "bundle");
+ }
final CallerIdentity caller = getCallerIdentity(admin);
Preconditions.checkCallAuthorization(
@@ -20215,9 +20290,20 @@
}
private boolean isLockTaskFeatureEnabled(int lockTaskFeature) throws RemoteException {
- //TODO(b/175285301): Explicitly get the user's identity to check.
- int lockTaskFeatures =
- getUserData(getCurrentForegroundUserId()).mLockTaskFeatures;
+ int lockTaskFeatures = 0;
+ if (isPolicyEngineForFinanceFlagEnabled()) {
+ LockTaskPolicy policy = mDevicePolicyEngine.getResolvedPolicy(
+ PolicyDefinition.LOCK_TASK, getCurrentForegroundUserId());
+ lockTaskFeatures = policy == null
+ // We default on the power button menu, in order to be consistent with pre-P
+ // behaviour.
+ ? DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS
+ : policy.getFlags();
+ } else {
+ //TODO(b/175285301): Explicitly get the user's identity to check.
+ lockTaskFeatures =
+ getUserData(getCurrentForegroundUserId()).mLockTaskFeatures;
+ }
return (lockTaskFeatures & lockTaskFeature) == lockTaskFeature;
}
@@ -21602,7 +21688,7 @@
}
copyAccount(targetUser, sourceUser, accountToMigrate, callerPackage);
if (!keepAccountMigrated) {
- removeAccount(accountToMigrate);
+ removeAccount(accountToMigrate, sourceUserId);
}
}
@@ -21646,9 +21732,10 @@
.write();
}
- private void removeAccount(Account account) {
- final AccountManager accountManager =
- mContext.getSystemService(AccountManager.class);
+ private void removeAccount(Account account, @UserIdInt int sourceUserId) {
+ final AccountManager accountManager = mContext.createContextAsUser(
+ UserHandle.of(sourceUserId), /* flags= */ 0)
+ .getSystemService(AccountManager.class);
final AccountManagerFuture<Bundle> bundle = accountManager.removeAccount(account,
null, null /* callback */, null /* handler */);
try {
@@ -23180,6 +23267,28 @@
}
/**
+ * Checks if the calling process has been granted permission to apply a device policy on a
+ * specific user. Only one permission provided in the list needs to be granted to pass this
+ * check.
+ * The given permissions will be checked along with their associated cross-user permissions if
+ * they exist and the target user is different to the calling user.
+ * Returns an {@link EnforcingAdmin} for the caller.
+ *
+ * @param admin the component name of the admin.
+ * @param callerPackageName The package name of the calling application.
+ * @param permissions The names of the permissions being checked.
+ * @param deviceAdminPolicy The userId of the user which the caller needs permission to act on.
+ * @throws SecurityException if the caller has not been granted the given permission,
+ * the associated cross-user permission if the caller's user is different to the target user.
+ */
+ private EnforcingAdmin enforcePermissionsAndGetEnforcingAdmin(@Nullable ComponentName admin,
+ String[] permissions, int deviceAdminPolicy, String callerPackageName,
+ int targetUserId) {
+ enforcePermissions(permissions, deviceAdminPolicy, callerPackageName, targetUserId);
+ return getEnforcingAdminForCaller(admin, callerPackageName);
+ }
+
+ /**
* Checks whether the calling process has been granted permission to query a device policy on
* a specific user.
* The given permission will be checked along with its associated cross-user permission if it
@@ -23225,12 +23334,13 @@
/**
* Checks if the calling process has been granted permission to apply a device policy on a
- * specific user.
- * The given permission will be checked along with its associated cross-user permission if it
- * exists and the target user is different to the calling user.
+ * specific user. Only one permission provided in the list needs to be granted to pass this
+ * check.
+ * The given permissions will be checked along with their associated cross-user permissions if
+ * they exists and the target user is different to the calling user.
*
* @param callerPackageName The package name of the calling application.
- * @param permission The name of the permission being checked.
+ * @param permissions The names of the permissions being checked.
* @param targetUserId The userId of the user which the caller needs permission to act on.
* @throws SecurityException if the caller has not been granted the given permission,
* the associated cross-user permission if the caller's user is different to the target user.
@@ -23295,6 +23405,27 @@
}
/**
+ * Checks if the calling process has been granted permission to apply a device policy on a
+ * specific user.
+ * The given permission will be checked along with its associated cross-user permission if it
+ * exists and the target user is different to the calling user.
+ *
+ * @param callerPackageName The package name of the calling application.
+ * @param adminPolicy The admin policy that should grant holders permission.
+ * @param permission The name of the permission being checked.
+ * @param targetUserId The userId of the user which the caller needs permission to act on.
+ * @throws SecurityException if the caller has not been granted the given permission,
+ * the associated cross-user permission if the caller's user is different to the target user.
+ */
+ private void enforcePermissions(String[] permissions, int adminPolicy,
+ String callerPackageName, int targetUserId) throws SecurityException {
+ if (hasAdminPolicy(adminPolicy, callerPackageName)) {
+ return;
+ }
+ enforcePermissions(permissions, callerPackageName, targetUserId);
+ }
+
+ /**
* Checks whether the calling process has been granted permission to query a device policy on
* a specific user.
* The given permission will be checked along with its associated cross-user permission if it
@@ -23421,7 +23552,8 @@
// Check for non-DPC active admins.
admin = getActiveAdminForCaller(who, caller);
if (admin != null) {
- return EnforcingAdmin.createDeviceAdminEnforcingAdmin(who, userId, admin);
+ return EnforcingAdmin.createDeviceAdminEnforcingAdmin(admin.info.getComponent(), userId,
+ admin);
}
admin = getUserData(userId).createOrGetPermissionBasedAdmin(userId);
return EnforcingAdmin.createEnforcingAdmin(caller.getPackageName(), userId, admin);
@@ -23709,15 +23841,14 @@
private void updateDialerAndSmsManagedShortcutsOverrideCache(
String defaultDialerPackageName, String defaultSmsPackageName) {
-
- List<String> shortcutOverrides = new ArrayList<>();
+ ArrayMap<String, String> shortcutOverrides = new ArrayMap<>();
if (defaultDialerPackageName != null) {
- shortcutOverrides.add(defaultDialerPackageName);
+ shortcutOverrides.put(defaultDialerPackageName, defaultDialerPackageName);
}
if (defaultSmsPackageName != null) {
- shortcutOverrides.add(defaultSmsPackageName);
+ shortcutOverrides.put(defaultSmsPackageName, defaultSmsPackageName);
}
mPolicyCache.setLauncherShortcutOverrides(shortcutOverrides);
}
@@ -23782,6 +23913,7 @@
public DevicePolicyState getDevicePolicyState() {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
+
return mInjector.binderWithCleanCallingIdentity(mDevicePolicyEngine::getDevicePolicyState);
}
@@ -24046,6 +24178,53 @@
});
}
+ /**
+ * Truncates char sequence to maximum length, nulls are ignored.
+ */
+ private static CharSequence truncateIfLonger(CharSequence input, int maxLength) {
+ return input == null || input.length() <= maxLength
+ ? input
+ : input.subSequence(0, maxLength);
+ }
+
+ /**
+ * Throw if string argument is too long to be serialized.
+ */
+ private static void enforceMaxStringLength(String str, String argName) {
+ Preconditions.checkArgument(
+ str.length() <= MAX_POLICY_STRING_LENGTH, argName + " loo long");
+ }
+
+ private static void enforceMaxPackageNameLength(String pkg) {
+ Preconditions.checkArgument(
+ pkg.length() <= MAX_PACKAGE_NAME_LENGTH, "Package name too long");
+ }
+
+ /**
+ * Throw if persistable bundle contains any string that we can't serialize.
+ */
+ private static void enforceMaxStringLength(PersistableBundle bundle, String argName) {
+ // Persistable bundles can have other persistable bundles as values, traverse with a queue.
+ Queue<PersistableBundle> queue = new ArrayDeque<>();
+ queue.add(bundle);
+ while (!queue.isEmpty()) {
+ PersistableBundle current = queue.remove();
+ for (String key : current.keySet()) {
+ enforceMaxStringLength(key, "key in " + argName);
+ Object value = current.get(key);
+ if (value instanceof String) {
+ enforceMaxStringLength((String) value, "string value in " + argName);
+ } else if (value instanceof String[]) {
+ for (String str : (String[]) value) {
+ enforceMaxStringLength(str, "string value in " + argName);
+ }
+ } else if (value instanceof PersistableBundle) {
+ queue.add((PersistableBundle) value);
+ }
+ }
+ }
+ }
+
private ActiveAdmin getActiveAdminForCaller(@Nullable ComponentName who,
CallerIdentity caller) {
synchronized (getLockObject()) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
index 638596b..43a2c9b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
@@ -308,6 +308,13 @@
DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY, accountType));
}
+ static PolicyDefinition<Set<String>> PERMITTED_INPUT_METHODS = new PolicyDefinition<>(
+ new NoArgsPolicyKey(DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY),
+ new MostRecent<>(),
+ POLICY_FLAG_LOCAL_ONLY_POLICY,
+ (Set<String> value, Context context, Integer userId, PolicyKey policyKey) -> true,
+ new StringSetPolicySerializer());
+
private static final Map<String, PolicyDefinition<?>> POLICY_DEFINITIONS = new HashMap<>();
private static Map<String, Integer> USER_RESTRICTION_FLAGS = new HashMap<>();
@@ -333,6 +340,8 @@
GENERIC_APPLICATION_HIDDEN);
POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY,
GENERIC_ACCOUNT_MANAGEMENT_DISABLED);
+ POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY,
+ PERMITTED_INPUT_METHODS);
// User Restriction Policies
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MODIFY_ACCOUNTS, /* flags= */ 0);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java
index 741f209..dd4c6af 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java
@@ -67,9 +67,8 @@
/**
* Returns {@code true} if the resolved policy has changed, {@code false} otherwise.
*/
- boolean addPolicy(@NonNull EnforcingAdmin admin, @NonNull PolicyValue<V> policy) {
+ boolean addPolicy(@NonNull EnforcingAdmin admin, @Nullable PolicyValue<V> policy) {
Objects.requireNonNull(admin);
- Objects.requireNonNull(policy);
//LinkedHashMap doesn't update the insertion order of existing keys, removing the existing
// key will cause it to update.
@@ -89,9 +88,9 @@
* Returns {@code true} if the resolved policy has changed, {@code false} otherwise.
*/
boolean addPolicy(
- @NonNull EnforcingAdmin admin, @NonNull PolicyValue<V> policy,
+ @NonNull EnforcingAdmin admin, @Nullable PolicyValue<V> policy,
LinkedHashMap<EnforcingAdmin, PolicyValue<V>> globalPoliciesSetByAdmins) {
- mPoliciesSetByAdmins.put(Objects.requireNonNull(admin), Objects.requireNonNull(policy));
+ mPoliciesSetByAdmins.put(Objects.requireNonNull(admin), policy);
return resolvePolicy(globalPoliciesSetByAdmins);
}
@@ -210,10 +209,12 @@
for (EnforcingAdmin admin : mPoliciesSetByAdmins.keySet()) {
serializer.startTag(/* namespace= */ null, TAG_ADMIN_POLICY_ENTRY);
- serializer.startTag(/* namespace= */ null, TAG_POLICY_VALUE_ENTRY);
- mPolicyDefinition.savePolicyValueToXml(
- serializer, mPoliciesSetByAdmins.get(admin).getValue());
- serializer.endTag(/* namespace= */ null, TAG_POLICY_VALUE_ENTRY);
+ if (mPoliciesSetByAdmins.get(admin) != null) {
+ serializer.startTag(/* namespace= */ null, TAG_POLICY_VALUE_ENTRY);
+ mPolicyDefinition.savePolicyValueToXml(
+ serializer, mPoliciesSetByAdmins.get(admin).getValue());
+ serializer.endTag(/* namespace= */ null, TAG_POLICY_VALUE_ENTRY);
+ }
serializer.startTag(/* namespace= */ null, TAG_ENFORCING_ADMIN_ENTRY);
admin.saveToXml(serializer);
@@ -250,7 +251,7 @@
break;
}
}
- if (admin != null && value != null) {
+ if (admin != null) {
policiesSetByAdmins.put(admin, value);
} else {
Log.e(TAG, "Error Parsing TAG_ADMIN_POLICY_ENTRY");
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index a5adf3f..f1d4de9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -54,6 +54,7 @@
import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_HIGH;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_ALLOW_LIST;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT;
+import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_LISTENER;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION;
@@ -2728,6 +2729,66 @@
}
@Test
+ public void exactListenerBinderCallWithoutPermissionWithoutAllowlist() throws RemoteException {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+ mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true);
+
+ mockScheduleExactAlarmState(false);
+ mockUseExactAlarmState(false);
+ when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(false);
+
+ final IAlarmListener listener = getNewListener(() -> {});
+ mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
+ 0, null, listener, "test-tag", null, null);
+
+ verify(mService, never()).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID);
+ verify(mService, never()).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE,
+ TEST_CALLING_UID);
+ verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());
+
+ final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L),
+ isNull(), eq(listener), eq("test-tag"), eq(FLAG_STANDALONE), isNull(), isNull(),
+ eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(),
+ eq(EXACT_ALLOW_REASON_LISTENER));
+
+ final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue());
+ final int type = idleOptions.getTemporaryAppAllowlistType();
+ assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
+ }
+
+ @Test
+ public void exactAllowWhileIdleListenerBinderCallWithoutPermissionWithoutAllowlist()
+ throws RemoteException {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+ mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true);
+
+ mockScheduleExactAlarmState(false);
+ mockUseExactAlarmState(false);
+ when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(false);
+
+ final IAlarmListener listener = getNewListener(() -> {});
+ mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
+ FLAG_ALLOW_WHILE_IDLE, null, listener, "test-tag", null, null);
+
+ verify(mService, never()).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID);
+ verify(mService, never()).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE,
+ TEST_CALLING_UID);
+ verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());
+
+ final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L),
+ isNull(), eq(listener), eq("test-tag"),
+ eq(FLAG_STANDALONE | FLAG_ALLOW_WHILE_IDLE_COMPAT), isNull(), isNull(),
+ eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(),
+ eq(EXACT_ALLOW_REASON_LISTENER));
+
+ final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue());
+ final int type = idleOptions.getTemporaryAppAllowlistType();
+ assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
+ }
+
+ @Test
public void inexactAllowWhileIdleBinderCall() throws RemoteException {
// Both permission and power exemption status don't matter for these alarms.
// We only want to test that the flags and idleOptions are correct.
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index 3fb7fb4..acfea85 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -40,6 +40,7 @@
import static com.android.server.am.BroadcastQueueTest.getUidForPackage;
import static com.android.server.am.BroadcastQueueTest.makeManifestReceiver;
import static com.android.server.am.BroadcastQueueTest.withPriority;
+import static com.android.server.am.BroadcastRecord.isReceiverEquals;
import static com.google.common.truth.Truth.assertThat;
@@ -49,13 +50,16 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import android.annotation.NonNull;
@@ -116,6 +120,7 @@
TestLooperManager mLooper;
BroadcastConstants mConstants;
+ private BroadcastSkipPolicy mSkipPolicy;
BroadcastQueueModernImpl mImpl;
BroadcastProcessQueue mHead;
@@ -139,29 +144,18 @@
mConstants.DELAY_NORMAL_MILLIS = 10_000;
mConstants.DELAY_CACHED_MILLIS = 120_000;
- final BroadcastSkipPolicy emptySkipPolicy = new BroadcastSkipPolicy(mAms) {
- public boolean shouldSkip(BroadcastRecord r, Object o) {
- // Ignored
- return false;
- }
- public String shouldSkipMessage(BroadcastRecord r, Object o) {
- // Ignored
- return null;
- }
- public boolean disallowBackgroundStart(BroadcastRecord r) {
- // Ignored
- return false;
- }
- };
+ mSkipPolicy = spy(new BroadcastSkipPolicy(mAms));
+ doReturn(null).when(mSkipPolicy).shouldSkipMessage(any(), any());
+ doReturn(false).when(mSkipPolicy).disallowBackgroundStart(any());
+
final BroadcastHistory emptyHistory = new BroadcastHistory(mConstants) {
public void addBroadcastToHistoryLocked(BroadcastRecord original) {
// Ignored
}
};
-
mImpl = new BroadcastQueueModernImpl(mAms, mHandlerThread.getThreadHandler(),
- mConstants, mConstants, emptySkipPolicy, emptyHistory);
+ mConstants, mConstants, mSkipPolicy, emptyHistory);
doReturn(1L).when(mQueue1).getRunnableAt();
doReturn(2L).when(mQueue2).getRunnableAt();
@@ -256,17 +250,12 @@
private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue,
BroadcastRecord record, int recordIndex) {
- enqueueOrReplaceBroadcast(queue, record, recordIndex, false, 42_000_000L);
+ enqueueOrReplaceBroadcast(queue, record, recordIndex, 42_000_000L);
}
private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue,
BroadcastRecord record, int recordIndex, long enqueueTime) {
- enqueueOrReplaceBroadcast(queue, record, recordIndex, false, enqueueTime);
- }
-
- private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue,
- BroadcastRecord record, int recordIndex, boolean wouldBeSkipped, long enqueueTime) {
- queue.enqueueOrReplaceBroadcast(record, recordIndex, wouldBeSkipped, (r, i) -> {
+ queue.enqueueOrReplaceBroadcast(record, recordIndex, (r, i) -> {
throw new UnsupportedOperationException();
});
record.enqueueTime = enqueueTime;
@@ -1199,6 +1188,42 @@
assertEquals(ProcessList.SCHED_GROUP_DEFAULT, queue.getPreferredSchedulingGroupLocked());
}
+ @Test
+ public void testSkipPolicy_atEnqueueTime() throws Exception {
+ final Intent userPresent = new Intent(Intent.ACTION_USER_PRESENT);
+ final Object greenReceiver = makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN);
+ final Object redReceiver = makeManifestReceiver(PACKAGE_RED, CLASS_RED);
+
+ final BroadcastRecord userPresentRecord = makeBroadcastRecord(userPresent,
+ List.of(greenReceiver, redReceiver));
+
+ final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK);
+ final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick,
+ List.of(greenReceiver, redReceiver));
+
+ doAnswer(invocation -> {
+ final BroadcastRecord r = invocation.getArgument(0);
+ final Object o = invocation.getArgument(1);
+ if (userPresent.getAction().equals(r.intent.getAction())
+ && isReceiverEquals(o, greenReceiver)) {
+ return "receiver skipped by test";
+ }
+ return null;
+ }).when(mSkipPolicy).shouldSkipMessage(any(BroadcastRecord.class), any());
+
+ mImpl.enqueueBroadcastLocked(userPresentRecord);
+ mImpl.enqueueBroadcastLocked(timeTickRecord);
+
+ final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN,
+ getUidForPackage(PACKAGE_GREEN));
+ // There should be only one broadcast for green process as the other would have
+ // been skipped.
+ verifyPendingRecords(greenQueue, List.of(timeTick));
+ final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED,
+ getUidForPackage(PACKAGE_RED));
+ verifyPendingRecords(redQueue, List.of(userPresent, timeTick));
+ }
+
private Intent createPackageChangedIntent(int uid, List<String> componentNameList) {
final Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
packageChangedIntent.putExtra(Intent.EXTRA_UID, uid);
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
index c4aa0bb..8dc0ac6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -64,6 +64,7 @@
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.display.RampAnimator.DualRampAnimator;
+import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.color.ColorDisplayService;
import com.android.server.display.layout.Layout;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
@@ -596,17 +597,17 @@
// We should still set screen state for the default display
DisplayPowerRequest dpr = new DisplayPowerRequest();
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
- advanceTime(1);
+ advanceTime(1); // Run updatePowerState
verify(mHolder.displayPowerState, times(2)).setScreenState(anyInt());
mHolder = createDisplayPowerController(42, UNIQUE_ID);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
- advanceTime(1);
+ advanceTime(1); // Run updatePowerState
verify(mHolder.displayPowerState, never()).setScreenState(anyInt());
mHolder.dpc.onBootCompleted();
- advanceTime(1);
+ advanceTime(1); // Run updatePowerState
verify(mHolder.displayPowerState).setScreenState(anyInt());
}
@@ -632,8 +633,8 @@
.thenReturn(brightness);
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
- when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness())
- .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+ when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
+ any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
@@ -667,8 +668,8 @@
.thenReturn(brightness);
dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
- when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness())
- .thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+ when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
+ any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1); // Run updatePowerState
@@ -822,6 +823,21 @@
);
}
+ @Test
+ public void testUpdateBrightnessThrottlingDataId() {
+ mHolder.display.getDisplayInfoLocked().thermalBrightnessThrottlingDataId =
+ "throttling-data-id";
+ clearInvocations(mHolder.display.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig());
+
+ mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.display.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig())
+ .getThermalBrightnessThrottlingDataMapByThrottlingId();
+ }
+
/**
* Creates a mock and registers it to {@link LocalServices}.
*/
@@ -862,8 +878,6 @@
when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
- when(logicalDisplayMock.getThermalBrightnessThrottlingDataIdLocked()).thenReturn(
- DisplayDeviceConfig.DEFAULT_ID);
when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
index 415adbb..5c0810f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -829,6 +829,21 @@
);
}
+ @Test
+ public void testUpdateBrightnessThrottlingDataId() {
+ mHolder.display.getDisplayInfoLocked().thermalBrightnessThrottlingDataId =
+ "throttling-data-id";
+ clearInvocations(mHolder.display.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig());
+
+ mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.display.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig())
+ .getThermalBrightnessThrottlingDataMapByThrottlingId();
+ }
+
/**
* Creates a mock and registers it to {@link LocalServices}.
*/
@@ -869,8 +884,6 @@
when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
- when(logicalDisplayMock.getThermalBrightnessThrottlingDataIdLocked()).thenReturn(
- DisplayDeviceConfig.DEFAULT_ID);
when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index 96eca71..8cfc150 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -281,8 +281,8 @@
@Test
public void testRegisterProxy() throws Exception {
mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY);
- verify(mProxyManager).registerProxy(eq(mMockServiceClient), eq(TEST_DISPLAY),
- eq(mTestableContext), anyInt(), any(), eq(mMockSecurityPolicy),
+ verify(mProxyManager).registerProxy(eq(mMockServiceClient), eq(TEST_DISPLAY), anyInt(),
+ eq(mMockSecurityPolicy),
eq(mA11yms), eq(mA11yms.getTraceManager()),
eq(mMockWindowManagerService));
}
@@ -295,7 +295,7 @@
assertThrows(SecurityException.class,
() -> mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY));
- verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
+ verify(mProxyManager, never()).registerProxy(any(), anyInt(), anyInt(), any(),
any(), any(), any());
}
@@ -307,7 +307,7 @@
assertThrows(SecurityException.class,
() -> mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY));
- verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
+ verify(mProxyManager, never()).registerProxy(any(), anyInt(), anyInt(), any(),
any(), any(), any());
}
@@ -316,7 +316,7 @@
public void testRegisterProxyForDefaultDisplay() throws Exception {
assertThrows(IllegalArgumentException.class,
() -> mA11yms.registerProxyForDisplay(mMockServiceClient, Display.DEFAULT_DISPLAY));
- verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
+ verify(mProxyManager, never()).registerProxy(any(), anyInt(), anyInt(), any(),
any(), any(), any());
}
@@ -325,7 +325,7 @@
public void testRegisterProxyForInvalidDisplay() throws Exception {
assertThrows(IllegalArgumentException.class,
() -> mA11yms.registerProxyForDisplay(mMockServiceClient, Display.INVALID_DISPLAY));
- verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
+ verify(mProxyManager, never()).registerProxy(any(), anyInt(), anyInt(), any(),
any(), any(), any());
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/ProxyAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/ProxyAccessibilityServiceConnectionTest.java
index dd44a79..6ac3658 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/ProxyAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/ProxyAccessibilityServiceConnectionTest.java
@@ -29,12 +29,14 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Color;
import android.os.Handler;
import android.view.accessibility.AccessibilityEvent;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -79,12 +81,15 @@
WindowManagerInternal mMockWindowManagerInternal;
ProxyAccessibilityServiceConnection mProxyConnection;
AccessibilityServiceInfo mAccessibilityServiceInfo;
+ private int mFocusStrokeWidthDefaultValue;
+ private int mFocusColorDefaultValue;
@Before
public void setup() {
final Resources resources = getInstrumentation().getContext().getResources();
MockitoAnnotations.initMocks(this);
when(mMockContext.getResources()).thenReturn(resources);
+ when(mMockSecurityPolicy.checkAccessibilityAccess(any())).thenReturn(true);
mAccessibilityServiceInfo = new AccessibilityServiceInfo();
mProxyConnection = new ProxyAccessibilityServiceConnection(mMockContext, COMPONENT_NAME,
@@ -92,10 +97,13 @@
getInstrumentation().getContext().getMainLooper()),
mMockLock, mMockSecurityPolicy, mMockSystemSupport, mMockA11yTrace,
mMockWindowManagerInternal, mMockA11yWindowManager, DISPLAY_ID, DEVICE_ID);
+
+ mFocusStrokeWidthDefaultValue = mProxyConnection.getFocusStrokeWidthLocked();
+ mFocusColorDefaultValue = mProxyConnection.getFocusColorLocked();
}
@Test
- public void testSetInstalledAndEnabledServices_clientChanged() {
+ public void testSetInstalledAndEnabledServices_updateInfos_notifiesSystemOfProxyChange() {
final List<AccessibilityServiceInfo> infos = new ArrayList<>();
final AccessibilityServiceInfo info1 = new AccessibilityServiceInfo();
infos.add(info1);
@@ -106,6 +114,17 @@
}
@Test
+ public void testSetFocusAppearance_updateAppearance_notifiesSystemOfProxyChange() {
+ final int updatedWidth = mFocusStrokeWidthDefaultValue + 10;
+ final int updatedColor = mFocusColorDefaultValue
+ == Color.BLUE ? Color.RED : Color.BLUE;
+
+ mProxyConnection.setFocusAppearance(updatedWidth, updatedColor);
+
+ verify(mMockSystemSupport).onProxyChanged(DEVICE_ID);
+ }
+
+ @Test
public void testSetInstalledAndEnabledServices_returnList() {
final List<AccessibilityServiceInfo> infos = new ArrayList<>();
final AccessibilityServiceInfo info1 = new AccessibilityServiceInfo();
@@ -196,7 +215,7 @@
}
@Test
- public void testSetServiceInfo_setIllegalOperationExceptionThrown_() {
+ public void testSetServiceInfo_setIllegalOperationExceptionThrown() {
UnsupportedOperationException thrown =
assertThrows(
UnsupportedOperationException.class,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java
new file mode 100644
index 0000000..6c7b995
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility;
+
+import static com.android.server.accessibility.ProxyAccessibilityServiceConnectionTest.INTERACTIVE_UI_TIMEOUT_100MS;
+import static com.android.server.accessibility.ProxyAccessibilityServiceConnectionTest.INTERACTIVE_UI_TIMEOUT_200MS;
+import static com.android.server.accessibility.ProxyAccessibilityServiceConnectionTest.NON_INTERACTIVE_UI_TIMEOUT_100MS;
+import static com.android.server.accessibility.ProxyAccessibilityServiceConnectionTest.NON_INTERACTIVE_UI_TIMEOUT_200MS;
+import static com.android.server.accessibility.ProxyManager.PROXY_COMPONENT_CLASS_NAME;
+import static com.android.server.accessibility.ProxyManager.PROXY_COMPONENT_PACKAGE_NAME;
+
+import static org.junit.Assert.fail;
+
+import android.accessibilityservice.AccessibilityGestureEvent;
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.AccessibilityTrace;
+import android.accessibilityservice.IAccessibilityServiceClient;
+import android.accessibilityservice.IAccessibilityServiceConnection;
+import android.accessibilityservice.MagnificationConfig;
+import android.companion.virtual.IVirtualDeviceManager;
+import android.companion.virtual.VirtualDeviceManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Region;
+import android.os.IBinder;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.util.ArraySet;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.IAccessibilityManagerClient;
+import android.view.inputmethod.EditorInfo;
+
+import com.android.internal.R;
+import com.android.internal.inputmethod.IAccessibilityInputMethodSession;
+import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback;
+import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
+import com.android.internal.util.IntPair;
+import com.android.server.LocalServices;
+import com.android.server.accessibility.test.MessageCapturingHandler;
+import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
+import com.android.server.wm.WindowManagerInternal;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.InstrumentationRegistry;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Tests for ProxyManager.
+ */
+public class ProxyManagerTest {
+ private static final int DISPLAY_ID = 1000;
+ private static final int DISPLAY_2_ID = 1001;
+ private static final int DEVICE_ID = 10;
+ private static final int STREAMED_CALLING_UID = 9876;
+
+ @Mock private Context mMockContext;
+ @Mock private AccessibilitySecurityPolicy mMockSecurityPolicy;
+ @Mock private AccessibilityWindowManager mMockA11yWindowManager;
+ @Mock private ProxyManager.SystemSupport mMockProxySystemSupport;
+ @Mock private AbstractAccessibilityServiceConnection.SystemSupport mMockConnectionSystemSupport;
+ @Mock private AccessibilityTrace mMockA11yTrace;
+ @Mock private WindowManagerInternal mMockWindowManagerInternal;
+ @Mock private IAccessibilityServiceClient mMockAccessibilityServiceClient;
+ @Mock private IBinder mMockServiceAsBinder;
+ @Mock private VirtualDeviceManagerInternal mMockVirtualDeviceManagerInternal;
+ @Mock private IVirtualDeviceManager mMockIVirtualDeviceManager;
+
+ private int mFocusStrokeWidthDefaultValue;
+ private int mFocusColorDefaultValue;
+
+ private MessageCapturingHandler mMessageCapturingHandler = new MessageCapturingHandler(null);
+ private ProxyManager mProxyManager;
+
+ @Before
+ public void setup() throws RemoteException {
+ MockitoAnnotations.initMocks(this);
+ final Resources resources = InstrumentationRegistry.getContext().getResources();
+
+ mFocusStrokeWidthDefaultValue =
+ resources.getDimensionPixelSize(R.dimen.accessibility_focus_highlight_stroke_width);
+ mFocusColorDefaultValue = resources.getColor(R.color.accessibility_focus_highlight_color);
+ when(mMockContext.getResources()).thenReturn(resources);
+
+ when(mMockVirtualDeviceManagerInternal.getDeviceIdsForUid(anyInt())).thenReturn(
+ new ArraySet(Set.of(DEVICE_ID)));
+ LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
+ LocalServices.addService(VirtualDeviceManagerInternal.class,
+ mMockVirtualDeviceManagerInternal);
+
+ when(mMockIVirtualDeviceManager.getDeviceIdForDisplayId(anyInt())).thenReturn(DEVICE_ID);
+ final VirtualDeviceManager virtualDeviceManager =
+ new VirtualDeviceManager(mMockIVirtualDeviceManager, mMockContext);
+ when(mMockContext.getSystemServiceName(VirtualDeviceManager.class)).thenReturn(
+ Context.VIRTUAL_DEVICE_SERVICE);
+ when(mMockContext.getSystemService(VirtualDeviceManager.class))
+ .thenReturn(virtualDeviceManager);
+
+ when(mMockA11yTrace.isA11yTracingEnabled()).thenReturn(false);
+
+ final RemoteCallbackList<IAccessibilityManagerClient> userClients =
+ new RemoteCallbackList<>();
+ final RemoteCallbackList<IAccessibilityManagerClient> globalClients =
+ new RemoteCallbackList<>();
+ when(mMockProxySystemSupport.getCurrentUserClientsLocked()).thenReturn(userClients);
+ when(mMockProxySystemSupport.getGlobalClientsLocked()).thenReturn(globalClients);
+
+ when(mMockAccessibilityServiceClient.asBinder()).thenReturn(mMockServiceAsBinder);
+
+ mProxyManager = new ProxyManager(new Object(), mMockA11yWindowManager, mMockContext,
+ mMessageCapturingHandler, new UiAutomationManager(new Object()),
+ mMockProxySystemSupport);
+ }
+
+ @After
+ public void tearDown() {
+ mMessageCapturingHandler.removeAllMessages();
+ }
+
+ /**
+ * Tests that the proxy’s backing AccessibilityServiceClient is initialized when registering a
+ * proxy.
+ */
+ @Test
+ public void registerProxy_always_connectsServiceClient() throws RemoteException {
+ registerProxy(DISPLAY_ID);
+ verify(mMockAccessibilityServiceClient).init(any(), anyInt(), any());
+ }
+
+ /** Tests that unregistering a proxy removes its display from tracking. */
+ @Test
+ public void unregisterProxy_always_stopsTrackingDisplay() {
+ registerProxy(DISPLAY_ID);
+
+ mProxyManager.unregisterProxy(DISPLAY_ID);
+
+ verify(mMockA11yWindowManager).stopTrackingDisplayProxy(DISPLAY_ID);
+ assertThat(mProxyManager.isProxyedDisplay(DISPLAY_ID)).isFalse();
+ }
+ /**
+ * Tests that unregistering a proxied display of a virtual device, where that virtual device
+ * owned only that one proxied display, removes the device from tracking.
+ */
+ @Test
+ public void unregisterProxy_deviceAssociatedWithSingleDisplay_stopsTrackingDevice() {
+ registerProxy(DISPLAY_ID);
+
+ mProxyManager.unregisterProxy(DISPLAY_ID);
+
+ assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isFalse();
+ verify(mMockProxySystemSupport).removeDeviceIdLocked(DEVICE_ID);
+ }
+
+ /**
+ * Tests that unregistering a proxied display of a virtual device, where that virtual device
+ * owns more than one proxied display, does not remove the device from tracking.
+ */
+ @Test
+ public void unregisterProxy_deviceAssociatedWithMultipleDisplays_tracksRemainingProxy() {
+ registerProxy(DISPLAY_ID);
+ registerProxy(DISPLAY_2_ID);
+
+ mProxyManager.unregisterProxy(DISPLAY_ID);
+
+ assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isTrue();
+ verify(mMockProxySystemSupport, never()).removeDeviceIdLocked(DEVICE_ID);
+ }
+
+ /**
+ * Tests that changing a proxy, e.g. registering/unregistering a proxy or updating its service
+ * info, notifies the apps being streamed and AccessibilityManagerService.
+ */
+ @Test
+ public void testOnProxyChanged_always_propagatesChange() {
+ registerProxy(DISPLAY_ID);
+ mMessageCapturingHandler.sendAllMessages();
+
+ mProxyManager.onProxyChanged(DEVICE_ID);
+
+ // Messages to notify IAccessibilityManagerClients should be posted.
+ assertThat(mMessageCapturingHandler.hasMessages()).isTrue();
+
+ verify(mMockProxySystemSupport).updateWindowsForAccessibilityCallbackLocked();
+ verify(mMockProxySystemSupport).notifyClearAccessibilityCacheLocked();
+ }
+
+ /**
+ * Tests that getting the first device id for an app uid, such as when an app queries for
+ * device-specific state, returns the right device id.
+ */
+ @Test
+ public void testGetFirstDeviceForUid_streamedAppQueriesState_getsHostDeviceId() {
+ registerProxy(DISPLAY_ID);
+ assertThat(mProxyManager.getFirstDeviceIdForUidLocked(STREAMED_CALLING_UID))
+ .isEqualTo(DEVICE_ID);
+ }
+
+ /**
+ * Tests that the app client state retrieved for a device reflects that touch exploration is
+ * enabled since a proxy info has requested touch exploration.
+ */
+ @Test
+ public void testGetClientState_proxyWantsTouchExploration_returnsTouchExplorationEnabled() {
+ registerProxy(DISPLAY_ID);
+
+ final AccessibilityServiceInfo secondDisplayInfo = new AccessibilityServiceInfo();
+ secondDisplayInfo.flags |= AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
+ AccessibilityServiceClientImpl client = new AccessibilityServiceClientImpl(
+ secondDisplayInfo);
+ registerProxy(DISPLAY_2_ID, client);
+
+ final int deviceClientState = mProxyManager.getStateLocked(DEVICE_ID);
+ assertThat((deviceClientState
+ & AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0).isTrue();
+ }
+
+ /**
+ * Tests that the highest interactive and non-interactive timeout is returned if there are
+ * multiple proxied displays belonging to a device.
+ */
+ @Test
+ public void testGetRecommendedTimeout_multipleProxies_returnsHighestTimeout() {
+ final AccessibilityServiceInfo firstDisplayInfo = new AccessibilityServiceInfo();
+ firstDisplayInfo.setInteractiveUiTimeoutMillis(INTERACTIVE_UI_TIMEOUT_100MS);
+ firstDisplayInfo.setNonInteractiveUiTimeoutMillis(NON_INTERACTIVE_UI_TIMEOUT_200MS);
+
+ final AccessibilityServiceInfo secondDisplayInfo = new AccessibilityServiceInfo();
+ secondDisplayInfo.setInteractiveUiTimeoutMillis(INTERACTIVE_UI_TIMEOUT_200MS);
+ secondDisplayInfo.setNonInteractiveUiTimeoutMillis(NON_INTERACTIVE_UI_TIMEOUT_100MS);
+
+ registerProxy(DISPLAY_ID, new AccessibilityServiceClientImpl(firstDisplayInfo));
+ registerProxy(DISPLAY_2_ID, new AccessibilityServiceClientImpl(secondDisplayInfo));
+
+ final long timeout = mProxyManager.getRecommendedTimeoutMillisLocked(DEVICE_ID);
+ final int interactiveTimeout = IntPair.first(timeout);
+ final int nonInteractiveTimeout = IntPair.second(timeout);
+
+ assertThat(interactiveTimeout).isEqualTo(INTERACTIVE_UI_TIMEOUT_200MS);
+ assertThat(nonInteractiveTimeout).isEqualTo(NON_INTERACTIVE_UI_TIMEOUT_200MS);
+ }
+ /**
+ * Tests that getting the installed and enabled services returns the info of the registered
+ * proxy. (The component name reflects the display id.)
+ */
+ @Test
+ public void testGetInstalledAndEnabledServices_defaultInfo_returnsInfoForDisplayId() {
+ final AccessibilityServiceInfo info = new AccessibilityServiceInfo();
+ registerProxy(DISPLAY_ID, new AccessibilityServiceClientImpl(info));
+ final List<AccessibilityServiceInfo> installedAndEnabledServices =
+ mProxyManager.getInstalledAndEnabledServiceInfosLocked(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK, DEVICE_ID);
+ assertThat(installedAndEnabledServices.size()).isEqualTo(1);
+ AccessibilityServiceInfo proxyInfo = installedAndEnabledServices.get(0);
+
+ assertThat(proxyInfo.getComponentName()).isEqualTo(new ComponentName(
+ PROXY_COMPONENT_PACKAGE_NAME, PROXY_COMPONENT_CLASS_NAME + DISPLAY_ID));
+ }
+
+ /**
+ * Tests that the app client state retrieved for a device reflects that accessibility is
+ * enabled.
+ */
+ @Test
+ public void testGetClientState_always_returnsAccessibilityEnabled() {
+ registerProxy(DISPLAY_ID);
+
+ final int deviceClientState = mProxyManager.getStateLocked(DEVICE_ID);
+ assertThat((deviceClientState
+ & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0).isTrue();
+ }
+
+ /**
+ * Tests that the manager can retrieve interactive windows if a proxy sets
+ * AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS.
+ */
+ @Test
+ public void testCanRetrieveInteractiveWindows_atLeastOneProxyWantsWindows_returnsTrue() {
+ registerProxy(DISPLAY_ID);
+
+ final AccessibilityServiceInfo secondDisplayInfo = new AccessibilityServiceInfo();
+ secondDisplayInfo.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
+ registerProxy(DISPLAY_2_ID, new AccessibilityServiceClientImpl(secondDisplayInfo));
+
+ assertThat(mProxyManager.canRetrieveInteractiveWindowsLocked()).isTrue();
+ }
+
+ /**
+ * Tests that getting service interfaces to interrupt when AccessibilityManager#interrupt
+ * returns the registered proxy interface.
+ */
+ @Test
+ public void testGetServiceInterfacesForInterrupt_defaultProxy_returnsProxyInterface() {
+ registerProxy(DISPLAY_ID);
+ final List<IAccessibilityServiceClient> interfacesToInterrupt = new ArrayList<>();
+ mProxyManager.addServiceInterfacesLocked(interfacesToInterrupt, DEVICE_ID);
+
+ assertThat(interfacesToInterrupt.size()).isEqualTo(1);
+ assertThat(interfacesToInterrupt.get(0).asBinder()).isEqualTo(mMockServiceAsBinder);
+ }
+
+ /** Tests that the default timeout (0) is returned when the proxy is registered. */
+ @Test
+ public void getRecommendedTimeout_defaultProxyInfo_getsDefaultTimeout() {
+ registerProxy(DISPLAY_ID);
+ final long timeout = mProxyManager.getRecommendedTimeoutMillisLocked(DEVICE_ID);
+ final int interactiveTimeout = IntPair.first(timeout);
+ final int nonInteractiveTimeout = IntPair.second(timeout);
+
+ assertThat(interactiveTimeout).isEqualTo(0);
+ assertThat(nonInteractiveTimeout).isEqualTo(0);
+ }
+
+ /** Tests that the manager returns the updated timeout when the proxy’s timeout is updated. */
+ @Test
+ public void getRecommendedTimeout_updateTimeout_getsUpdatedTimeout() {
+ registerProxy(DISPLAY_ID);
+
+ mProxyManager.updateTimeoutsIfNeeded(NON_INTERACTIVE_UI_TIMEOUT_100MS,
+ INTERACTIVE_UI_TIMEOUT_200MS);
+
+ final long updatedTimeout = mProxyManager.getRecommendedTimeoutMillisLocked(DEVICE_ID);
+ final int updatedInteractiveTimeout = IntPair.first(updatedTimeout);
+ final int updatedNonInteractiveTimeout = IntPair.second(updatedTimeout);
+
+ assertThat(updatedInteractiveTimeout).isEqualTo(INTERACTIVE_UI_TIMEOUT_200MS);
+ assertThat(updatedNonInteractiveTimeout).isEqualTo(NON_INTERACTIVE_UI_TIMEOUT_100MS);
+ }
+
+ /** Tests that the system’s default focus color is returned. */
+ @Test
+ public void testGetFocusColor_defaultProxy_getsDefaultSystemColor() {
+ registerProxy(DISPLAY_ID);
+ final int focusColor = mProxyManager.getFocusColorLocked(DEVICE_ID);
+ assertThat(focusColor).isEqualTo(mFocusColorDefaultValue);
+ }
+
+ /** Tests that the system’s default focus stroke width is returned. */
+ @Test
+ public void testGetFocusStrokeWidth_defaultProxy_getsDefaultSystemWidth() {
+ registerProxy(DISPLAY_ID);
+ final int focusStrokeWidth = mProxyManager.getFocusStrokeWidthLocked(DEVICE_ID);
+ assertThat(focusStrokeWidth).isEqualTo(mFocusStrokeWidthDefaultValue);
+ }
+
+ private void registerProxy(int displayId) {
+ try {
+ mProxyManager.registerProxy(mMockAccessibilityServiceClient, displayId, anyInt(),
+ mMockSecurityPolicy, mMockConnectionSystemSupport,
+ mMockA11yTrace, mMockWindowManagerInternal);
+ } catch (RemoteException e) {
+ fail("Failed to register proxy " + e);
+ }
+ }
+
+ private void registerProxy(int displayId, AccessibilityServiceClientImpl serviceClient) {
+ try {
+ mProxyManager.registerProxy(serviceClient, displayId, anyInt(),
+ mMockSecurityPolicy, mMockConnectionSystemSupport,
+ mMockA11yTrace, mMockWindowManagerInternal);
+ } catch (RemoteException e) {
+ fail("Failed to register proxy " + e);
+ }
+ }
+
+ /**
+ * IAccessibilityServiceClient implementation.
+ * A proxy connection does not populate non-default AccessibilityServiceInfo values until the
+ * proxy is connected in A11yDisplayProxy#onServiceConnected. For tests that check for
+ * non-default values, populate immediately in this testing class, since a real Service is not
+ * being used and connected.
+ */
+ static class AccessibilityServiceClientImpl extends IAccessibilityServiceClient.Stub {
+ List<AccessibilityServiceInfo> mInstalledAndEnabledServices;
+
+ AccessibilityServiceClientImpl(AccessibilityServiceInfo
+ installedAndEnabledService) {
+ mInstalledAndEnabledServices = List.of(installedAndEnabledService);
+ }
+
+ @Override
+ public void init(IAccessibilityServiceConnection connection, int connectionId,
+ IBinder windowToken) throws RemoteException {
+ connection.setInstalledAndEnabledServices(mInstalledAndEnabledServices);
+ }
+
+ @Override
+ public void onAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onInterrupt() throws RemoteException {
+
+ }
+
+ @Override
+ public void onGesture(AccessibilityGestureEvent gestureEvent) throws RemoteException {
+
+ }
+
+ @Override
+ public void clearAccessibilityCache() throws RemoteException {
+
+ }
+
+ @Override
+ public void onKeyEvent(KeyEvent event, int sequence) throws RemoteException {
+
+ }
+
+ @Override
+ public void onMagnificationChanged(int displayId, Region region, MagnificationConfig config)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onMotionEvent(MotionEvent event) throws RemoteException {
+
+ }
+
+ @Override
+ public void onTouchStateChanged(int displayId, int state) throws RemoteException {
+
+ }
+
+ @Override
+ public void onSoftKeyboardShowModeChanged(int showMode) throws RemoteException {
+
+ }
+
+ @Override
+ public void onPerformGestureResult(int sequence, boolean completedSuccessfully)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onFingerprintCapturingGesturesChanged(boolean capturing)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onFingerprintGesture(int gesture) throws RemoteException {
+
+ }
+
+ @Override
+ public void onAccessibilityButtonClicked(int displayId) throws RemoteException {
+
+ }
+
+ @Override
+ public void onAccessibilityButtonAvailabilityChanged(boolean available)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onSystemActionsChanged() throws RemoteException {
+
+ }
+
+ @Override
+ public void createImeSession(IAccessibilityInputMethodSessionCallback callback)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void setImeSessionEnabled(IAccessibilityInputMethodSession session, boolean enabled)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void bindInput() throws RemoteException {
+
+ }
+
+ @Override
+ public void unbindInput() throws RemoteException {
+
+ }
+
+ @Override
+ public void startInput(IRemoteAccessibilityInputConnection connection,
+ EditorInfo editorInfo, boolean restarting) throws RemoteException {
+
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
index 07c6182..fb3a5f6 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
@@ -80,7 +80,7 @@
@Mock
private WindowManager mWindowManager;
- private OperationContextExt mOpContext = new OperationContextExt();
+ private OperationContextExt mOpContext = new OperationContextExt(true);
private IBiometricContextListener mListener;
private BiometricContextProvider mProvider;
@@ -316,25 +316,6 @@
assertThat(aidlContext.isAod).isEqualTo(false);
assertThat(aidlContext.isCrypto).isEqualTo(false);
- for (int type : List.of(StatusBarManager.SESSION_BIOMETRIC_PROMPT,
- StatusBarManager.SESSION_KEYGUARD)) {
- final int id = 40 + type;
- final boolean aod = (type & 1) == 0;
-
- mListener.onDisplayStateChanged(aod ? AuthenticateOptions.DISPLAY_STATE_AOD
- : AuthenticateOptions.DISPLAY_STATE_LOCKSCREEN);
- mSessionListener.onSessionStarted(type, InstanceId.fakeInstanceId(id));
- context = mProvider.updateContext(mOpContext, false /* crypto */);
- aidlContext = context.toAidlContext();
- assertThat(context).isSameInstanceAs(mOpContext);
- assertThat(aidlContext.id).isEqualTo(id);
- assertThat(aidlContext.reason).isEqualTo(reason(type));
- assertThat(aidlContext.isAod).isEqualTo(aod);
- assertThat(aidlContext.isCrypto).isEqualTo(false);
-
- mSessionListener.onSessionEnded(type, InstanceId.fakeInstanceId(id));
- }
-
context = mProvider.updateContext(mOpContext, false /* crypto */);
aidlContext = context.toAidlContext();
assertThat(context).isSameInstanceAs(mOpContext);
@@ -344,6 +325,33 @@
assertThat(aidlContext.isCrypto).isEqualTo(false);
}
+ @Test
+ public void testUpdateAllSessionTypes() throws RemoteException {
+ OperationContextExt context = mProvider.updateContext(mOpContext, false /* crypto */);
+ OperationContext aidlContext = context.toAidlContext();
+
+ for (int type : List.of(StatusBarManager.SESSION_BIOMETRIC_PROMPT,
+ StatusBarManager.SESSION_KEYGUARD)) {
+ final int id = 40 + type;
+ final boolean aod = (type & 1) == 0;
+
+ OperationContextExt opContext =
+ new OperationContextExt(type == StatusBarManager.SESSION_BIOMETRIC_PROMPT);
+ mListener.onDisplayStateChanged(aod ? AuthenticateOptions.DISPLAY_STATE_AOD
+ : AuthenticateOptions.DISPLAY_STATE_LOCKSCREEN);
+ mSessionListener.onSessionStarted(type, InstanceId.fakeInstanceId(id));
+ context = mProvider.updateContext(opContext, false /* crypto */);
+ aidlContext = context.toAidlContext();
+ assertThat(context).isSameInstanceAs(opContext);
+ assertThat(aidlContext.id).isEqualTo(id);
+ assertThat(aidlContext.reason).isEqualTo(reason(type));
+ assertThat(aidlContext.isAod).isEqualTo(aod);
+ assertThat(aidlContext.isCrypto).isEqualTo(false);
+
+ mSessionListener.onSessionEnded(type, InstanceId.fakeInstanceId(id));
+ }
+ }
+
private static byte reason(int type) {
if (type == StatusBarManager.SESSION_BIOMETRIC_PROMPT) {
return OperationReason.BIOMETRIC_PROMPT;
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricFrameworkStatsLoggerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricFrameworkStatsLoggerTest.java
index 5adf391..5cff48d 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricFrameworkStatsLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricFrameworkStatsLoggerTest.java
@@ -34,7 +34,7 @@
@Test
public void testConvertsWakeReason_whenEmpty() {
- final OperationContextExt ctx = new OperationContextExt();
+ final OperationContextExt ctx = new OperationContextExt(false);
final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx);
final int[] reasonDetails = BiometricFrameworkStatsLogger
@@ -48,11 +48,11 @@
public void testConvertsWakeReason_whenPowerReason() {
final OperationContext context = new OperationContext();
context.wakeReason = WakeReason.WAKE_MOTION;
- final OperationContextExt ctx = new OperationContextExt(context);
+ final OperationContextExt ctx = new OperationContextExt(context, false);
final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx);
final int[] reasonDetails = BiometricFrameworkStatsLogger
- .toProtoWakeReasonDetails(new OperationContextExt(context));
+ .toProtoWakeReasonDetails(new OperationContextExt(context, false));
assertThat(reason).isEqualTo(BiometricsProtoEnums.WAKE_REASON_WAKE_MOTION);
assertThat(reasonDetails).isEmpty();
@@ -63,7 +63,7 @@
final OperationContext context = new OperationContext();
context.authenticateReason = AuthenticateReason.faceAuthenticateReason(
AuthenticateReason.Face.ASSISTANT_VISIBLE);
- final OperationContextExt ctx = new OperationContextExt(context);
+ final OperationContextExt ctx = new OperationContextExt(context, false);
final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx);
final int[] reasonDetails = BiometricFrameworkStatsLogger
@@ -79,7 +79,7 @@
final OperationContext context = new OperationContext();
context.authenticateReason = AuthenticateReason.vendorAuthenticateReason(
new AuthenticateReason.Vendor());
- final OperationContextExt ctx = new OperationContextExt(context);
+ final OperationContextExt ctx = new OperationContextExt(context, false);
final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx);
final int[] reasonDetails = BiometricFrameworkStatsLogger
@@ -96,7 +96,7 @@
context.wakeReason = WakeReason.WAKE_KEY;
context.authenticateReason = AuthenticateReason.faceAuthenticateReason(
AuthenticateReason.Face.PRIMARY_BOUNCER_SHOWN);
- final OperationContextExt ctx = new OperationContextExt(context);
+ final OperationContextExt ctx = new OperationContextExt(context, false);
final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx);
final int[] reasonDetails = BiometricFrameworkStatsLogger
@@ -113,7 +113,7 @@
context.wakeReason = WakeReason.LID;
context.authenticateReason = AuthenticateReason.vendorAuthenticateReason(
new AuthenticateReason.Vendor());
- final OperationContextExt ctx = new OperationContextExt(context);
+ final OperationContextExt ctx = new OperationContextExt(context, false);
final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx);
final int[] reasonDetails = BiometricFrameworkStatsLogger
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
index 81dcf48..612f717 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
@@ -74,7 +74,7 @@
@Before
public void setUp() {
- mOpContext = new OperationContextExt();
+ mOpContext = new OperationContextExt(false);
mContext.addMockSystemService(SensorManager.class, mSensorManager);
when(mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)).thenReturn(
new Sensor(new InputSensorInfo("", "", 0, 0, Sensor.TYPE_LIGHT, 0, 0, 0, 0, 0, 0,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/OperationContextExtTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/OperationContextExtTest.java
index c652b74..5cf5960 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/OperationContextExtTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/OperationContextExtTest.java
@@ -53,12 +53,12 @@
@Test
public void hasAidlContext() {
- OperationContextExt context = new OperationContextExt();
+ OperationContextExt context = new OperationContextExt(false);
assertThat(context.toAidlContext()).isNotNull();
final OperationContext aidlContext = newAidlContext();
- context = new OperationContextExt(aidlContext);
+ context = new OperationContextExt(aidlContext, false);
assertThat(context.toAidlContext()).isSameInstanceAs(aidlContext);
final int id = 5;
@@ -79,7 +79,7 @@
@Test
public void hasNoOrderWithoutSession() {
- OperationContextExt context = new OperationContextExt();
+ OperationContextExt context = new OperationContextExt(false);
assertThat(context.getOrderAndIncrement()).isEqualTo(-1);
assertThat(context.getOrderAndIncrement()).isEqualTo(-1);
}
@@ -96,7 +96,7 @@
);
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
- final OperationContextExt context = new OperationContextExt(newAidlContext());
+ final OperationContextExt context = new OperationContextExt(newAidlContext(), true);
when(mBiometricContext.getDisplayState()).thenReturn(entry.getKey());
assertThat(context.update(mBiometricContext).getDisplayState())
.isEqualTo(entry.getValue());
@@ -136,7 +136,8 @@
when(mBiometricContext.isDisplayOn()).thenReturn(true);
when(mBiometricContext.getDisplayState()).thenReturn(displayState);
- final OperationContextExt context = new OperationContextExt(newAidlContext());
+ final OperationContextExt context = new OperationContextExt(newAidlContext(),
+ sessionType == OperationReason.BIOMETRIC_PROMPT);
assertThat(context.update(mBiometricContext)).isSameInstanceAs(context);
diff --git a/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceCallTest.java b/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceCallTest.java
index c7fb97f..9d42a5b 100644
--- a/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceCallTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceCallTest.java
@@ -18,9 +18,11 @@
import static com.google.common.truth.Truth.assertWithMessage;
+import android.content.ComponentName;
import android.platform.test.annotations.Presubmit;
import android.telecom.Call;
import android.telecom.ParcelableCall;
+import android.telecom.PhoneAccountHandle;
import android.testing.AndroidTestingRunner;
import androidx.test.InstrumentationRegistry;
@@ -37,12 +39,14 @@
private static final String CALLER_DISPLAY_NAME = "name";
private static final String CONTACT_DISPLAY_NAME = "contact";
+ private final Call.Details mUninitializedCallDetails = createCallDetails(
+ /* state= */ -1, /* capabilities= */ 0);
@Test
public void updateCallDetails_uninitialized() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
.isEqualTo(android.companion.Telecom.Call.UNKNOWN_STATUS);
assertWithMessage("Wrong controls").that(crossDeviceCall.getControls()).isEmpty();
@@ -51,8 +55,8 @@
@Test
public void updateCallDetails_ringing() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_RINGING,
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
@@ -66,8 +70,8 @@
@Test
public void updateCallDetails_ongoing() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_ACTIVE,
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
@@ -81,8 +85,8 @@
@Test
public void updateCallDetails_holding() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_HOLDING,
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
@@ -95,8 +99,8 @@
@Test
public void updateCallDetails_cannotHold() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.updateCallDetails(
createCallDetails(Call.STATE_ACTIVE, Call.Details.CAPABILITY_MUTE));
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
@@ -109,8 +113,8 @@
@Test
public void updateCallDetails_cannotMute() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.updateCallDetails(
createCallDetails(Call.STATE_ACTIVE, Call.Details.CAPABILITY_HOLD));
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
@@ -123,8 +127,8 @@
@Test
public void updateCallDetails_transitionRingingToOngoing() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_RINGING,
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
assertWithMessage("Wrong status for ringing state").that(crossDeviceCall.getStatus())
@@ -146,8 +150,8 @@
@Test
public void updateSilencedIfRinging_ringing_silenced() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_RINGING,
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
crossDeviceCall.updateSilencedIfRinging();
@@ -161,8 +165,8 @@
@Test
public void updateSilencedIfRinging_notRinging_notSilenced() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_ACTIVE,
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
crossDeviceCall.updateSilencedIfRinging();
@@ -177,8 +181,8 @@
@Test
public void getReadableCallerId_enterpriseCall_adminBlocked_ott() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.mIsEnterprise = true;
crossDeviceCall.mIsOtt = true;
crossDeviceCall.updateCallDetails(
@@ -193,8 +197,8 @@
@Test
public void getReadableCallerId_enterpriseCall_adminUnblocked_ott() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.mIsEnterprise = true;
crossDeviceCall.mIsOtt = true;
crossDeviceCall.updateCallDetails(
@@ -209,8 +213,8 @@
@Test
public void getReadableCallerId_enterpriseCall_adminBlocked_pstn() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.mIsEnterprise = true;
crossDeviceCall.mIsOtt = false;
crossDeviceCall.updateCallDetails(
@@ -225,8 +229,8 @@
@Test
public void getReadableCallerId_nonEnterpriseCall_adminBlocked_ott() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.mIsEnterprise = false;
crossDeviceCall.mIsOtt = true;
crossDeviceCall.updateCallDetails(
@@ -241,8 +245,8 @@
@Test
public void getReadableCallerId_nonEnterpriseCall_adminUnblocked_ott() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.mIsEnterprise = false;
crossDeviceCall.mIsOtt = true;
crossDeviceCall.updateCallDetails(
@@ -257,8 +261,8 @@
@Test
public void getReadableCallerId_nonEnterpriseCall_adminBlocked_pstn() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.mIsEnterprise = false;
crossDeviceCall.mIsOtt = false;
crossDeviceCall.updateCallDetails(
@@ -273,8 +277,8 @@
@Test
public void getReadableCallerId_nonEnterpriseCall_adminUnblocked_pstn() {
final CrossDeviceCall crossDeviceCall = new CrossDeviceCall(
- InstrumentationRegistry.getTargetContext().getPackageManager(), /* call= */
- null, /* callAudioState= */ null);
+ InstrumentationRegistry.getTargetContext().getPackageManager(),
+ mUninitializedCallDetails, /* callAudioState= */ null);
crossDeviceCall.mIsEnterprise = false;
crossDeviceCall.mIsOtt = false;
crossDeviceCall.updateCallDetails(
@@ -294,6 +298,8 @@
parcelableCallBuilder.setCapabilities(capabilities);
parcelableCallBuilder.setState(state);
parcelableCallBuilder.setConferenceableCallIds(Collections.emptyList());
+ parcelableCallBuilder.setAccountHandle(new PhoneAccountHandle(
+ new ComponentName("com.google.test", "com.google.test.Activity"), "label"));
return Call.Details.createFromParcelableCall(parcelableCallBuilder.createParcelableCall());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 34b88b0..1e342f5 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -130,6 +130,7 @@
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.IpcDataCache;
+import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
@@ -1511,7 +1512,6 @@
* Validates that when the device owner is removed, the reset password token is cleared
*/
@Test
- @Ignore("b/277916462")
public void testClearDeviceOwner_clearResetPasswordToken() throws Exception {
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -2602,7 +2602,6 @@
}
@Test
- @Ignore("b/277916462")
public void testSetApplicationHiddenWithDO() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -2628,7 +2627,6 @@
}
@Test
- @Ignore("b/277916462")
public void testSetApplicationHiddenWithPOOfOrganizationOwnedDevice() throws Exception {
final int MANAGED_PROFILE_USER_ID = CALLER_USER_HANDLE;
final int MANAGED_PROFILE_ADMIN_UID =
@@ -4375,7 +4373,6 @@
}
@Test
- @Ignore("b/277916462")
public void testSetAutoTimeZoneEnabledModifiesSetting() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -4387,7 +4384,6 @@
}
@Test
- @Ignore("b/277916462")
public void testSetAutoTimeZoneEnabledWithPOOnUser0() throws Exception {
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
setupProfileOwnerOnUser0();
@@ -4399,7 +4395,6 @@
}
@Test
- @Ignore("b/277916462")
public void testSetAutoTimeZoneEnabledFailWithPONotOnUser0() throws Exception {
setupProfileOwner();
assertExpectException(SecurityException.class, null,
@@ -4409,7 +4404,6 @@
}
@Test
- @Ignore("b/277916462")
public void testSetAutoTimeZoneEnabledWithPOOfOrganizationOwnedDevice() throws Exception {
setupProfileOwner();
configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
@@ -5383,7 +5377,6 @@
}
@Test
- @Ignore("b/277916462")
public void testResetPasswordWithToken() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -5418,7 +5411,6 @@
}
@Test
- @Ignore("b/277916462")
public void resetPasswordWithToken_NumericPin() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -5439,7 +5431,6 @@
}
@Test
- @Ignore("b/277916462")
public void resetPasswordWithToken_EmptyPassword() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -7260,7 +7251,6 @@
}
@Test
- @Ignore("b/277916462")
public void testCanProfileOwnerResetPasswordWhenLocked() throws Exception {
setDeviceEncryptionPerUser();
setupProfileOwner();
@@ -7324,7 +7314,6 @@
}
@Test
- @Ignore("b/277916462")
public void testSetAccountTypesWithManagementDisabledOnManagedProfile() throws Exception {
setupProfileOwner();
@@ -7344,7 +7333,6 @@
}
@Test
- @Ignore("b/277916462")
public void testSetAccountTypesWithManagementDisabledOnOrgOwnedManagedProfile()
throws Exception {
mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS);
@@ -8539,6 +8527,46 @@
eq(FUSED_PROVIDER), any(), eq(getServices().executor), any());
}
+ /**
+ * Verifies that bundles with tons of moderately long strings are persisted correctly.
+ *
+ * Policy is serialized into binary XML and there is a limit on the max string length: 65535.
+ * This test ensures that as long as each string in the trust agent configuration is below this
+ * limit, the policy can be serialized and deserialized correctly, even when the total length
+ * of the configuration is above that limit. This should be the case because PersistableBundle
+ * contents are stored as XML subtrees rather than as strings.
+ */
+ @Test
+ public void testSetTrustAgentConfiguration_largeBundlePersisted() {
+ setAsProfileOwner(admin1);
+
+ ComponentName agent = new ComponentName("some.trust.agent", "some.trust.agent.Agent");
+ PersistableBundle configIn = new PersistableBundle();
+ String kilobyteString = new String(new char[1024]).replace('\0', 'A');
+ for (int i = 0; i < 1024; i++) {
+ configIn.putString("key-" + i, kilobyteString);
+ }
+
+ runAsCaller(mAdmin1Context, dpms, dpm -> {
+ dpm.setTrustAgentConfiguration(admin1, agent, configIn);
+ });
+
+ // Re-read policies to see if they were serialized/deserialized correctly.
+ initializeDpms();
+
+ List<PersistableBundle> configsOut = new ArrayList<>();
+ runAsCaller(mAdmin1Context, dpms, dpm -> {
+ configsOut.addAll(dpm.getTrustAgentConfiguration(admin1, agent));
+ });
+
+ assertThat(configsOut.size()).isEqualTo(1);
+ PersistableBundle configOut = configsOut.get(0);
+ assertThat(configOut.size()).isEqualTo(1024);
+ for (int i = 0; i < 1024; i++) {
+ assertThat(configOut.getString("key-" + i, null)).isEqualTo(kilobyteString);
+ }
+ }
+
private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) {
final AppOpsManager.PackageOps vpnOp = new AppOpsManager.PackageOps(userVpnPackage,
userVpnUid, List.of(new AppOpsManager.OpEntry(
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index 7536c79..1eec70d 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -649,9 +649,9 @@
assertEquals(0, mLogicalDisplayMapper.getDisplayLocked(device2)
.getLeadDisplayIdLocked());
assertEquals("concurrent", mLogicalDisplayMapper.getDisplayLocked(device1)
- .getThermalBrightnessThrottlingDataIdLocked());
+ .getDisplayInfoLocked().thermalBrightnessThrottlingDataId);
assertEquals("concurrent", mLogicalDisplayMapper.getDisplayLocked(device2)
- .getThermalBrightnessThrottlingDataIdLocked());
+ .getDisplayInfoLocked().thermalBrightnessThrottlingDataId);
mLogicalDisplayMapper.setDeviceStateLocked(1, false);
advanceTime(1000);
@@ -661,10 +661,10 @@
assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
assertEquals(DisplayDeviceConfig.DEFAULT_ID,
mLogicalDisplayMapper.getDisplayLocked(device1)
- .getThermalBrightnessThrottlingDataIdLocked());
+ .getDisplayInfoLocked().thermalBrightnessThrottlingDataId);
assertEquals(DisplayDeviceConfig.DEFAULT_ID,
mLogicalDisplayMapper.getDisplayLocked(device2)
- .getThermalBrightnessThrottlingDataIdLocked());
+ .getDisplayInfoLocked().thermalBrightnessThrottlingDataId);
mLogicalDisplayMapper.setDeviceStateLocked(2, false);
advanceTime(1000);
@@ -674,10 +674,10 @@
assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
assertEquals(DisplayDeviceConfig.DEFAULT_ID,
mLogicalDisplayMapper.getDisplayLocked(device1)
- .getThermalBrightnessThrottlingDataIdLocked());
+ .getDisplayInfoLocked().thermalBrightnessThrottlingDataId);
assertEquals(DisplayDeviceConfig.DEFAULT_ID,
mLogicalDisplayMapper.getDisplayLocked(device2)
- .getThermalBrightnessThrottlingDataIdLocked());
+ .getDisplayInfoLocked().thermalBrightnessThrottlingDataId);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
index 5ea3029..f6cf571 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
@@ -205,4 +205,19 @@
assertNotEquals(info3, info2);
assertTrue(refreshRanges.contentEquals(info3.thermalRefreshRateThrottling));
}
+
+ @Test
+ public void testSetThermalBrightnessThrottlingDataId() {
+ String brightnessThrottlingDataId = "throttling_data_id";
+ DisplayInfo info1 = mLogicalDisplay.getDisplayInfoLocked();
+ mLogicalDisplay.setThermalBrightnessThrottlingDataIdLocked(brightnessThrottlingDataId);
+ DisplayInfo info2 = mLogicalDisplay.getDisplayInfoLocked();
+ // Display info should only be updated when updateLocked is called
+ assertEquals(info2, info1);
+
+ mLogicalDisplay.updateLocked(mDeviceRepo);
+ DisplayInfo info3 = mLogicalDisplay.getDisplayInfoLocked();
+ assertNotEquals(info3, info2);
+ assertEquals(brightnessThrottlingDataId, info3.thermalBrightnessThrottlingDataId);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
index d7b12e0..e6d3bbc 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
@@ -19,10 +19,13 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -66,25 +69,27 @@
@Mock
private HandlerExecutor mBrightnessChangeExecutor;
+ private final DisplayBrightnessController.Injector mInjector = new
+ DisplayBrightnessController.Injector() {
+ @Override
+ DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector(
+ Context context, int displayId) {
+ return mDisplayBrightnessStrategySelector;
+ }
+ };
+
private DisplayBrightnessController mDisplayBrightnessController;
@Before
public void before() {
MockitoAnnotations.initMocks(this);
when(mContext.getResources()).thenReturn(mResources);
- DisplayBrightnessController.Injector injector = new DisplayBrightnessController.Injector() {
- @Override
- DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector(
- Context context, int displayId) {
- return mDisplayBrightnessStrategySelector;
- }
- };
when(mBrightnessSetting.getBrightness()).thenReturn(Float.NaN);
when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(-1f);
when(mResources.getBoolean(
com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay))
.thenReturn(true);
- mDisplayBrightnessController = new DisplayBrightnessController(mContext, injector,
+ mDisplayBrightnessController = new DisplayBrightnessController(mContext, mInjector,
DISPLAY_ID, DEFAULT_BRIGHTNESS, mBrightnessSetting, mOnBrightnessChangeRunnable,
mBrightnessChangeExecutor);
}
@@ -257,27 +262,6 @@
}
@Test
- public void testBrightnessNitsForDefaultDisplay() {
- float brightness = 0.3f;
- float nits = 500;
- AutomaticBrightnessController automaticBrightnessController =
- mock(AutomaticBrightnessController.class);
- when(automaticBrightnessController.convertToFloatScale(nits)).thenReturn(brightness);
- when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits);
-
- mDisplayBrightnessController.setAutomaticBrightnessController(
- automaticBrightnessController);
- assertEquals(brightness, mDisplayBrightnessController.getCurrentBrightness(),
- /* delta= */ 0);
-
- float newBrightness = 0.5f;
- float newNits = 700;
- when(automaticBrightnessController.convertToNits(newBrightness)).thenReturn(newNits);
- mDisplayBrightnessController.setBrightness(newBrightness);
- verify(mBrightnessSetting).setBrightnessNitsForDefaultDisplay(newNits);
- }
-
- @Test
public void testConvertToNits() {
final float brightness = 0.5f;
final float nits = 300;
@@ -330,4 +314,48 @@
mDisplayBrightnessController.stop();
verify(mBrightnessSetting).unregisterListener(brightnessSettingListener);
}
+
+ @Test
+ public void testLoadNitBasedBrightnessSetting() {
+ // When the nits value is valid, the brightness is set from the old default display nits
+ // value
+ float nits = 200f;
+ float brightness = 0.3f;
+ AutomaticBrightnessController automaticBrightnessController =
+ mock(AutomaticBrightnessController.class);
+ when(automaticBrightnessController.convertToFloatScale(nits)).thenReturn(brightness);
+ when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits);
+ mDisplayBrightnessController.setAutomaticBrightnessController(
+ automaticBrightnessController);
+ verify(mBrightnessSetting).setBrightness(brightness);
+ assertEquals(brightness, mDisplayBrightnessController.getCurrentBrightness(), 0.01f);
+ clearInvocations(automaticBrightnessController, mBrightnessSetting);
+
+ // When the nits value is invalid, the brightness is resumed from where it was last set
+ nits = -1;
+ brightness = 0.4f;
+ when(automaticBrightnessController.convertToFloatScale(nits)).thenReturn(brightness);
+ when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits);
+ when(mBrightnessSetting.getBrightness()).thenReturn(brightness);
+ mDisplayBrightnessController.setAutomaticBrightnessController(
+ automaticBrightnessController);
+ verify(mBrightnessSetting, never()).setBrightness(brightness);
+ assertEquals(brightness, mDisplayBrightnessController.getCurrentBrightness(), 0.01f);
+ clearInvocations(automaticBrightnessController, mBrightnessSetting);
+
+ // When the display is a non-default display, the brightness is resumed from where it was
+ // last set
+ int nonDefaultDisplayId = 1;
+ mDisplayBrightnessController = new DisplayBrightnessController(mContext, mInjector,
+ nonDefaultDisplayId, DEFAULT_BRIGHTNESS, mBrightnessSetting,
+ mOnBrightnessChangeRunnable, mBrightnessChangeExecutor);
+ brightness = 0.5f;
+ when(mBrightnessSetting.getBrightness()).thenReturn(brightness);
+ mDisplayBrightnessController.setAutomaticBrightnessController(
+ automaticBrightnessController);
+ assertEquals(brightness, mDisplayBrightnessController.getCurrentBrightness(), 0.01f);
+ verifyZeroInteractions(automaticBrightnessController);
+ verify(mBrightnessSetting, never()).getBrightnessNitsForDefaultDisplay();
+ verify(mBrightnessSetting, never()).setBrightness(brightness);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
index eb208d2..d9cf15b 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -40,6 +41,7 @@
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
import com.android.server.display.AutomaticBrightnessController;
+import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.brightness.BrightnessReason;
import org.junit.After;
@@ -262,12 +264,13 @@
float automaticScreenBrightness = 0.3f;
AutomaticBrightnessController automaticBrightnessController = mock(
AutomaticBrightnessController.class);
- when(automaticBrightnessController.getAutomaticScreenBrightness()).thenReturn(
- automaticScreenBrightness);
+ when(automaticBrightnessController.getAutomaticScreenBrightness(any(BrightnessEvent.class)))
+ .thenReturn(automaticScreenBrightness);
mAutomaticBrightnessStrategy.setAutomaticBrightnessController(
automaticBrightnessController);
assertEquals(automaticScreenBrightness,
- mAutomaticBrightnessStrategy.getAutomaticScreenBrightness(), 0.0f);
+ mAutomaticBrightnessStrategy.getAutomaticScreenBrightness(
+ new BrightnessEvent(DISPLAY_ID)), 0.0f);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
index 5751db0..275533f 100644
--- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
@@ -446,6 +446,25 @@
}
@Test
+ public void testSetUserReviewGrantedConsentResult_projectionNull_consentNotGranted()
+ throws Exception {
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+ projection.start(mIMediaProjectionCallback);
+ assertThat(mService.isCurrentProjection(projection)).isTrue();
+ doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+ // Some other token.
+ final IMediaProjection otherProjection = null;
+ // Waiting for user to review consent.
+ mService.setContentRecordingSession(mWaitingDisplaySession);
+ mService.setUserReviewGrantedConsentResult(RECORD_CANCEL, otherProjection);
+
+ // Display result is ignored; only the first session is set.
+ verify(mWindowManagerInternal, times(1)).setContentRecordingSession(
+ eq(mWaitingDisplaySession));
+ }
+
+ @Test
public void testSetUserReviewGrantedConsentResult_noVirtualDisplay() throws Exception {
MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
projection.start(mIMediaProjectionCallback);
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java
index d9cd77d..af144cf 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java
@@ -37,7 +37,6 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.annotation.NonNull;
-import android.content.AttributionSource;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.INetd;
@@ -50,7 +49,7 @@
import android.os.PermissionEnforcer;
import android.os.Process;
import android.os.RemoteException;
-import android.permission.PermissionCheckerManager;
+import android.os.test.FakePermissionEnforcer;
import android.platform.test.annotations.Presubmit;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArrayMap;
@@ -90,7 +89,6 @@
private ArgumentCaptor<INetdUnsolicitedEventListener> mUnsolListenerCaptor;
private final MockDependencies mDeps = new MockDependencies();
- private final MockPermissionEnforcer mPermissionEnforcer = new MockPermissionEnforcer();
private final class MockDependencies extends NetworkManagementService.Dependencies {
@Override
@@ -118,24 +116,6 @@
}
}
- private static final class MockPermissionEnforcer extends PermissionEnforcer {
- @Override
- protected int checkPermission(@NonNull String permission,
- @NonNull AttributionSource source) {
- String[] granted = new String [] {
- android.Manifest.permission.NETWORK_SETTINGS,
- android.Manifest.permission.OBSERVE_NETWORK_POLICY,
- android.Manifest.permission.SHUTDOWN
- };
- for (String p : granted) {
- if (p.equals(permission)) {
- return PermissionCheckerManager.PERMISSION_GRANTED;
- }
- }
- return PermissionCheckerManager.PERMISSION_HARD_DENIED;
- }
- }
-
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -145,12 +125,15 @@
eq(ConnectivityManager.class));
doReturn(mCm).when(mContext).getSystemService(eq(Context.CONNECTIVITY_SERVICE));
// The AIDL stub will use PermissionEnforcer to check permission from the caller.
- // Mock the service. See MockPermissionEnforcer above.
+ // Mock the service and grant the expected permissions.
+ FakePermissionEnforcer permissionEnforcer = new FakePermissionEnforcer();
+ permissionEnforcer.grant(android.Manifest.permission.NETWORK_SETTINGS);
+ permissionEnforcer.grant(android.Manifest.permission.OBSERVE_NETWORK_POLICY);
+ permissionEnforcer.grant(android.Manifest.permission.SHUTDOWN);
doReturn(Context.PERMISSION_ENFORCER_SERVICE).when(mContext).getSystemServiceName(
eq(PermissionEnforcer.class));
- doReturn(mPermissionEnforcer).when(mContext).getSystemService(
+ doReturn(permissionEnforcer).when(mContext).getSystemService(
eq(Context.PERMISSION_ENFORCER_SERVICE));
-
// Start the service and wait until it connects to our socket.
mNMService = NetworkManagementService.create(mContext, mDeps);
}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 21a11bc..52bf244 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -40,6 +40,7 @@
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -1611,7 +1612,8 @@
startSystem();
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
- verify(mNotifierMock, never()).onWakefulnessChangeStarted(anyInt(), anyInt(), anyLong());
+ verify(mNotifierMock, never()).onGlobalWakefulnessChangeStarted(anyInt(), anyInt(),
+ anyLong());
}
@Test
@@ -1630,7 +1632,7 @@
startSystem();
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
- verify(mNotifierMock).onWakefulnessChangeStarted(eq(WAKEFULNESS_ASLEEP), anyInt(),
+ verify(mNotifierMock).onGlobalWakefulnessChangeStarted(eq(WAKEFULNESS_ASLEEP), anyInt(),
anyLong());
}
@@ -2112,7 +2114,7 @@
}
@Test
- public void testMultiDisplay_defaultDozing_addNewDisplayDefaultGoesBackToDoze() {
+ public void testMultiDisplay_addNewDisplay_becomeGloballyAwakeButDefaultRemainsDozing() {
final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
final int nonDefaultDisplay = Display.DEFAULT_DISPLAY + 1;
final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener =
@@ -2142,6 +2144,7 @@
assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
WAKEFULNESS_DOZING);
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
+ verify(mDreamManagerInternalMock).stopDream(anyBoolean(), anyString());
verify(mDreamManagerInternalMock).startDream(eq(true), anyString());
listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);
@@ -2152,7 +2155,10 @@
WAKEFULNESS_AWAKE);
assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
WAKEFULNESS_DOZING);
- verify(mDreamManagerInternalMock, times(2)).startDream(eq(true), anyString());
+
+ // Make sure there were no additional calls to stopDream or startDream
+ verify(mDreamManagerInternalMock, atMost(1)).stopDream(anyBoolean(), anyString());
+ verify(mDreamManagerInternalMock, atMost(1)).startDream(eq(true), anyString());
}
@Test
@@ -2169,7 +2175,7 @@
}
@Test
- public void testMultiDisplay_onlyOneDisplaySleeps_onWakefulnessChangedEventFires() {
+ public void testMultiDisplay_onlyOneDisplaySleeps_onWakefulnessChangedEventsFire() {
createService();
startSystem();
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
@@ -2177,12 +2183,14 @@
assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
WAKEFULNESS_ASLEEP);
- verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(Display.DEFAULT_DISPLAY_GROUP),
- eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_ASLEEP));
+ verify(mNotifierMock).onGroupWakefulnessChangeStarted(eq(Display.DEFAULT_DISPLAY_GROUP),
+ eq(WAKEFULNESS_ASLEEP), eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), anyLong());
+ verify(mNotifierMock).onGlobalWakefulnessChangeStarted(eq(WAKEFULNESS_ASLEEP),
+ eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), anyLong());
}
@Test
- public void testMultiDisplay_bothDisplaysSleep_onWakefulnessChangedEventFiresCorrectly() {
+ public void testMultiDisplay_bothDisplaysSleep_onWakefulnessChangedEventsFireCorrectly() {
final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
final int nonDefaultDisplay = Display.DEFAULT_DISPLAY + 1;
final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener =
@@ -2201,10 +2209,10 @@
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);
- mService.setWakefulnessLocked(nonDefaultDisplayGroupId, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
- null, null);
- mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
- null, null);
+ mService.setWakefulnessLocked(nonDefaultDisplayGroupId, WAKEFULNESS_ASLEEP, 0, 0,
+ PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0, null, null);
+ mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0,
+ PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0, null, null);
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
@@ -2212,14 +2220,16 @@
assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
WAKEFULNESS_ASLEEP);
- verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(nonDefaultDisplayGroupId),
- eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_AWAKE));
- verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(Display.DEFAULT_DISPLAY_GROUP),
- eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_ASLEEP));
+ verify(mNotifierMock).onGroupWakefulnessChangeStarted(eq(nonDefaultDisplayGroupId),
+ eq(WAKEFULNESS_ASLEEP), eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), anyLong());
+ verify(mNotifierMock).onGroupWakefulnessChangeStarted(eq(Display.DEFAULT_DISPLAY_GROUP),
+ eq(WAKEFULNESS_ASLEEP), eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), anyLong());
+ verify(mNotifierMock).onGlobalWakefulnessChangeStarted(eq(WAKEFULNESS_ASLEEP),
+ eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), anyLong());
}
@Test
- public void testMultiDisplay_separateWakeStates_onWakefulnessChangedEventFiresCorrectly() {
+ public void testMultiDisplay_separateWakeStates_onWakefulnessChangedEventsFireCorrectly() {
final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
final int nonDefaultDisplay = Display.DEFAULT_DISPLAY + 1;
final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener =
@@ -2255,10 +2265,53 @@
WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
WAKEFULNESS_AWAKE);
- verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(Display.DEFAULT_DISPLAY_GROUP),
- eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_AWAKE));
- verify(mNotifierMock, never()).onPowerGroupWakefulnessChanged(
- eq(nonDefaultDisplayGroupId), anyInt(), anyInt(), anyInt());
+ verify(mNotifierMock).onGroupWakefulnessChangeStarted(eq(nonDefaultDisplayGroupId),
+ eq(WAKEFULNESS_AWAKE), eq(PowerManager.WAKE_REASON_DISPLAY_GROUP_ADDED), anyLong());
+ verify(mNotifierMock).onGroupWakefulnessChangeStarted(eq(Display.DEFAULT_DISPLAY_GROUP),
+ eq(WAKEFULNESS_ASLEEP), eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), anyLong());
+ verify(mNotifierMock, never()).onGlobalWakefulnessChangeStarted(eq(WAKEFULNESS_ASLEEP),
+ anyInt(), anyLong());
+ }
+
+ @Test
+ public void testMultiDisplay_oneDisplayGroupChanges_globalDoesNotChange() {
+ final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
+ final int nonDefaultDisplay = Display.DEFAULT_DISPLAY + 1;
+ final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener =
+ new AtomicReference<>();
+ doAnswer((Answer<Void>) invocation -> {
+ listener.set(invocation.getArgument(0));
+ return null;
+ }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any());
+ final DisplayInfo info = new DisplayInfo();
+ info.displayGroupId = nonDefaultDisplayGroupId;
+ when(mDisplayManagerInternalMock.getDisplayInfo(nonDefaultDisplay)).thenReturn(info);
+
+ createService();
+ startSystem();
+
+ listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);
+
+ assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
+ WAKEFULNESS_AWAKE);
+ assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
+ WAKEFULNESS_AWAKE);
+ assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+
+ long eventTime = mClock.now();
+ mService.setWakefulnessLocked(nonDefaultDisplayGroupId, WAKEFULNESS_ASLEEP, eventTime, 0,
+ PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0, null, null);
+
+ assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
+ WAKEFULNESS_AWAKE);
+ assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
+ WAKEFULNESS_ASLEEP);
+ assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+ verify(mNotifierMock, never()).onGlobalWakefulnessChangeStarted(anyInt(), anyInt(),
+ anyLong());
+ verify(mNotifierMock, atMost(1)).onGroupWakefulnessChangeStarted(
+ eq(nonDefaultDisplayGroupId), eq(WAKEFULNESS_ASLEEP),
+ eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), eq(eventTime));
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index 2665e19..3513557 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -202,9 +202,11 @@
.canonicalToCurrentPackageNames(any());
} catch (PackageManager.NameNotFoundException ignored) { }
- doReturn(mTelecomManager).when(mContext).getSystemService(eq(Context.TELECOM_SERVICE));
- doReturn(mNotificationManager).when(mContext)
- .getSystemService(eq(NotificationManager.class));
+ doReturn(false).when(mTelecomManager).isInCall();
+ doReturn(false).when(mTelecomManager).isRinging();
+ doReturn(mTelecomManager).when(mPhoneWindowManager).getTelecommService();
+ doNothing().when(mNotificationManager).silenceNotificationSound();
+ doReturn(mNotificationManager).when(mPhoneWindowManager).getNotificationService();
doReturn(mVibrator).when(mContext).getSystemService(eq(Context.VIBRATOR_SERVICE));
final PowerManager.WakeLock wakeLock = mock(PowerManager.WakeLock.class);
@@ -233,8 +235,9 @@
doNothing().when(mPhoneWindowManager).updateSettings();
doNothing().when(mPhoneWindowManager).screenTurningOn(anyInt(), any());
doNothing().when(mPhoneWindowManager).screenTurnedOn(anyInt());
- doNothing().when(mPhoneWindowManager).startedWakingUp(anyInt());
- doNothing().when(mPhoneWindowManager).finishedWakingUp(anyInt());
+ doNothing().when(mPhoneWindowManager).startedWakingUp(anyInt(), anyInt());
+ doNothing().when(mPhoneWindowManager).finishedWakingUp(anyInt(), anyInt());
+ doNothing().when(mPhoneWindowManager).lockNow(any());
mPhoneWindowManager.init(new TestInjector(mContext, mWindowManagerFuncsImpl));
mPhoneWindowManager.systemReady();
@@ -249,6 +252,7 @@
void tearDown() {
mHandlerThread.quitSafely();
LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
+ Mockito.reset(mPhoneWindowManager);
mMockitoSession.finishMocking();
}
@@ -322,6 +326,7 @@
void overrideDisplayState(int state) {
doReturn(state).when(mDisplay).getState();
+ doReturn(state == STATE_ON).when(mDisplayPolicy).isAwake();
Mockito.reset(mPowerManager);
}
@@ -388,6 +393,7 @@
}
void assertDreamRequest() {
+ waitForIdle();
verify(mDreamManagerInternal).requestDream();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 0033e3e..cb984f8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -851,7 +851,7 @@
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
}
}, 0, 0));
activity.updateOptionsLocked(opts);
@@ -3124,7 +3124,7 @@
.setSystemDecorations(true).build();
// Add a decor insets provider window.
final WindowState navbar = createNavBarWithProvidedInsets(squareDisplay);
- assertTrue(navbar.providesNonDecorInsets()
+ assertTrue(navbar.providesDisplayDecorInsets()
&& squareDisplay.getDisplayPolicy().updateDecorInsetsInfo());
squareDisplay.sendNewConfiguration();
final Task task = new TaskBuilder(mSupervisor).setDisplay(squareDisplay).build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 6d13124..169968c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -87,7 +87,7 @@
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 0ae579b..a11079b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -735,7 +735,7 @@
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException {
+ public void onAnimationCancelled() throws RemoteException {
mFinishedCallback = null;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 59cc4f5..ba8c94d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -549,7 +549,7 @@
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
mCancelled = true;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java b/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
index 06b4ad9..7b4392b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
@@ -50,7 +50,6 @@
import android.util.Log;
import android.view.IWindowManager;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import com.android.server.am.AssistDataRequester;
@@ -155,7 +154,6 @@
}
@Test
- @FlakyTest(bugId = 130388718)
public void testRequestData() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
CALLER_ASSIST_SCREENSHOT_ALLOWED);
@@ -263,7 +261,6 @@
}
@Test
- @FlakyTest(bugId = 130388718)
public void testNoFetchScreenshots_expectNoScreenshotCallbacks() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
CALLER_ASSIST_SCREENSHOT_ALLOWED);
@@ -275,7 +272,6 @@
}
@Test
- @FlakyTest(bugId = 130388718)
public void testDisallowAssistScreenshot_expectNullScreenshotCallback() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
!CALLER_ASSIST_SCREENSHOT_ALLOWED);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index c8fdee0..353a8ec 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -45,6 +45,8 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -298,20 +300,27 @@
@Test
public void testUpdateDisplayConfigurationByDecor() {
+ doReturn(NO_CUTOUT).when(mDisplayContent).calculateDisplayCutoutForRotation(anyInt());
final WindowState navbar = createNavBarWithProvidedInsets(mDisplayContent);
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
final DisplayInfo di = mDisplayContent.getDisplayInfo();
final int prevScreenHeightDp = mDisplayContent.getConfiguration().screenHeightDp;
- assertTrue(navbar.providesNonDecorInsets() && displayPolicy.updateDecorInsetsInfo());
+ assertTrue(navbar.providesDisplayDecorInsets() && displayPolicy.updateDecorInsetsInfo());
assertEquals(NAV_BAR_HEIGHT, displayPolicy.getDecorInsetsInfo(di.rotation,
di.logicalWidth, di.logicalHeight).mConfigInsets.bottom);
mDisplayContent.sendNewConfiguration();
assertNotEquals(prevScreenHeightDp, mDisplayContent.getConfiguration().screenHeightDp);
- assertFalse(navbar.providesNonDecorInsets() && displayPolicy.updateDecorInsetsInfo());
+ assertFalse(navbar.providesDisplayDecorInsets() && displayPolicy.updateDecorInsetsInfo());
navbar.removeIfPossible();
assertEquals(0, displayPolicy.getDecorInsetsInfo(di.rotation, di.logicalWidth,
di.logicalHeight).mNonDecorInsets.bottom);
+
+ final WindowState statusBar = createStatusBarWithProvidedInsets(mDisplayContent);
+ assertTrue(statusBar.providesDisplayDecorInsets()
+ && displayPolicy.updateDecorInsetsInfo());
+ assertEquals(STATUS_BAR_HEIGHT, displayPolicy.getDecorInsetsInfo(di.rotation,
+ di.logicalWidth, di.logicalHeight).mConfigInsets.top);
}
@SetupWindows(addWindows = { W_NAVIGATION_BAR, W_INPUT_METHOD })
diff --git a/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java b/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
index 027f903..8cf2776 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
@@ -27,7 +27,6 @@
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import org.junit.After;
@@ -110,7 +109,6 @@
}
@Test
- @FlakyTest(bugId = 131005232)
public void testProcessOneItem_Flush() throws Exception {
mFactory.setExpectedProcessedItemNumber(1);
mListener.setExpectedOnPreProcessItemCallbackTimes(1);
@@ -162,7 +160,6 @@
}
@Test
- @FlakyTest(bugId = 128526085)
public void testProcessTwoItems_OneAfterAnother() throws Exception {
// First item
mFactory.setExpectedProcessedItemNumber(1);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
index 0db983c..c4d03be 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
@@ -37,7 +37,6 @@
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.server.wm.RefreshRatePolicy.FrameRateVote;
@@ -53,7 +52,6 @@
@SmallTest
@Presubmit
@RunWith(WindowTestRunner.class)
-@FlakyTest
public class RefreshRatePolicyTest extends WindowTestsBase {
private static final int HI_MODE_ID = 1;
private static final float HI_REFRESH_RATE = 90;
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index eb26415..11d9629 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -211,7 +211,7 @@
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
adapter.onAnimationCancelled(mMockLeash);
- verify(mMockRunner).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner).onAnimationCancelled();
}
@Test
@@ -227,7 +227,7 @@
mClock.fastForward(10500);
mHandler.timeAdvance();
- verify(mMockRunner).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner).onAnimationCancelled();
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
eq(adapter));
}
@@ -248,12 +248,12 @@
mClock.fastForward(10500);
mHandler.timeAdvance();
- verify(mMockRunner, never()).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner, never()).onAnimationCancelled();
mClock.fastForward(52500);
mHandler.timeAdvance();
- verify(mMockRunner).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner).onAnimationCancelled();
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
eq(adapter));
} finally {
@@ -265,7 +265,7 @@
public void testZeroAnimations() throws Exception {
mController.goodToGo(TRANSIT_OLD_NONE);
verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
- verify(mMockRunner).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner).onAnimationCancelled();
}
@Test
@@ -275,7 +275,7 @@
new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
- verify(mMockRunner).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner).onAnimationCancelled();
}
@Test
@@ -317,7 +317,7 @@
win.mActivityRecord.removeImmediately();
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
- verify(mMockRunner).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner).onAnimationCancelled();
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
eq(adapter));
}
@@ -575,7 +575,7 @@
// Cancel the wallpaper window animator and ensure the runner is not canceled
wallpaperWindowToken.cancelAnimation();
- verify(mMockRunner, never()).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner, never()).onAnimationCancelled();
} finally {
mDisplayContent.mOpeningApps.clear();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index ff753f2..339162a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -98,7 +98,6 @@
mFinishCallbackLatch.countDown();
}
- @FlakyTest(bugId = 144611135)
@Test
public void testAnimation() throws Exception {
mSurfaceAnimationRunner
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceControlTests.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceControlTests.java
index 342ab83..4f45d5c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceControlTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceControlTests.java
@@ -125,9 +125,10 @@
public void testSurfaceChangedOnRotation() {
final Instrumentation instrumentation = getInstrumentation();
final Context context = instrumentation.getContext();
- final Activity activity = instrumentation.startActivitySync(new Intent().setComponent(
+ final Intent intent = new Intent().setComponent(
new ComponentName(context, ActivityOptionsTest.MainActivity.class))
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ final Activity activity = instrumentation.startActivitySync(intent);
final SurfaceView sv = new SurfaceView(activity);
final AtomicInteger surfaceChangedCount = new AtomicInteger();
instrumentation.runOnMainSync(() -> activity.setContentView(sv));
@@ -157,12 +158,27 @@
instrumentation.waitForIdleSync();
final int newRotation = activity.getResources().getConfiguration()
.windowConfiguration.getRotation();
+ if (rotation == newRotation) {
+ // The device might not support requested orientation.
+ activity.finishAndRemoveTask();
+ return;
+ }
final int count = surfaceChangedCount.get();
+ activity.moveTaskToBack(true /* nonRoot */);
+ instrumentation.getUiAutomation().syncInputTransactions();
+ context.startActivity(intent);
+ instrumentation.getUiAutomation().syncInputTransactions();
+ final int countAfterToFront = count - surfaceChangedCount.get();
activity.finishAndRemoveTask();
+
// The first count is triggered from creation, so the target number is 2.
- if (rotation != newRotation && count > 2) {
+ if (count > 2) {
fail("More than once surfaceChanged for rotation change: " + count);
}
+ if (countAfterToFront > 1) {
+ fail("More than once surfaceChanged for app transition with rotation change: "
+ + countAfterToFront);
+ }
}
private SurfaceControl buildTestSurface() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
index d43805a..c53addc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
@@ -63,6 +63,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.List;
+
/**
* Tests for the {@link TaskDisplayArea} container.
*
@@ -349,23 +351,24 @@
@Test
public void testReuseTaskAsRootTask() {
final Task candidateTask = createTask(mDisplayContent);
- final int type = ACTIVITY_TYPE_STANDARD;
- assertGetOrCreateRootTask(WINDOWING_MODE_FULLSCREEN, type, candidateTask,
- true /* reuseCandidate */);
- assertGetOrCreateRootTask(WINDOWING_MODE_UNDEFINED, type, candidateTask,
- true /* reuseCandidate */);
- assertGetOrCreateRootTask(WINDOWING_MODE_FREEFORM, type, candidateTask,
- true /* reuseCandidate */);
- assertGetOrCreateRootTask(WINDOWING_MODE_MULTI_WINDOW, type, candidateTask,
- true /* reuseCandidate */);
- assertGetOrCreateRootTask(WINDOWING_MODE_PINNED, type, candidateTask,
- true /* reuseCandidate */);
+ List<Integer> activityTypesWithReusableRootTask = List.of(ACTIVITY_TYPE_STANDARD,
+ ACTIVITY_TYPE_RECENTS);
+ for (Integer type : activityTypesWithReusableRootTask) {
+ assertGetOrCreateRootTask(WINDOWING_MODE_FULLSCREEN, type, candidateTask,
+ true /* reuseCandidate */);
+ assertGetOrCreateRootTask(WINDOWING_MODE_UNDEFINED, type, candidateTask,
+ true /* reuseCandidate */);
+ assertGetOrCreateRootTask(WINDOWING_MODE_FREEFORM, type, candidateTask,
+ true /* reuseCandidate */);
+ assertGetOrCreateRootTask(WINDOWING_MODE_MULTI_WINDOW, type, candidateTask,
+ true /* reuseCandidate */);
+ assertGetOrCreateRootTask(WINDOWING_MODE_PINNED, type, candidateTask,
+ true /* reuseCandidate */);
+ }
final int windowingMode = WINDOWING_MODE_FULLSCREEN;
assertGetOrCreateRootTask(windowingMode, ACTIVITY_TYPE_HOME, candidateTask,
false /* reuseCandidate */);
- assertGetOrCreateRootTask(windowingMode, ACTIVITY_TYPE_RECENTS, candidateTask,
- false /* reuseCandidate */);
assertGetOrCreateRootTask(windowingMode, ACTIVITY_TYPE_ASSISTANT, candidateTask,
false /* reuseCandidate */);
assertGetOrCreateRootTask(windowingMode, ACTIVITY_TYPE_DREAM, candidateTask,
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index 790b154..453e468 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -52,7 +52,6 @@
import android.view.ViewGroup;
import android.widget.LinearLayout;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import org.junit.After;
@@ -319,7 +318,6 @@
};
@Presubmit
- @FlakyTest(bugId = 150409355)
@Test
public void testNotifyTaskRequestedOrientationChanged() throws Exception {
final ArrayBlockingQueue<int[]> taskIdAndOrientationQueue = new ArrayBlockingQueue<>(10);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 32033fb..adf3f39 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -114,24 +114,35 @@
}
@Override
- public void startedWakingUp(@WakeReason int wakeReason) {
+ public void startedWakingUpGlobal(@WakeReason int reason) {
}
@Override
- public void finishedWakingUp(@WakeReason int wakeReason) {
+ public void finishedWakingUpGlobal(@WakeReason int reason) {
}
@Override
- public void startedGoingToSleep(@GoToSleepReason int sleepReason) {
+ public void startedGoingToSleepGlobal(@GoToSleepReason int reason) {
}
@Override
- public void finishedGoingToSleep(@GoToSleepReason int sleepReason) {
+ public void finishedGoingToSleepGlobal(@GoToSleepReason int reason) {
}
@Override
- public void onPowerGroupWakefulnessChanged(int groupId, int wakefulness,
- @GoToSleepReason int pmSleepReason, int globalWakefulness) {
+ public void startedWakingUp(int displayGroupId, @WakeReason int wakeReason) {
+ }
+
+ @Override
+ public void finishedWakingUp(int displayGroupId, @WakeReason int wakeReason) {
+ }
+
+ @Override
+ public void startedGoingToSleep(int displayGroupId, @GoToSleepReason int sleepReason) {
+ }
+
+ @Override
+ public void finishedGoingToSleep(int displayGroupId, @GoToSleepReason int sleepReason) {
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index a1ddd57..ad606cb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -1112,7 +1112,7 @@
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
}
}, 0, 0, false);
adapter.setCallingPidUid(123, 456);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
index 0b1b877..2ae1172 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
@@ -26,7 +26,6 @@
import android.hardware.HardwareBuffer;
import android.platform.test.annotations.Presubmit;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import org.junit.Test;
@@ -55,7 +54,6 @@
}
@Test
- @FlakyTest(bugId = 131005232)
public void testDestroy_nullsSurface() {
final WindowContainerThumbnail t = buildThumbnail();
assertNotNull(t.getSurfaceControl());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index ba6b3b6..58bf184 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -27,6 +27,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_OWN_FOCUS;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
@@ -65,6 +66,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
@@ -89,6 +91,7 @@
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
import android.window.ClientWindowFrames;
import android.window.ScreenCapture;
import android.window.WindowContainerToken;
@@ -101,6 +104,7 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
/**
* Build/Install/Run:
@@ -272,6 +276,124 @@
}
@Test
+ public void testRelayout_firstLayout_dwpcHelperCalledWithCorrectFlags() {
+ // When doing the first layout, the initial flags should be reported as changed to
+ // keepActivityOnWindowFlagsChanged.
+ testRelayoutFlagChanges(
+ /*firstRelayout=*/ true,
+ /*startFlags=*/ FLAG_SECURE,
+ /*startPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*newFlags=*/ FLAG_SECURE,
+ /*newPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*expectedChangedFlags=*/ FLAG_SECURE,
+ /*expectedChangedPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*expectedFlagsValue=*/ FLAG_SECURE,
+ /*expectedPrivateFlagsValue=*/ PRIVATE_FLAG_TRUSTED_OVERLAY);
+ }
+
+ @Test
+ public void testRelayout_secondLayoutFlagAdded_dwpcHelperCalledWithCorrectFlags() {
+ testRelayoutFlagChanges(
+ /*firstRelayout=*/ false,
+ /*startFlags=*/ 0,
+ /*startPrivateFlags=*/ 0,
+ /*newFlags=*/ FLAG_SECURE,
+ /*newPrivateFlags=*/ 0,
+ /*expectedChangedFlags=*/ FLAG_SECURE,
+ /*expectedChangedPrivateFlags=*/ 0,
+ /*expectedFlagsValue=*/ FLAG_SECURE,
+ /*expectedPrivateFlagsValue=*/ 0);
+ }
+
+ @Test
+ public void testRelayout_secondLayoutMultipleFlagsAddOne_dwpcHelperCalledWithCorrectFlags() {
+ testRelayoutFlagChanges(
+ /*firstRelayout=*/ false,
+ /*startFlags=*/ FLAG_NOT_FOCUSABLE,
+ /*startPrivateFlags=*/ 0,
+ /*newFlags=*/ FLAG_SECURE | FLAG_NOT_FOCUSABLE,
+ /*newPrivateFlags=*/ 0,
+ /*expectedChangedFlags=*/ FLAG_SECURE,
+ /*expectedChangedPrivateFlags=*/ 0,
+ /*expectedFlagsValue=*/ FLAG_SECURE | FLAG_NOT_FOCUSABLE,
+ /*expectedPrivateFlagsValue=*/ 0);
+ }
+
+ @Test
+ public void testRelayout_secondLayoutPrivateFlagAdded_dwpcHelperCalledWithCorrectFlags() {
+ testRelayoutFlagChanges(
+ /*firstRelayout=*/ false,
+ /*startFlags=*/ 0,
+ /*startPrivateFlags=*/ 0,
+ /*newFlags=*/ 0,
+ /*newPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*expectedChangedFlags=*/ 0,
+ /*expectedChangedPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*expectedFlagsValue=*/ 0,
+ /*expectedPrivateFlagsValue=*/ PRIVATE_FLAG_TRUSTED_OVERLAY);
+ }
+
+ @Test
+ public void testRelayout_secondLayoutFlagsRemoved_dwpcHelperCalledWithCorrectFlags() {
+ testRelayoutFlagChanges(
+ /*firstRelayout=*/ false,
+ /*startFlags=*/ FLAG_SECURE,
+ /*startPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*newFlags=*/ 0,
+ /*newPrivateFlags=*/ 0,
+ /*expectedChangedFlags=*/ FLAG_SECURE,
+ /*expectedChangedPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*expectedFlagsValue=*/ 0,
+ /*expectedPrivateFlagsValue=*/ 0);
+ }
+
+ // Helper method to test relayout of a window, either for the initial layout, or a subsequent
+ // one, and makes sure that the flags and private flags changes and final values are properly
+ // reported to mDwpcHelper.keepActivityOnWindowFlagsChanged.
+ private void testRelayoutFlagChanges(boolean firstRelayout, int startFlags,
+ int startPrivateFlags, int newFlags, int newPrivateFlags, int expectedChangedFlags,
+ int expectedChangedPrivateFlags, int expectedFlagsValue,
+ int expectedPrivateFlagsValue) {
+ final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "appWin");
+ win.mRelayoutCalled = !firstRelayout;
+ mWm.mWindowMap.put(win.mClient.asBinder(), win);
+ spyOn(mDisplayContent.mDwpcHelper);
+ when(mDisplayContent.mDwpcHelper.hasController()).thenReturn(true);
+
+ win.mAttrs.flags = startFlags;
+ win.mAttrs.privateFlags = startPrivateFlags;
+
+ LayoutParams newParams = new LayoutParams();
+ newParams.copyFrom(win.mAttrs);
+ newParams.flags = newFlags;
+ newParams.privateFlags = newPrivateFlags;
+
+ int seq = 1;
+ if (!firstRelayout) {
+ win.mRelayoutSeq = 1;
+ seq = 2;
+ }
+ mWm.relayoutWindow(win.mSession, win.mClient, newParams, 100, 200, View.VISIBLE, 0, seq,
+ 0, new ClientWindowFrames(), new MergedConfiguration(),
+ new SurfaceControl(), new InsetsState(), new InsetsSourceControl.Array(),
+ new Bundle());
+
+ ArgumentCaptor<Integer> changedFlags = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> changedPrivateFlags = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> flagsValue = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> privateFlagsValue = ArgumentCaptor.forClass(Integer.class);
+
+ verify(mDisplayContent.mDwpcHelper).keepActivityOnWindowFlagsChanged(
+ any(ActivityInfo.class), changedFlags.capture(), changedPrivateFlags.capture(),
+ flagsValue.capture(), privateFlagsValue.capture());
+
+ assertThat(changedFlags.getValue()).isEqualTo(expectedChangedFlags);
+ assertThat(changedPrivateFlags.getValue()).isEqualTo(expectedChangedPrivateFlags);
+ assertThat(flagsValue.getValue()).isEqualTo(expectedFlagsValue);
+ assertThat(privateFlagsValue.getValue()).isEqualTo(expectedPrivateFlagsValue);
+ }
+
+ @Test
public void testMoveWindowTokenToDisplay_NullToken_DoNothing() {
mWm.moveWindowTokenToDisplay(null, mDisplayContent.getDisplayId());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 07244a4..a63807d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -471,6 +471,17 @@
return navbar;
}
+ WindowState createStatusBarWithProvidedInsets(DisplayContent dc) {
+ final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, dc, "statusBar");
+ final Binder owner = new Binder();
+ statusBar.mAttrs.providedInsets = new InsetsFrameProvider[] {
+ new InsetsFrameProvider(owner, 0, WindowInsets.Type.statusBars())
+ .setInsetsSize(Insets.of(0, STATUS_BAR_HEIGHT, 0, 0))
+ };
+ dc.getDisplayPolicy().addWindowLw(statusBar, statusBar.mAttrs);
+ return statusBar;
+ }
+
WindowState createAppWindow(Task task, int type, String name) {
final ActivityRecord activity = createNonAttachedActivityRecord(task.getDisplayContent());
task.addChild(activity, 0);
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
index 10b7952..ba17884 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
@@ -584,15 +584,34 @@
}
/**
+ * Returns true only if there is a terminal whose subtype and terminal type are the same as
+ * the given values.
* @hide
*/
- public boolean hasAudioTerminal(int subType) {
+ public boolean hasAudioTerminal(int subType, int terminalType) {
for (UsbDescriptor descriptor : mDescriptors) {
- if (descriptor instanceof UsbACInterface) {
- if (((UsbACInterface) descriptor).getSubclass()
- == UsbDescriptor.AUDIO_AUDIOCONTROL
- && ((UsbACInterface) descriptor).getSubtype()
- == subType) {
+ if (descriptor instanceof UsbACTerminal) {
+ if (((UsbACTerminal) descriptor).getSubclass() == UsbDescriptor.AUDIO_AUDIOCONTROL
+ && ((UsbACTerminal) descriptor).getSubtype() == subType
+ && ((UsbACTerminal) descriptor).getTerminalType() == terminalType) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true only if there is an interface whose subtype is the same as the given one and
+ * terminal type is different from the given one.
+ * @hide
+ */
+ public boolean hasAudioTerminalExcludeType(int subType, int excludedTerminalType) {
+ for (UsbDescriptor descriptor : mDescriptors) {
+ if (descriptor instanceof UsbACTerminal) {
+ if (((UsbACTerminal) descriptor).getSubclass() == UsbDescriptor.AUDIO_AUDIOCONTROL
+ && ((UsbACTerminal) descriptor).getSubtype() == subType
+ && ((UsbACTerminal) descriptor).getTerminalType() != excludedTerminalType) {
return true;
}
}
@@ -604,14 +623,21 @@
* @hide
*/
public boolean hasAudioPlayback() {
- return hasAudioTerminal(UsbACInterface.ACI_OUTPUT_TERMINAL);
+ return hasAudioTerminalExcludeType(
+ UsbACInterface.ACI_OUTPUT_TERMINAL, UsbTerminalTypes.TERMINAL_USB_STREAMING)
+ && hasAudioTerminal(
+ UsbACInterface.ACI_INPUT_TERMINAL, UsbTerminalTypes.TERMINAL_USB_STREAMING);
}
/**
* @hide
*/
public boolean hasAudioCapture() {
- return hasAudioTerminal(UsbACInterface.ACI_INPUT_TERMINAL);
+ return hasAudioTerminalExcludeType(
+ UsbACInterface.ACI_INPUT_TERMINAL, UsbTerminalTypes.TERMINAL_USB_STREAMING)
+ && hasAudioTerminal(
+ UsbACInterface.ACI_OUTPUT_TERMINAL,
+ UsbTerminalTypes.TERMINAL_USB_STREAMING);
}
/**
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index bee75df..255db1e 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -1043,7 +1043,13 @@
internalClearGlobalStateLocked();
if (mModule != null) {
mModule.detach();
- mModule = mModuleProvider.apply(this);
+ try {
+ // This is best effort
+ // TODO (b/279507851)
+ mModule = mModuleProvider.apply(this);
+ } catch (Exception e) {
+ mModule = null;
+ }
}
}
}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 77e5317..913535e 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -57,6 +57,7 @@
import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
import android.hardware.soundtrigger.SoundTrigger.SoundModel;
+import android.hardware.soundtrigger.SoundTriggerModule;
import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioRecord;
@@ -134,6 +135,8 @@
private Object mLock;
private final SoundTriggerServiceStub mServiceStub;
private final LocalSoundTriggerService mLocalSoundTriggerService;
+
+ private ISoundTriggerMiddlewareService mMiddlewareService;
private SoundTriggerDbHelper mDbHelper;
private final EventLogger mServiceEventLogger = new EventLogger(256, "Service");
@@ -241,17 +244,18 @@
if (PHASE_THIRD_PARTY_APPS_CAN_START == phase) {
mDbHelper = new SoundTriggerDbHelper(mContext);
}
+ mMiddlewareService = ISoundTriggerMiddlewareService.Stub.asInterface(
+ ServiceManager.waitForService(Context.SOUND_TRIGGER_MIDDLEWARE_SERVICE));
+
}
// Must be called with cleared binder context.
- private static List<ModuleProperties> listUnderlyingModuleProperties(
+ private List<ModuleProperties> listUnderlyingModuleProperties(
Identity originatorIdentity) {
Identity middlemanIdentity = new Identity();
middlemanIdentity.packageName = ActivityThread.currentOpPackageName();
- var service = ISoundTriggerMiddlewareService.Stub.asInterface(
- ServiceManager.waitForService(Context.SOUND_TRIGGER_MIDDLEWARE_SERVICE));
try {
- return Arrays.stream(service.listModulesAsMiddleman(middlemanIdentity,
+ return Arrays.stream(mMiddlewareService.listModulesAsMiddleman(middlemanIdentity,
originatorIdentity))
.map(desc -> ConversionUtil.aidl2apiModuleDescriptor(desc))
.collect(Collectors.toList());
@@ -282,10 +286,9 @@
return new SoundTriggerHelper(
mContext,
eventLogger,
- (SoundTrigger.StatusListener statusListener) ->
- SoundTrigger.attachModuleAsMiddleman(
- moduleId, statusListener, null /* handler */,
- middlemanIdentity, originatorIdentity),
+ (SoundTrigger.StatusListener statusListener) -> new SoundTriggerModule(
+ mMiddlewareService, moduleId, statusListener,
+ Looper.getMainLooper(), middlemanIdentity, originatorIdentity),
moduleId,
() -> listUnderlyingModuleProperties(originatorIdentity)
);
@@ -293,7 +296,10 @@
// Helper to add session logger to the capacity limited detached list.
// If we are at capacity, remove the oldest, and retry
- private void addDetachedSessionLogger(EventLogger logger) {
+ private void detachSessionLogger(EventLogger logger) {
+ if (!mSessionEventLoggers.remove(logger)) {
+ return;
+ }
// Attempt to push to the top of the queue
while (!mDetachedSessionEventLoggers.offerFirst(logger)) {
// Remove the oldest element, if one still exists
@@ -869,8 +875,7 @@
private void detach() {
mSoundTriggerHelper.detach();
- mSessionEventLoggers.remove(mEventLogger);
- addDetachedSessionLogger(mEventLogger);
+ detachSessionLogger(mEventLogger);
}
private void enforceCallingPermission(String permission) {
@@ -1656,8 +1661,7 @@
private void detachInternal() {
mEventLogger.enqueue(new SessionEvent(Type.DETACH, null));
- mSessionEventLoggers.remove(mEventLogger);
- addDetachedSessionLogger(mEventLogger);
+ detachSessionLogger(mEventLogger);
mSoundTriggerHelper.detach();
}
}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
index 13fe14c..00cedd7 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
@@ -78,7 +78,7 @@
public @NonNull
SoundTriggerModuleDescriptor[] listModules() {
Identity identity = getIdentity();
- enforcePermissionsForPreflight(identity);
+ enforcePermissionForPreflight(mContext, identity, CAPTURE_AUDIO_HOTWORD);
return mDelegate.listModules();
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 9dd2a61..26590c4 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -744,10 +744,6 @@
* state of calls in the self-managed {@link ConnectionService}. An example use-case is
* exposing these calls to an automotive device via its companion app.
* <p>
- * This meta-data can only be set for an {@link InCallService} which also sets
- * {@link #METADATA_IN_CALL_SERVICE_UI}. Only the default phone/dialer app, or a car-mode
- * {@link InCallService} can see self-managed calls.
- * <p>
* See also {@link Connection#PROPERTY_SELF_MANAGED}.
*/
public static final String METADATA_INCLUDE_SELF_MANAGED_CALLS =
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index f27c23b..1888943 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -5773,14 +5773,15 @@
* </ul>
* @hide
*/
- public static final String KEY_SA_DISABLE_POLICY_INT = KEY_PREFIX + "sa_disable_policy_int";
+ public static final String KEY_NR_SA_DISABLE_POLICY_INT =
+ KEY_PREFIX + "sa_disable_policy_int";
/** @hide */
@IntDef({
- SA_DISABLE_POLICY_NONE,
- SA_DISABLE_POLICY_WFC_ESTABLISHED,
- SA_DISABLE_POLICY_WFC_ESTABLISHED_WHEN_VONR_DISABLED,
- SA_DISABLE_POLICY_VOWIFI_REGISTERED
+ NR_SA_DISABLE_POLICY_NONE,
+ NR_SA_DISABLE_POLICY_WFC_ESTABLISHED,
+ NR_SA_DISABLE_POLICY_WFC_ESTABLISHED_WHEN_VONR_DISABLED,
+ NR_SA_DISABLE_POLICY_VOWIFI_REGISTERED
})
public @interface NrSaDisablePolicy {}
@@ -5788,14 +5789,14 @@
* Do not disables NR SA mode.
* @hide
*/
- public static final int SA_DISABLE_POLICY_NONE = 0;
+ public static final int NR_SA_DISABLE_POLICY_NONE = 0;
/**
* Disables NR SA mode when VoWiFi call is established in order to improve the delay or
* voice mute when the handover from ePDG to NR is not supported in UE or network.
* @hide
*/
- public static final int SA_DISABLE_POLICY_WFC_ESTABLISHED = 1;
+ public static final int NR_SA_DISABLE_POLICY_WFC_ESTABLISHED = 1;
/**
* Disables NR SA mode when VoWiFi call is established when VoNR is disabled in order to
@@ -5803,14 +5804,14 @@
* in UE or network.
* @hide
*/
- public static final int SA_DISABLE_POLICY_WFC_ESTABLISHED_WHEN_VONR_DISABLED = 2;
+ public static final int NR_SA_DISABLE_POLICY_WFC_ESTABLISHED_WHEN_VONR_DISABLED = 2;
/**
* Disables NR SA mode when IMS is registered over WiFi in order to improve the delay or
* voice mute when the handover from ePDG to NR is not supported in UE or network.
* @hide
*/
- public static final int SA_DISABLE_POLICY_VOWIFI_REGISTERED = 3;
+ public static final int NR_SA_DISABLE_POLICY_VOWIFI_REGISTERED = 3;
private Ims() {}
@@ -5883,7 +5884,7 @@
defaults.putInt(KEY_REGISTRATION_RETRY_BASE_TIMER_MILLIS_INT, 30000);
defaults.putInt(KEY_REGISTRATION_RETRY_MAX_TIMER_MILLIS_INT, 1800000);
defaults.putInt(KEY_REGISTRATION_SUBSCRIBE_EXPIRY_TIMER_SEC_INT, 600000);
- defaults.putInt(KEY_SA_DISABLE_POLICY_INT, SA_DISABLE_POLICY_NONE);
+ defaults.putInt(KEY_NR_SA_DISABLE_POLICY_INT, NR_SA_DISABLE_POLICY_NONE);
defaults.putIntArray(
KEY_IPSEC_AUTHENTICATION_ALGORITHMS_INT_ARRAY,
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 1ce85ba..28ea5a6 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1186,6 +1186,7 @@
ApnSetting other = (ApnSetting) o;
return mEntryName.equals(other.mEntryName)
+ && Objects.equals(mId, other.mId)
&& Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
&& Objects.equals(mApnName, other.mApnName)
&& Objects.equals(mProxyAddress, other.mProxyAddress)
@@ -1337,6 +1338,14 @@
public ContentValues toContentValues() {
ContentValues apnValue = new ContentValues();
apnValue.put(Telephony.Carriers.NUMERIC, nullToEmpty(mOperatorNumeric));
+ // If the APN is editable, the user may be able to set an invalid numeric. The numeric must
+ // always be 5 or 6 characters (depending on the length of the MNC), so skip if it is
+ // potentially invalid.
+ if (!TextUtils.isEmpty(mOperatorNumeric)
+ && (mOperatorNumeric.length() == 5 || mOperatorNumeric.length() == 6)) {
+ apnValue.put(Telephony.Carriers.MCC, mOperatorNumeric.substring(0, 3));
+ apnValue.put(Telephony.Carriers.MNC, mOperatorNumeric.substring(3));
+ }
apnValue.put(Telephony.Carriers.NAME, nullToEmpty(mEntryName));
apnValue.put(Telephony.Carriers.APN, nullToEmpty(mApnName));
apnValue.put(Telephony.Carriers.PROXY, nullToEmpty(mProxyAddress));
@@ -1356,6 +1365,7 @@
getProtocolStringFromInt(mRoamingProtocol));
apnValue.put(Telephony.Carriers.CARRIER_ENABLED, mCarrierEnabled);
apnValue.put(Telephony.Carriers.MVNO_TYPE, getMvnoTypeStringFromInt(mMvnoType));
+ apnValue.put(Telephony.Carriers.MVNO_MATCH_DATA, nullToEmpty(mMvnoMatchData));
apnValue.put(Telephony.Carriers.NETWORK_TYPE_BITMASK, mNetworkTypeBitmask);
apnValue.put(Telephony.Carriers.LINGERING_NETWORK_TYPE_BITMASK,
mLingeringNetworkTypeBitmask);
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 8ed60c1..b273ba2 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -571,6 +571,7 @@
int RIL_REQUEST_UPDATE_IMS_CALL_STATUS = 240;
int RIL_REQUEST_SET_N1_MODE_ENABLED = 241;
int RIL_REQUEST_IS_N1_MODE_ENABLED = 242;
+ int RIL_REQUEST_IS_NULL_CIPHER_AND_INTEGRITY_ENABLED = 259;
/* Responses begin */
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
index 4e3ae0c..efd9b00 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
@@ -18,7 +18,7 @@
import android.app.Instrumentation
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerBuilderProvider
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index f389e13..1f120d4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -19,9 +19,9 @@
package com.android.server.wm.flicker
import android.tools.common.PlatformConsts
-import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.common.datatypes.component.IComponentNameMatcher
import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.common.traces.component.IComponentNameMatcher
import android.tools.common.traces.wm.WindowManagerTrace
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.helpers.WindowUtils
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
index c3cbb84..8638288 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.activityembedding
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index 5dc2dd7..10b71ff 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -40,20 +40,27 @@
* Launch an app [testApp] and wait animation to complete
* Press back button
* ```
+ *
* To run only the presubmit assertions add: `--
+ *
* ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
* ```
+ *
* To run only the postsubmit assertions add: `--
+ *
* ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
* ```
+ *
* To run only the flaky assertions add: `--
+ *
* ```
* --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
* ```
+ *
* Notes:
* ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index b042a14..e5bd350 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -40,20 +40,27 @@
* Launch an app [testApp] and wait animation to complete
* Press home button
* ```
+ *
* To run only the presubmit assertions add: `--
+ *
* ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
* ```
+ *
* To run only the postsubmit assertions add: `--
+ *
* ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
* ```
+ *
* To run only the flaky assertions add: `--
+ *
* ```
* --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
* ```
+ *
* Notes:
* ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
index c4628aa..4570fa2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.close
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.LAUNCHER
+import android.tools.common.traces.component.ComponentNameMatcher.Companion.LAUNCHER
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
index e531bc0..6053f1d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.common.traces.wm.WindowManagerState.Companion.STATE_RESUMED
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt
index afb9fbf..94ac1a6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
class AppPairsHelper(
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
index 47dd4e9..c6fa1bb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
index d4f48fe..747cf37 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.WindowManagerStateHelper
import android.tools.device.traces.parsers.toFlickerComponent
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
index 73effbd..d172252 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.traces.parsers.WindowManagerStateHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
index a6e57d5..7a8d780 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.traces.parsers.WindowManagerStateHelper
import android.tools.device.traces.parsers.toFlickerComponent
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
index d61a500..83a41ab 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
@@ -18,10 +18,10 @@
import android.app.Instrumentation
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.common.datatypes.component.IComponentMatcher
import android.tools.common.traces.Condition
import android.tools.common.traces.DeviceStateDump
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.common.traces.component.IComponentMatcher
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.helpers.IME_PACKAGE
import android.tools.device.traces.parsers.WindowManagerStateHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
index fb5e1d2..b2aeb14 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
index 1ccac13..a670d68 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
@@ -17,15 +17,15 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import androidx.test.uiautomator.By
-import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.testapp.ActivityOptions
-import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.device.traces.parsers.toFlickerComponent
-import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.helpers.SYSTEMUI_PACKAGE
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.Until
+import com.android.server.wm.flicker.testapp.ActivityOptions
class LetterboxAppHelper
@JvmOverloads
@@ -37,13 +37,21 @@
) : StandardAppHelper(instr, launcherName, component) {
fun clickRestart(wmHelper: WindowManagerStateHelper) {
- val restartButton = uiDevice.wait(Until.findObject(By.res(
- SYSTEMUI_PACKAGE, "size_compat_restart_button")), FIND_TIMEOUT)
+ val restartButton =
+ uiDevice.wait(
+ Until.findObject(By.res(SYSTEMUI_PACKAGE, "size_compat_restart_button")),
+ FIND_TIMEOUT
+ )
restartButton?.run { restartButton.click() } ?: error("Restart button not found")
// size compat mode restart confirmation dialog button
- val restartDialogButton = uiDevice.wait(Until.findObject(By.res(
- SYSTEMUI_PACKAGE, "letterbox_restart_dialog_restart_button")), FIND_TIMEOUT)
+ val restartDialogButton =
+ uiDevice.wait(
+ Until.findObject(
+ By.res(SYSTEMUI_PACKAGE, "letterbox_restart_dialog_restart_button")
+ ),
+ FIND_TIMEOUT
+ )
restartDialogButton?.run { restartDialogButton.click() }
?: error("Restart dialog button not found")
wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
index ab91685..c98f1c4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.traces.parsers.toFlickerComponent
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
index e93e9c8..65175ef 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
@@ -19,7 +19,7 @@
import android.app.Instrumentation
import android.content.Context
import android.provider.Settings
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.util.Log
import com.android.compatibility.common.util.SystemUtil
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
index c547ad0..5b3d308 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.traces.parsers.WindowManagerStateHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
index 20ee3b9..ee65004 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
index 78f8bcf..7665690 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.traces.parsers.WindowManagerStateHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
index c5a21a8..24e231c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
@@ -21,8 +21,8 @@
import android.media.session.MediaSessionManager
import android.tools.common.datatypes.Rect
import android.tools.common.datatypes.Region
-import android.tools.common.datatypes.component.IComponentMatcher
import android.tools.common.traces.ConditionsFactory
+import android.tools.common.traces.component.IComponentMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.helpers.SYSTEMUI_PACKAGE
@@ -250,7 +250,8 @@
waitConditions = arrayOf(ConditionsFactory.hasPipWindow())
)
- wmHelper.StateSyncBuilder()
+ wmHelper
+ .StateSyncBuilder()
.withWindowSurfaceAppeared(this)
.withPipShown()
.waitForAndVerify()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
index 06e668e..cac3530 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
index 94c90da..8366a7a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
index 64af811..89c6c35 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
index 316766a..895725c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.traces.parsers.WindowManagerStateHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
index 34fa921..7e0632d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
@@ -18,8 +18,8 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
index 823328a..7f496d8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
@@ -19,7 +19,7 @@
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
index df9d33b..cbe03dc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
index 7954dd1..82c390b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
index 10ce5ea..c693ca7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
index 579c10f..8e33719 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
@@ -18,7 +18,7 @@
package com.android.server.wm.flicker.ime
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.legacy.FlickerTest
fun FlickerTest.imeLayerBecomesVisible() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
index 3f87aef..19bbf0c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
@@ -18,8 +18,8 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.NavBar
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
index 6179fc2..f64ad53 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
index 690ed53..11bc7b9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
@@ -19,7 +19,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.NavBar
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
index 866e858..46967db 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
index 6f22589..277b9155 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
index 231d0d7..9275d6a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
@@ -17,8 +17,8 @@
package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
import android.tools.common.traces.ConditionsFactory
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
index 3c577ac..e6594c9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTestCfArm.kt
index 3289bc6..ac05c76 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTestCfArm.kt
@@ -41,4 +41,4 @@
return FlickerTestFactory.nonRotationTests()
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index d0dc42f..26f88d2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -23,9 +23,9 @@
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.helpers.setRotation
-import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -42,6 +42,7 @@
* Make sure no apps are running on the device
* Launch an app [testApp] and wait animation to complete
* ```
+ *
* Notes:
* ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTestCfArm.kt
index f75d9ee..d9a99da 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTestCfArm.kt
@@ -49,4 +49,4 @@
return FlickerTestFactory.nonRotationTests()
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
index 1a1d403..3d5a8e3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.legacy.FlickerTest
import com.android.server.wm.flicker.replacesLayer
import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
index b1a267a..b21777b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
@@ -78,9 +78,7 @@
override fun taskBarLayerIsVisibleAtStartAndEnd() {}
/** {@inheritDoc} */
- @Test
- @Ignore("Display is off at the start")
- override fun taskBarWindowIsAlwaysVisible() {}
+ @Test @Ignore("Display is off at the start") override fun taskBarWindowIsAlwaysVisible() {}
/** {@inheritDoc} */
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
index e414325..ec92ca6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
@@ -20,7 +20,7 @@
import android.platform.test.annotations.Presubmit
import android.platform.test.rule.SettingOverrideRule
import android.provider.Settings
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
index 0b09e24..009d617 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
@@ -19,7 +19,7 @@
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
@@ -113,9 +113,7 @@
@Test
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
- @Presubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
+ @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
@FlakyTest(bugId = 278227468)
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
index 730f78f..eae9ca1 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
import com.android.server.wm.flicker.navBarLayerPositionAtEnd
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
index 9c16b79..7bcb910 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdCfArm.kt
index 4aa78d4..8b4a613 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdCfArm.kt
@@ -44,4 +44,4 @@
return FlickerTestFactory.nonRotationTests()
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
index 23cb1d4..425e674d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index 00d7544..8e1b059 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -44,6 +44,7 @@
* Relaunch an app [testApp] by selecting it in the overview screen, and wait animation to
* complete (only this action is traced)
* ```
+ *
* Notes:
* ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index 17f5638..1383ae3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -20,7 +20,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.NavBar
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerTest
@@ -47,6 +47,7 @@
* Lock the device.
* Launch an app on top of the lock screen [testApp] and wait animation to complete
* ```
+ *
* Notes:
* ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
@@ -161,9 +162,7 @@
super.appWindowBecomesFirstAndOnlyTopWindow()
/** {@inheritDoc} */
- @Presubmit
- @Test
- override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
+ @Presubmit @Test override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
/** Checks the [ComponentNameMatcher.NAV_BAR] is visible at the end of the transition */
@Presubmit
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
index e0db96f..87a14c6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index cdd2d45..3385830 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -42,6 +42,7 @@
* Press home
* Relaunch an app [testApp] and wait animation to complete (only this action is traced)
* ```
+ *
* Notes:
* ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTestCfArm.kt
index 9679059..d8b38b3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTestCfArm.kt
@@ -43,4 +43,4 @@
return FlickerTestFactory.nonRotationTests()
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
index b848e63..b48611e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
@@ -20,20 +20,20 @@
import android.os.Bundle
import android.os.Handler
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
import android.tools.common.traces.ConditionsFactory
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerBuilderProvider
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.flicker.R
-import com.android.server.wm.flicker.helpers.setRotation
-import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
-import android.tools.device.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.server.wm.flicker.helpers.setRotation
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
index be73547..d0fd732 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
@@ -21,11 +21,11 @@
import android.content.res.Resources
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.SPLASH_SCREEN
-import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER
-import android.tools.common.datatypes.component.ComponentSplashScreenMatcher
-import android.tools.common.datatypes.component.IComponentMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher.Companion.SPLASH_SCREEN
+import android.tools.common.traces.component.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER
+import android.tools.common.traces.component.ComponentSplashScreenMatcher
+import android.tools.common.traces.component.IComponentMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
index eadeef5..a8b80ad 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
@@ -20,7 +20,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.NavBar
import android.tools.common.datatypes.Rect
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index 1360495..96cd8ff 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -20,7 +20,7 @@
import android.platform.test.annotations.Presubmit
import android.tools.common.NavBar
import android.tools.common.datatypes.Rect
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
index d49f035..7e935f0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
@@ -21,7 +21,7 @@
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.common.datatypes.Rect
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index fe789a7..855ea3e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -18,7 +18,7 @@
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
index 3c0bbd6..fe9da33 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.rotation
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index 4d010f3..0cbbb83 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -19,7 +19,7 @@
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
import android.tools.common.ScenarioBuilder
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/TouchLatency/app/build.gradle b/tests/TouchLatency/app/build.gradle
index 129baab..07f6bca 100644
--- a/tests/TouchLatency/app/build.gradle
+++ b/tests/TouchLatency/app/build.gradle
@@ -2,7 +2,6 @@
android {
compileSdkVersion 33
- buildToolsVersion '28.0.3'
defaultConfig {
applicationId "com.prefabulated.touchlatency"
diff --git a/tests/TouchLatency/app/src/main/AndroidManifest.xml b/tests/TouchLatency/app/src/main/AndroidManifest.xml
index 25bb5d9..5743b25 100644
--- a/tests/TouchLatency/app/src/main/AndroidManifest.xml
+++ b/tests/TouchLatency/app/src/main/AndroidManifest.xml
@@ -30,12 +30,6 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
-
- <activity android:name=".TouchLatencyActivityPresentation"
- android:label="@string/app_name"
- android:parentActivityName=".TouchLatencyActivity"
- android:exported="true">
- </activity>
</application>
</manifest>
diff --git a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
index 3a520bc..7678633 100644
--- a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
+++ b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
@@ -16,8 +16,6 @@
package com.prefabulated.touchlatency;
-import android.app.ActivityOptions;
-import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.os.Handler;
@@ -105,7 +103,6 @@
updateDisplayMode(menuItem, currentMode);
}
updateRefreshRateMenu(mMenu.findItem(R.id.frame_rate));
- updateMultiDisplayMenu(mMenu.findItem(R.id.multi_display));
}
@Override
@@ -186,20 +183,6 @@
mCurrentModeIndex = modeIndex;
}
- private void changeMultipleDisplays() {
- Intent intent = new Intent(this, TouchLatencyActivityPresentation.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
- ActivityOptions options = ActivityOptions.makeBasic();
- for (int i = 1; i < mDisplayManager.getDisplays().length; ++i) {
- // We assume the first display is already displaying the TouchLatencyActivity
- int displayId = mDisplayManager.getDisplays()[i].getDisplayId();
- options.setLaunchDisplayId(displayId);
- intent.putExtra(TouchLatencyActivityPresentation.DISPLAY_ID, displayId);
- startActivity(intent, options.toBundle());
- }
- }
-
-
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Trace.beginSection("TouchLatencyActivity onOptionsItemSelected");
@@ -218,10 +201,6 @@
changeDisplayMode(item);
break;
}
- case R.id.multi_display: {
- changeMultipleDisplays();
- break;
- }
}
Trace.endSection();
diff --git a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivityPresentation.java b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivityPresentation.java
deleted file mode 100644
index 2602e6b..0000000
--- a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivityPresentation.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.prefabulated.touchlatency;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.os.Trace;
-import android.view.Display;
-import android.view.Display.Mode;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.Window;
-import android.view.WindowManager;
-
-public class TouchLatencyActivityPresentation extends Activity {
- public static final String DISPLAY_ID = "DISPLAY_ID";
- private Mode[] mDisplayModes;
- private int mCurrentModeIndex;
- private int mDisplayId;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- if (getIntent().hasExtra(DISPLAY_ID)) {
- mDisplayId = (int) getIntent().getExtras().get(DISPLAY_ID);
- }
- Trace.beginSection(
- "TouchLatencyActivityPresentation::DisplayId::" + mDisplayId + " onCreate");
- setContentView(R.layout.activity_touch_latency);
-
- mTouchView = findViewById(R.id.canvasView);
-
- WindowManager wm = getWindowManager();
- Display display = wm.getDefaultDisplay();
- mDisplayModes = display.getSupportedModes();
- Mode currentMode = getWindowManager().getDefaultDisplay().getMode();
-
- for (int i = 0; i < mDisplayModes.length; i++) {
- if (currentMode.getModeId() == mDisplayModes[i].getModeId()) {
- mCurrentModeIndex = i;
- break;
- }
- }
- Trace.endSection();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- Trace.beginSection(
- "TouchLatencyActivityPresentation::DisplayId:: "
- + mDisplayId + " onCreateOptionsMenu");
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.menu_touch_latency, menu);
- if (mDisplayModes.length > 1) {
- MenuItem menuItem = menu.findItem(R.id.display_mode);
- Mode currentMode = getWindowManager().getDefaultDisplay().getMode();
- updateDisplayMode(menuItem, currentMode);
- }
- Trace.endSection();
- return true;
- }
-
- private void updateDisplayMode(MenuItem menuItem, Mode displayMode) {
- int fps = (int) displayMode.getRefreshRate();
- menuItem.setTitle(fps + "hz");
- menuItem.setVisible(true);
- }
-
- public void changeDisplayMode(MenuItem item) {
- Window w = getWindow();
- WindowManager.LayoutParams params = w.getAttributes();
-
- int modeIndex = (mCurrentModeIndex + 1) % mDisplayModes.length;
- params.preferredDisplayModeId = mDisplayModes[modeIndex].getModeId();
- w.setAttributes(params);
-
- updateDisplayMode(item, mDisplayModes[modeIndex]);
- mCurrentModeIndex = modeIndex;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- Trace.beginSection(
- "TouchLatencyActivityPresentation::DisplayId::"
- + mDisplayId + " onOptionsItemSelected");
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
-
- //noinspection SimplifiableIfStatement
- switch (id) {
- case R.id.action_settings: {
- mTouchView.changeMode(item);
- break;
- }
- case R.id.display_mode: {
- changeDisplayMode(item);
- break;
- }
- }
-
- Trace.endSection();
- return super.onOptionsItemSelected(item);
- }
-
- private TouchLatencyView mTouchView;
-}
diff --git a/tests/TouchLatency/app/src/main/res/menu/menu_touch_latency.xml b/tests/TouchLatency/app/src/main/res/menu/menu_touch_latency.xml
index 7169021..f637f71 100644
--- a/tests/TouchLatency/app/src/main/res/menu/menu_touch_latency.xml
+++ b/tests/TouchLatency/app/src/main/res/menu/menu_touch_latency.xml
@@ -30,9 +30,4 @@
android:title="@string/display_mode"
android:visible="false"
app:showAsAction="always" />
- <item
- android:id="@+id/multi_display"
- android:title="@string/multi_display"
- android:visible="false"
- app:showAsAction="ifRoom" />
</menu>
diff --git a/tests/TouchLatency/build.gradle b/tests/TouchLatency/build.gradle
index 381e55e..f52935b 100644
--- a/tests/TouchLatency/build.gradle
+++ b/tests/TouchLatency/build.gradle
@@ -6,7 +6,7 @@
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.2.2'
+ classpath 'com.android.tools.build:gradle:7.4.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/tests/TouchLatency/gradle/wrapper/gradle-wrapper.jar b/tests/TouchLatency/gradle/wrapper/gradle-wrapper.jar
index 758de96..7454180 100644
--- a/tests/TouchLatency/gradle/wrapper/gradle-wrapper.jar
+++ b/tests/TouchLatency/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/tests/TouchLatency/gradle/wrapper/gradle-wrapper.properties b/tests/TouchLatency/gradle/wrapper/gradle-wrapper.properties
index 4d9ca16..8049c68 100644
--- a/tests/TouchLatency/gradle/wrapper/gradle-wrapper.properties
+++ b/tests/TouchLatency/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/tests/TouchLatency/gradlew b/tests/TouchLatency/gradlew
index cccdd3d..1b6c787 100755
--- a/tests/TouchLatency/gradlew
+++ b/tests/TouchLatency/gradlew
@@ -1,78 +1,129 @@
-#!/usr/bin/env sh
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
##############################################################################
-##
-## Gradle start up script for UN*X
-##
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
##############################################################################
# Attempt to set APP_HOME
+
# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
+APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
warn () {
echo "$*"
-}
+} >&2
die () {
echo
echo "$*"
echo
exit 1
-}
+} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACMD=$JAVA_HOME/jre/sh/java
else
- JAVACMD="$JAVA_HOME/bin/java"
+ JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -81,7 +132,7 @@
location of your Java installation."
fi
else
- JAVACMD="java"
+ JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
@@ -89,84 +140,95 @@
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
- fi
- i=$((i+1))
- done
- case $i in
- (0) set -- ;;
- (1) set -- "$args0" ;;
- (2) set -- "$args0" "$args1" ;;
- (3) set -- "$args0" "$args1" "$args2" ;;
- (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=$(save "$@")
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
- cd "$(dirname "$0")"
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
fi
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
exec "$JAVACMD" "$@"
diff --git a/tests/TouchLatency/gradlew.bat b/tests/TouchLatency/gradlew.bat
index e95643d..ac1b06f 100644
--- a/tests/TouchLatency/gradlew.bat
+++ b/tests/TouchLatency/gradlew.bat
@@ -1,3 +1,19 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -13,15 +29,18 @@
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
+if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,28 +64,14 @@
goto fail
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
index c6e675a..e207b01 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
@@ -185,6 +185,7 @@
*/
@NonNull
public Builder setExtras(@NonNull Bundle extras) {
+ Objects.requireNonNull(extras);
mExtras = extras;
return this;
}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java
deleted file mode 100644
index b18ab50..0000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
-import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT;
-import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_TIMEOUT;
-import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Bundle;
-import android.os.Parcel;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-import java.util.Arrays;
-
-/**
- * Unit tests for {@link HotspotNetworkConnectionStatus}.
- */
-@SmallTest
-public class HotspotNetworkConnectionStatusTest {
- private static final long DEVICE_ID = 11L;
- private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
- new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
- .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
- .setBatteryPercentage(50).build();
- private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
- private static final String NETWORK_NAME = "TEST_NETWORK";
- private static final String HOTSPOT_SSID = "TEST_SSID";
- private static final String HOTSPOT_BSSID = "TEST _BSSID";
- private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
- private static final long DEVICE_ID_1 = 111L;
- private static final String BUNDLE_KEY = "INT-KEY";
- private static final int BUNDLE_VALUE = 1;
-
- /**
- * Verifies parcel serialization/deserialization.
- */
- @Test
- public void testParcelOperation() {
- HotspotNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
-
- Parcel parcelW = Parcel.obtain();
- status.writeToParcel(parcelW, 0);
- byte[] bytes = parcelW.marshall();
- parcelW.recycle();
-
- Parcel parcelR = Parcel.obtain();
- parcelR.unmarshall(bytes, 0, bytes.length);
- parcelR.setDataPosition(0);
- HotspotNetworkConnectionStatus fromParcel =
- HotspotNetworkConnectionStatus.CREATOR.createFromParcel(parcelR);
-
- assertThat(fromParcel).isEqualTo(status);
- assertThat(fromParcel.hashCode()).isEqualTo(status.hashCode());
- }
-
- /**
- * Verifies the Equals operation
- */
- @Test
- public void testEqualsOperation() {
- HotspotNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
- HotspotNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
- assertThat(status1).isEqualTo(status2);
-
- HotspotNetworkConnectionStatus.Builder builder = buildConnectionStatusBuilder()
- .setStatus(CONNECTION_STATUS_TETHERING_TIMEOUT);
- assertThat(builder.build()).isNotEqualTo(status1);
-
- builder = buildConnectionStatusBuilder()
- .setHotspotNetwork(buildHotspotNetworkBuilder().setDeviceId(DEVICE_ID_1).build());
- assertThat(builder.build()).isNotEqualTo(status1);
- }
-
- /**
- * Verifies the get methods return the expected data.
- */
- @Test
- public void testGetMethods() {
- HotspotNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
- assertThat(status.getStatus()).isEqualTo(CONNECTION_STATUS_ENABLING_HOTSPOT);
- assertThat(status.getHotspotNetwork()).isEqualTo(buildHotspotNetworkBuilder().build());
- assertThat(status.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
- }
-
- @Test
- public void testHashCode() {
- HotspotNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
- HotspotNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
-
- assertThat(status1.hashCode()).isEqualTo(status2.hashCode());
- }
-
- private HotspotNetworkConnectionStatus.Builder buildConnectionStatusBuilder() {
- return new HotspotNetworkConnectionStatus.Builder()
- .setStatus(CONNECTION_STATUS_ENABLING_HOTSPOT)
- .setHotspotNetwork(buildHotspotNetworkBuilder().build())
- .setExtras(buildBundle());
- }
-
- private Bundle buildBundle() {
- Bundle bundle = new Bundle();
- bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
- return bundle;
- }
-
- private HotspotNetwork.Builder buildHotspotNetworkBuilder() {
- HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
- .setDeviceId(DEVICE_ID)
- .setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
- .setHostNetworkType(NETWORK_TYPE)
- .setNetworkName(NETWORK_NAME)
- .setHotspotSsid(HOTSPOT_SSID)
- .setHotspotBssid(HOTSPOT_BSSID);
- Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
- return builder;
- }
-}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
deleted file mode 100644
index 0827ffa..0000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
-import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_WIFI;
-import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
-import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertThrows;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.util.ArraySet;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Arrays;
-
-/**
- * Unit tests for {@link HotspotNetwork}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class HotspotNetworkTest {
- private static final long DEVICE_ID = 11L;
- private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
- new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
- .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
- .setBatteryPercentage(50).build();
- private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
- private static final String NETWORK_NAME = "TEST_NETWORK";
- private static final String HOTSPOT_SSID = "TEST_SSID";
- private static final String HOTSPOT_BSSID = "TEST _BSSID";
- private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
- private static final String BUNDLE_KEY = "INT-KEY";
- private static final int BUNDLE_VALUE = 1;
-
- private static final long DEVICE_ID_1 = 111L;
- private static final NetworkProviderInfo NETWORK_PROVIDER_INFO1 =
- new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
- .setDeviceType(DEVICE_TYPE_PHONE).setConnectionStrength(2)
- .setBatteryPercentage(50).build();
- private static final int NETWORK_TYPE_1 = NETWORK_TYPE_WIFI;
- private static final String NETWORK_NAME_1 = "TEST_NETWORK1";
- private static final String HOTSPOT_SSID_1 = "TEST_SSID1";
- private static final String HOTSPOT_BSSID_1 = "TEST _BSSID1";
- private static final int[] HOTSPOT_SECURITY_TYPES_1 = {SECURITY_TYPE_PSK, SECURITY_TYPE_EAP};
-
- /**
- * Verifies parcel serialization/deserialization.
- */
- @Test
- public void testParcelOperation() {
- HotspotNetwork network = buildHotspotNetworkBuilder(true).build();
-
- Parcel parcelW = Parcel.obtain();
- network.writeToParcel(parcelW, 0);
- byte[] bytes = parcelW.marshall();
- parcelW.recycle();
-
- Parcel parcelR = Parcel.obtain();
- parcelR.unmarshall(bytes, 0, bytes.length);
- parcelR.setDataPosition(0);
- HotspotNetwork fromParcel = HotspotNetwork.CREATOR.createFromParcel(parcelR);
-
- assertThat(fromParcel).isEqualTo(network);
- assertThat(fromParcel.hashCode()).isEqualTo(network.hashCode());
- }
-
- /**
- * Verifies the Equals operation
- */
- @Test
- public void testEqualsOperation() {
- HotspotNetwork network1 = buildHotspotNetworkBuilder(true).build();
- HotspotNetwork network2 = buildHotspotNetworkBuilder(true).build();
- assertThat(network1).isEqualTo(network2);
-
- HotspotNetwork.Builder builder = buildHotspotNetworkBuilder(true).setDeviceId(DEVICE_ID_1);
- assertThat(builder.build()).isNotEqualTo(network1);
-
- builder = buildHotspotNetworkBuilder(true).setNetworkProviderInfo(NETWORK_PROVIDER_INFO1);
- assertThat(builder.build()).isNotEqualTo(network1);
-
- builder = buildHotspotNetworkBuilder(true).setHostNetworkType(NETWORK_TYPE_1);
- assertThat(builder.build()).isNotEqualTo(network1);
-
- builder = buildHotspotNetworkBuilder(true).setNetworkName(NETWORK_NAME_1);
- assertThat(builder.build()).isNotEqualTo(network1);
-
- builder = buildHotspotNetworkBuilder(true).setHotspotSsid(HOTSPOT_SSID_1);
- assertThat(builder.build()).isNotEqualTo(network1);
-
- builder = buildHotspotNetworkBuilder(true).setHotspotBssid(HOTSPOT_BSSID_1);
- assertThat(builder.build()).isNotEqualTo(network1);
-
- builder = buildHotspotNetworkBuilder(true);
- HotspotNetwork.Builder builder1 = buildHotspotNetworkBuilder(true);
- Arrays.stream(HOTSPOT_SECURITY_TYPES_1).forEach(builder1::addHotspotSecurityType);
-
- assertThat(builder1.build()).isNotEqualTo(builder.build());
- }
-
- /**
- * Verifies the get methods return the expected data.
- */
- @Test
- public void testGetMethods() {
- HotspotNetwork network = buildHotspotNetworkBuilder(true).build();
- ArraySet<Integer> securityTypes = new ArraySet<>();
- Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(securityTypes::add);
-
- assertThat(network.getDeviceId()).isEqualTo(DEVICE_ID);
- assertThat(network.getNetworkProviderInfo()).isEqualTo(NETWORK_PROVIDER_INFO);
- assertThat(network.getHostNetworkType()).isEqualTo(NETWORK_TYPE);
- assertThat(network.getNetworkName()).isEqualTo(NETWORK_NAME);
- assertThat(network.getHotspotSsid()).isEqualTo(HOTSPOT_SSID);
- assertThat(network.getHotspotBssid()).isEqualTo(HOTSPOT_BSSID);
- assertThat(network.getHotspotSecurityTypes()).containsExactlyElementsIn(securityTypes);
- assertThat(network.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
- }
-
- @Test
- public void testHashCode() {
- HotspotNetwork network1 = buildHotspotNetworkBuilder(true).build();
- HotspotNetwork network2 = buildHotspotNetworkBuilder(true).build();
-
- assertThat(network1.hashCode()).isEqualTo(network2.hashCode());
- }
-
- @Test
- public void networkProviderInfoNotSet_shouldThrowException() {
- Exception e = assertThrows(IllegalArgumentException.class,
- () -> buildHotspotNetworkBuilder(false).build());
- assertThat(e.getMessage()).contains("NetworkProviderInfo");
- }
-
- private HotspotNetwork.Builder buildHotspotNetworkBuilder(boolean withNetworkProviderInfo) {
- HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
- .setDeviceId(DEVICE_ID)
- .setHostNetworkType(NETWORK_TYPE)
- .setNetworkName(NETWORK_NAME)
- .setHotspotSsid(HOTSPOT_SSID)
- .setHotspotBssid(HOTSPOT_BSSID)
- .setExtras(buildBundle());
- Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
- if (withNetworkProviderInfo) {
- builder.setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
- }
- return builder;
- }
-
- private Bundle buildBundle() {
- Bundle bundle = new Bundle();
- bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
- return bundle;
- }
-}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
deleted file mode 100644
index f98a0fc..0000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
-import static android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVED;
-import static android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVE_FAILED;
-import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Bundle;
-import android.os.Parcel;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-import java.util.Arrays;
-
-/**
- * Unit tests for {@link KnownNetworkConnectionStatus}.
- */
-@SmallTest
-public class KnownNetworkConnectionStatusTest {
- private static final int NETWORK_SOURCE = NETWORK_SOURCE_NEARBY_SELF;
- private static final String SSID = "TEST_SSID";
- private static final int[] SECURITY_TYPES = {SECURITY_TYPE_WEP};
- private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
- new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
- .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
- .setBatteryPercentage(50).build();
- private static final String SSID_1 = "TEST_SSID1";
- private static final String BUNDLE_KEY = "INT-KEY";
- private static final int BUNDLE_VALUE = 1;
-
- /**
- * Verifies parcel serialization/deserialization.
- */
- @Test
- public void testParcelOperation() {
- KnownNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
-
- Parcel parcelW = Parcel.obtain();
- status.writeToParcel(parcelW, 0);
- byte[] bytes = parcelW.marshall();
- parcelW.recycle();
-
- Parcel parcelR = Parcel.obtain();
- parcelR.unmarshall(bytes, 0, bytes.length);
- parcelR.setDataPosition(0);
- KnownNetworkConnectionStatus fromParcel =
- KnownNetworkConnectionStatus.CREATOR.createFromParcel(parcelR);
-
- assertThat(fromParcel).isEqualTo(status);
- assertThat(fromParcel.hashCode()).isEqualTo(status.hashCode());
- }
-
- /**
- * Verifies the Equals operation
- */
- @Test
- public void testEqualsOperation() {
- KnownNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
- KnownNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
- assertThat(status1).isEqualTo(status2);
-
- KnownNetworkConnectionStatus.Builder builder = buildConnectionStatusBuilder()
- .setStatus(CONNECTION_STATUS_SAVE_FAILED);
- assertThat(builder.build()).isNotEqualTo(status1);
-
- builder = buildConnectionStatusBuilder()
- .setKnownNetwork(buildKnownNetworkBuilder().setSsid(SSID_1).build());
- assertThat(builder.build()).isNotEqualTo(status1);
- }
-
- /**
- * Verifies the get methods return the expected data.
- */
- @Test
- public void testGetMethods() {
- KnownNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
- assertThat(status.getStatus()).isEqualTo(CONNECTION_STATUS_SAVED);
- assertThat(status.getKnownNetwork()).isEqualTo(buildKnownNetworkBuilder().build());
- assertThat(status.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
- }
-
- @Test
- public void testHashCode() {
- KnownNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
- KnownNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
-
- assertThat(status1.hashCode()).isEqualTo(status2.hashCode());
- }
-
- private KnownNetworkConnectionStatus.Builder buildConnectionStatusBuilder() {
- return new KnownNetworkConnectionStatus.Builder()
- .setStatus(CONNECTION_STATUS_SAVED)
- .setKnownNetwork(buildKnownNetworkBuilder().build())
- .setExtras(buildBundle());
- }
-
- private Bundle buildBundle() {
- Bundle bundle = new Bundle();
- bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
- return bundle;
- }
-
- private KnownNetwork.Builder buildKnownNetworkBuilder() {
- KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
- .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
- Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
- return builder;
- }
-
-}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
deleted file mode 100644
index 81d7b44..0000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_CLOUD_SELF;
-import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
-import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
-import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.util.ArraySet;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-import java.util.Arrays;
-
-/**
- * Unit tests for {@link KnownNetwork}.
- */
-@SmallTest
-public class KnownNetworkTest {
-
- private static final int NETWORK_SOURCE = NETWORK_SOURCE_NEARBY_SELF;
- private static final String SSID = "TEST_SSID";
- private static final int[] SECURITY_TYPES = {SECURITY_TYPE_WEP};
- private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
- new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
- .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
- .setBatteryPercentage(50).build();
- private static final String BUNDLE_KEY = "INT-KEY";
- private static final int BUNDLE_VALUE = 1;
-
- private static final int NETWORK_SOURCE_1 = NETWORK_SOURCE_CLOUD_SELF;
- private static final String SSID_1 = "TEST_SSID1";
- private static final int[] SECURITY_TYPES_1 = {SECURITY_TYPE_PSK};
- private static final NetworkProviderInfo NETWORK_PROVIDER_INFO1 =
- new NetworkProviderInfo.Builder("TEST_NAME_1", "TEST_MODEL_1")
- .setDeviceType(DEVICE_TYPE_PHONE).setConnectionStrength(3)
- .setBatteryPercentage(33).build();
-
- /**
- * Verifies parcel serialization/deserialization.
- */
- @Test
- public void testParcelOperation() {
- KnownNetwork network = buildKnownNetworkBuilder().build();
-
- Parcel parcelW = Parcel.obtain();
- network.writeToParcel(parcelW, 0);
- byte[] bytes = parcelW.marshall();
- parcelW.recycle();
-
- Parcel parcelR = Parcel.obtain();
- parcelR.unmarshall(bytes, 0, bytes.length);
- parcelR.setDataPosition(0);
- KnownNetwork fromParcel = KnownNetwork.CREATOR.createFromParcel(parcelR);
-
- assertThat(fromParcel).isEqualTo(network);
- assertThat(fromParcel.hashCode()).isEqualTo(network.hashCode());
- }
-
- /**
- * Verifies the Equals operation
- */
- @Test
- public void testEqualsOperation() {
- KnownNetwork network1 = buildKnownNetworkBuilder().build();
- KnownNetwork network2 = buildKnownNetworkBuilder().build();
- assertThat(network1).isEqualTo(network2);
-
- KnownNetwork.Builder builder = buildKnownNetworkBuilder()
- .setNetworkSource(NETWORK_SOURCE_1);
- assertThat(builder.build()).isNotEqualTo(network1);
-
- builder = buildKnownNetworkBuilder().setSsid(SSID_1);
- assertThat(builder.build()).isNotEqualTo(network1);
-
- builder = buildKnownNetworkBuilder();
- Arrays.stream(SECURITY_TYPES_1).forEach(builder::addSecurityType);
- assertThat(builder.build()).isNotEqualTo(network1);
-
- builder = buildKnownNetworkBuilder().setNetworkProviderInfo(NETWORK_PROVIDER_INFO1);
- assertThat(builder.build()).isNotEqualTo(network1);
- }
-
- /**
- * Verifies the get methods return the expected data.
- */
- @Test
- public void testGetMethods() {
- KnownNetwork network = buildKnownNetworkBuilder().build();
- ArraySet<Integer> securityTypes = new ArraySet<>();
- Arrays.stream(SECURITY_TYPES).forEach(securityTypes::add);
-
- assertThat(network.getNetworkSource()).isEqualTo(NETWORK_SOURCE);
- assertThat(network.getSsid()).isEqualTo(SSID);
- assertThat(network.getSecurityTypes()).containsExactlyElementsIn(securityTypes);
- assertThat(network.getNetworkProviderInfo()).isEqualTo(NETWORK_PROVIDER_INFO);
- assertThat(network.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
- }
-
- @Test
- public void testHashCode() {
- KnownNetwork network1 = buildKnownNetworkBuilder().build();
- KnownNetwork network2 = buildKnownNetworkBuilder().build();
-
- assertThat(network1.hashCode()).isEqualTo(network2.hashCode());
- }
-
- private KnownNetwork.Builder buildKnownNetworkBuilder() {
- KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
- .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
- .setExtras(buildBundle());
- Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
- return builder;
- }
-
- private Bundle buildBundle() {
- Bundle bundle = new Bundle();
- bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
- return bundle;
- }
-}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java
deleted file mode 100644
index 4aa9ca6..0000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_LAPTOP;
-import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Bundle;
-import android.os.Parcel;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Unit tests for {@link NetworkProviderInfo}.
- */
-@SmallTest
-public class NetworkProviderInfoTest {
-
- private static final int DEVICE_TYPE = DEVICE_TYPE_PHONE;
- private static final String DEVICE_NAME = "TEST_NAME";
- private static final String DEVICE_MODEL = "TEST_MODEL";
- private static final int BATTERY_PERCENTAGE = 50;
- private static final int CONNECTION_STRENGTH = 2;
- private static final String BUNDLE_KEY = "INT-KEY";
- private static final int BUNDLE_VALUE = 1;
-
- private static final int DEVICE_TYPE_1 = DEVICE_TYPE_LAPTOP;
- private static final String DEVICE_NAME_1 = "TEST_NAME1";
- private static final String DEVICE_MODEL_1 = "TEST_MODEL1";
- private static final int BATTERY_PERCENTAGE_1 = 30;
- private static final int CONNECTION_STRENGTH_1 = 1;
-
- /**
- * Verifies parcel serialization/deserialization.
- */
- @Test
- public void testParcelOperation() {
- NetworkProviderInfo info = buildNetworkProviderInfoBuilder().build();
-
- Parcel parcelW = Parcel.obtain();
- info.writeToParcel(parcelW, 0);
- byte[] bytes = parcelW.marshall();
- parcelW.recycle();
-
- Parcel parcelR = Parcel.obtain();
- parcelR.unmarshall(bytes, 0, bytes.length);
- parcelR.setDataPosition(0);
- NetworkProviderInfo fromParcel = NetworkProviderInfo.CREATOR.createFromParcel(parcelR);
-
- assertThat(fromParcel).isEqualTo(info);
- assertThat(fromParcel.hashCode()).isEqualTo(info.hashCode());
- }
-
- /**
- * Verifies the Equals operation
- */
- @Test
- public void testEqualsOperation() {
- NetworkProviderInfo info1 = buildNetworkProviderInfoBuilder().build();
- NetworkProviderInfo info2 = buildNetworkProviderInfoBuilder().build();
- assertThat(info1).isEqualTo(info2);
-
- NetworkProviderInfo.Builder builder = buildNetworkProviderInfoBuilder().setDeviceType(
- DEVICE_TYPE_1);
- assertThat(builder.build()).isNotEqualTo(info1);
-
- builder = buildNetworkProviderInfoBuilder().setDeviceName(DEVICE_NAME_1);
- assertThat(builder.build()).isNotEqualTo(info1);
-
- builder = buildNetworkProviderInfoBuilder().setModelName(DEVICE_MODEL_1);
- assertThat(builder.build()).isNotEqualTo(info1);
-
- builder = buildNetworkProviderInfoBuilder()
- .setBatteryPercentage(BATTERY_PERCENTAGE_1);
- assertThat(builder.build()).isNotEqualTo(info1);
-
- builder = buildNetworkProviderInfoBuilder()
- .setConnectionStrength(CONNECTION_STRENGTH_1);
- assertThat(builder.build()).isNotEqualTo(info1);
- }
-
- /**
- * Verifies the get methods return the expected data.
- */
- @Test
- public void testGetMethods() {
- NetworkProviderInfo info = buildNetworkProviderInfoBuilder().build();
- assertThat(info.getDeviceType()).isEqualTo(DEVICE_TYPE);
- assertThat(info.getDeviceName()).isEqualTo(DEVICE_NAME);
- assertThat(info.getModelName()).isEqualTo(DEVICE_MODEL);
- assertThat(info.getBatteryPercentage()).isEqualTo(BATTERY_PERCENTAGE);
- assertThat(info.getConnectionStrength()).isEqualTo(CONNECTION_STRENGTH);
- assertThat(info.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
- }
-
- @Test
- public void testHashCode() {
- NetworkProviderInfo info1 = buildNetworkProviderInfoBuilder().build();
- NetworkProviderInfo info2 = buildNetworkProviderInfoBuilder().build();
-
- assertThat(info1.hashCode()).isEqualTo(info2.hashCode());
- }
-
- private NetworkProviderInfo.Builder buildNetworkProviderInfoBuilder() {
- return new NetworkProviderInfo.Builder(DEVICE_NAME, DEVICE_MODEL).setDeviceType(DEVICE_TYPE)
- .setBatteryPercentage(BATTERY_PERCENTAGE)
- .setConnectionStrength(CONNECTION_STRENGTH)
- .setExtras(buildBundle());
- }
-
- private Bundle buildBundle() {
- Bundle bundle = new Bundle();
- bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
- return bundle;
- }
-}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
deleted file mode 100644
index a03a6c2..0000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_EAP;
-import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
-import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
-import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
-import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.res.Resources;
-import android.net.wifi.sharedconnectivity.service.ISharedConnectivityService;
-import android.os.Bundle;
-import android.os.RemoteException;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-/**
- * Unit tests for {@link SharedConnectivityManager}.
- */
-@SmallTest
-public class SharedConnectivityManagerTest {
- private static final long DEVICE_ID = 11L;
- private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
- new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
- .setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
- .setBatteryPercentage(50).build();
- private static final int NETWORK_TYPE = NETWORK_TYPE_CELLULAR;
- private static final String NETWORK_NAME = "TEST_NETWORK";
- private static final String HOTSPOT_SSID = "TEST_SSID";
- private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
-
- private static final int NETWORK_SOURCE = NETWORK_SOURCE_NEARBY_SELF;
- private static final String SSID = "TEST_SSID";
- private static final int[] SECURITY_TYPES = {SECURITY_TYPE_WEP};
-
- private static final String SERVICE_PACKAGE_NAME = "TEST_PACKAGE";
- private static final String SERVICE_INTENT_ACTION = "TEST_INTENT_ACTION";
-
-
- @Mock
- Context mContext;
- @Mock
- ISharedConnectivityService mService;
- @Mock
- Executor mExecutor;
- @Mock
- SharedConnectivityClientCallback mClientCallback, mClientCallback2;
- @Mock
- Resources mResources;
- @Mock
- ISharedConnectivityService.Stub mIBinder;
-
- private static final ComponentName COMPONENT_NAME =
- new ComponentName("dummypkg", "dummycls");
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- setResources(mContext);
- }
-
- @Test
- public void resourcesNotDefined_createShouldReturnNull() {
- when(mResources.getString(anyInt())).thenThrow(new Resources.NotFoundException());
-
- assertThat(SharedConnectivityManager.create(mContext)).isNull();
- }
-
- @Test
- public void resourceStringsAreEmpty_createShouldReturnNull() {
- when(mResources.getString(anyInt())).thenReturn("");
-
- assertThat(SharedConnectivityManager.create(mContext)).isNull();
- }
-
- @Test
- public void bindingToServiceOnFirstCallbackRegistration() {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.registerCallback(mExecutor, mClientCallback);
-
- verify(mContext).bindService(any(Intent.class), any(ServiceConnection.class), anyInt());
- }
-
- @Test
- public void bindIsCalledOnceOnMultipleCallbackRegistrations() throws Exception {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
-
- manager.registerCallback(mExecutor, mClientCallback);
- verify(mContext, times(1)).bindService(any(Intent.class), any(ServiceConnection.class),
- anyInt());
-
- manager.registerCallback(mExecutor, mClientCallback2);
- verify(mContext, times(1)).bindService(any(Intent.class), any(ServiceConnection.class),
- anyInt());
- }
-
- @Test
- public void unbindIsCalledOnLastCallbackUnregistrations() throws Exception {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
-
- manager.registerCallback(mExecutor, mClientCallback);
- manager.registerCallback(mExecutor, mClientCallback2);
- manager.unregisterCallback(mClientCallback);
- verify(mContext, never()).unbindService(
- any(ServiceConnection.class));
-
- manager.unregisterCallback(mClientCallback2);
- verify(mContext, times(1)).unbindService(
- any(ServiceConnection.class));
- }
-
- @Test
- public void registerCallback_serviceNotConnected_canUnregisterAndReregister() {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
-
- manager.registerCallback(mExecutor, mClientCallback);
- manager.unregisterCallback(mClientCallback);
- manager.registerCallback(mExecutor, mClientCallback);
-
- verify(mClientCallback, never()).onRegisterCallbackFailed(any(Exception.class));
- }
-
- @Test
- public void registerCallback_serviceConnected() throws Exception {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
-
- manager.registerCallback(mExecutor, mClientCallback);
-
- verify(mService).registerCallback(any());
- verify(mClientCallback, never()).onRegisterCallbackFailed(any(Exception.class));
- }
-
- @Test
- public void registerCallback_doubleRegistration_shouldFail() throws Exception {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
-
- manager.registerCallback(mExecutor, mClientCallback);
- manager.registerCallback(mExecutor, mClientCallback);
-
- verify(mClientCallback).onRegisterCallbackFailed(any(IllegalStateException.class));
- }
-
- @Test
- public void registerCallback_remoteException_shouldFail() throws Exception {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
- doThrow(new RemoteException()).when(mService).registerCallback(any());
-
- manager.registerCallback(mExecutor, mClientCallback);
-
- verify(mClientCallback).onRegisterCallbackFailed(any(RemoteException.class));
- }
-
- @Test
- public void unregisterCallback_withoutRegisteringFirst_serviceNotConnected_shouldFail() {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(null);
-
- assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
- }
-
- @Test
- public void unregisterCallback_withoutRegisteringFirst_serviceConnected_shouldFail() {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
-
- assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
- }
-
- @Test
- public void unregisterCallback() throws Exception {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
-
- manager.registerCallback(mExecutor, mClientCallback);
-
- assertThat(manager.unregisterCallback(mClientCallback)).isTrue();
- verify(mService).unregisterCallback(any());
- }
-
- @Test
- public void unregisterCallback_doubleUnregistration_serviceConnected_shouldFail() {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
-
- manager.registerCallback(mExecutor, mClientCallback);
- manager.unregisterCallback(mClientCallback);
-
- assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
- }
-
- @Test
- public void unregisterCallback_doubleUnregistration_serviceNotConnected_shouldFail() {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(null);
-
- manager.registerCallback(mExecutor, mClientCallback);
- manager.unregisterCallback(mClientCallback);
-
- assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
- }
-
- @Test
- public void unregisterCallback_remoteException_shouldFail() throws Exception {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
-
- doThrow(new RemoteException()).when(mService).unregisterCallback(any());
-
- assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
- }
-
- @Test
- public void onServiceConnected() {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
-
- manager.registerCallback(mExecutor, mClientCallback);
- manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
-
- verify(mClientCallback).onServiceConnected();
- }
-
- @Test
- public void onServiceDisconnected() {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
-
- manager.registerCallback(mExecutor, mClientCallback);
- manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
- manager.getServiceConnection().onServiceDisconnected(COMPONENT_NAME);
-
- verify(mClientCallback).onServiceDisconnected();
- }
-
-
- @Test
- public void connectHotspotNetwork_serviceNotConnected_shouldFail() {
- HotspotNetwork network = buildHotspotNetwork();
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(null);
-
- assertThat(manager.connectHotspotNetwork(network)).isFalse();
- }
-
- @Test
- public void connectHotspotNetwork() throws RemoteException {
- HotspotNetwork network = buildHotspotNetwork();
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
-
- manager.connectHotspotNetwork(network);
-
- verify(mService).connectHotspotNetwork(network);
- }
-
- @Test
- public void connectHotspotNetwork_remoteException_shouldFail() throws RemoteException {
- HotspotNetwork network = buildHotspotNetwork();
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
- doThrow(new RemoteException()).when(mService).connectHotspotNetwork(network);
-
- assertThat(manager.connectHotspotNetwork(network)).isFalse();
- }
-
- @Test
- public void disconnectHotspotNetwork_serviceNotConnected_shouldFail() {
- HotspotNetwork network = buildHotspotNetwork();
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(null);
-
- assertThat(manager.disconnectHotspotNetwork(network)).isFalse();
- }
-
- @Test
- public void disconnectHotspotNetwork() throws RemoteException {
- HotspotNetwork network = buildHotspotNetwork();
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
-
- manager.disconnectHotspotNetwork(network);
-
- verify(mService).disconnectHotspotNetwork(network);
- }
-
- @Test
- public void disconnectHotspotNetwork_remoteException_shouldFail() throws RemoteException {
- HotspotNetwork network = buildHotspotNetwork();
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
- doThrow(new RemoteException()).when(mService).disconnectHotspotNetwork(any());
-
- assertThat(manager.disconnectHotspotNetwork(network)).isFalse();
- }
-
- @Test
- public void connectKnownNetwork_serviceNotConnected_shouldFail() throws RemoteException {
- KnownNetwork network = buildKnownNetwork();
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(null);
-
- assertThat(manager.connectKnownNetwork(network)).isFalse();
- }
-
- @Test
- public void connectKnownNetwork() throws RemoteException {
- KnownNetwork network = buildKnownNetwork();
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
-
- manager.connectKnownNetwork(network);
-
- verify(mService).connectKnownNetwork(network);
- }
-
- @Test
- public void connectKnownNetwork_remoteException_shouldFail() throws RemoteException {
- KnownNetwork network = buildKnownNetwork();
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
- doThrow(new RemoteException()).when(mService).connectKnownNetwork(network);
-
- assertThat(manager.connectKnownNetwork(network)).isFalse();
- }
-
- @Test
- public void forgetKnownNetwork_serviceNotConnected_shouldFail() {
- KnownNetwork network = buildKnownNetwork();
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(null);
-
- assertThat(manager.forgetKnownNetwork(network)).isFalse();
- }
-
- @Test
- public void forgetKnownNetwork_serviceConnected() throws RemoteException {
- KnownNetwork network = buildKnownNetwork();
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
-
- manager.forgetKnownNetwork(network);
-
- verify(mService).forgetKnownNetwork(network);
- }
-
- @Test
- public void forgetKnownNetwork_remoteException_shouldFail() throws RemoteException {
- KnownNetwork network = buildKnownNetwork();
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
- doThrow(new RemoteException()).when(mService).forgetKnownNetwork(network);
-
- assertThat(manager.forgetKnownNetwork(network)).isFalse();
- }
-
- @Test
- public void getHotspotNetworks_serviceNotConnected_shouldReturnNull() {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(null);
-
- assertThat(manager.getHotspotNetworks()).isNull();
- }
-
- @Test
- public void getHotspotNetworks_remoteException_shouldReturnNull() throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
- doThrow(new RemoteException()).when(mService).getHotspotNetworks();
-
- assertThat(manager.getHotspotNetworks()).isNull();
- }
-
- @Test
- public void getHotspotNetworks_shouldReturnNetworksList() throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- List<HotspotNetwork> networks = List.of(buildHotspotNetwork());
- manager.setService(mService);
- when(mService.getHotspotNetworks()).thenReturn(networks);
-
- assertThat(manager.getHotspotNetworks()).containsExactly(buildHotspotNetwork());
- }
-
- @Test
- public void getKnownNetworks_serviceNotConnected_shouldReturnNull()
- throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(null);
-
- assertThat(manager.getKnownNetworks()).isNull();
- }
-
- @Test
- public void getKnownNetworks_remoteException_shouldReturnNull() throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
- doThrow(new RemoteException()).when(mService).getKnownNetworks();
-
- assertThat(manager.getKnownNetworks()).isNull();
- }
-
- @Test
- public void getKnownNetworks_shouldReturnNetworksList() throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- List<KnownNetwork> networks = List.of(buildKnownNetwork());
- manager.setService(mService);
- when(mService.getKnownNetworks()).thenReturn(networks);
-
- assertThat(manager.getKnownNetworks()).containsExactly(buildKnownNetwork());
- }
-
- @Test
- public void getSettingsState_serviceNotConnected_shouldReturnNull() throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(null);
-
- assertThat(manager.getSettingsState()).isNull();
- }
-
- @Test
- public void getSettingsState_remoteException_shouldReturnNull() throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
- doThrow(new RemoteException()).when(mService).getSettingsState();
-
- assertThat(manager.getSettingsState()).isNull();
- }
-
- @Test
- public void getSettingsState_serviceConnected_shouldReturnState() throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- SharedConnectivitySettingsState state =
- new SharedConnectivitySettingsState.Builder().setInstantTetherEnabled(true)
- .setExtras(new Bundle()).build();
- manager.setService(mService);
- when(mService.getSettingsState()).thenReturn(state);
-
- assertThat(manager.getSettingsState()).isEqualTo(state);
- }
-
- @Test
- public void getHotspotNetworkConnectionStatus_serviceNotConnected_shouldReturnNull()
- throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(null);
-
- assertThat(manager.getHotspotNetworkConnectionStatus()).isNull();
- }
-
- @Test
- public void getHotspotNetworkConnectionStatus_remoteException_shouldReturnNull()
- throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
- doThrow(new RemoteException()).when(mService).getHotspotNetworkConnectionStatus();
-
- assertThat(manager.getHotspotNetworkConnectionStatus()).isNull();
- }
-
- @Test
- public void getHotspotNetworkConnectionStatus_serviceConnected_shouldReturnStatus()
- throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- HotspotNetworkConnectionStatus status = new HotspotNetworkConnectionStatus.Builder()
- .setStatus(HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT)
- .setExtras(new Bundle()).build();
- manager.setService(mService);
- when(mService.getHotspotNetworkConnectionStatus()).thenReturn(status);
-
- assertThat(manager.getHotspotNetworkConnectionStatus()).isEqualTo(status);
- }
-
- @Test
- public void getKnownNetworkConnectionStatus_serviceNotConnected_shouldReturnNull()
- throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(null);
-
- assertThat(manager.getKnownNetworkConnectionStatus()).isNull();
- }
-
- @Test
- public void getKnownNetworkConnectionStatus_remoteException_shouldReturnNull()
- throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- manager.setService(mService);
- doThrow(new RemoteException()).when(mService).getKnownNetworkConnectionStatus();
-
- assertThat(manager.getKnownNetworkConnectionStatus()).isNull();
- }
-
- @Test
- public void getKnownNetworkConnectionStatus_serviceConnected_shouldReturnStatus()
- throws RemoteException {
- SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
- KnownNetworkConnectionStatus status = new KnownNetworkConnectionStatus.Builder()
- .setStatus(KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVED)
- .setExtras(new Bundle()).build();
- manager.setService(mService);
- when(mService.getKnownNetworkConnectionStatus()).thenReturn(status);
-
- assertThat(manager.getKnownNetworkConnectionStatus()).isEqualTo(status);
- }
-
- private void setResources(@Mock Context context) {
- when(context.getResources()).thenReturn(mResources);
- when(mResources.getString(anyInt()))
- .thenReturn(SERVICE_PACKAGE_NAME, SERVICE_INTENT_ACTION);
- }
-
- private HotspotNetwork buildHotspotNetwork() {
- HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
- .setDeviceId(DEVICE_ID)
- .setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
- .setHostNetworkType(NETWORK_TYPE)
- .setNetworkName(NETWORK_NAME)
- .setHotspotSsid(HOTSPOT_SSID);
- Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
- return builder.build();
- }
-
- private KnownNetwork buildKnownNetwork() {
- KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
- .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
- Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
- return builder.build();
- }
-}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java
deleted file mode 100644
index d6e7138..0000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.sharedconnectivity.app;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertThrows;
-
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.os.Parcel;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Unit tests for {@link SharedConnectivitySettingsState}.
- */
-@SmallTest
-public class SharedConnectivitySettingsStateTest {
- private static final boolean INSTANT_TETHER_STATE = true;
- private static final String INTENT_ACTION = "instant.tether.settings";
-
- private static final boolean INSTANT_TETHER_STATE_1 = false;
- private static final String INTENT_ACTION_1 = "instant.tether.settings1";
-
- @Test
- public void pendingIntentMutable_buildShouldThrow() {
- SharedConnectivitySettingsState.Builder builder =
- new SharedConnectivitySettingsState.Builder()
- .setInstantTetherEnabled(INSTANT_TETHER_STATE)
- .setInstantTetherSettingsPendingIntent(PendingIntent.getActivity(
- ApplicationProvider.getApplicationContext(), 0,
- new Intent(INTENT_ACTION).setComponent(new ComponentName(
- "com.test.package", "TestClass")),
- PendingIntent.FLAG_MUTABLE));
-
- Exception e = assertThrows(IllegalArgumentException.class, builder::build);
- assertThat(e.getMessage()).contains("Pending intent must be immutable");
- }
-
- @Test
- public void parcelOperation() {
- SharedConnectivitySettingsState state = buildSettingsStateBuilder(INTENT_ACTION).build();
-
- Parcel parcel = Parcel.obtain();
- state.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- SharedConnectivitySettingsState fromParcel =
- SharedConnectivitySettingsState.CREATOR.createFromParcel(parcel);
-
- assertThat(fromParcel).isEqualTo(state);
- assertThat(fromParcel.hashCode()).isEqualTo(state.hashCode());
- }
-
- @Test
- public void equalsOperation() {
- SharedConnectivitySettingsState state1 = buildSettingsStateBuilder(INTENT_ACTION).build();
- SharedConnectivitySettingsState state2 = buildSettingsStateBuilder(INTENT_ACTION).build();
- assertThat(state1).isEqualTo(state2);
-
- SharedConnectivitySettingsState.Builder builder = buildSettingsStateBuilder(INTENT_ACTION)
- .setInstantTetherEnabled(INSTANT_TETHER_STATE_1);
- assertThat(builder.build()).isNotEqualTo(state1);
-
- builder = buildSettingsStateBuilder(INTENT_ACTION_1);
- assertThat(builder.build()).isNotEqualTo(state1);
- }
-
- @Test
- public void getMethods() {
- SharedConnectivitySettingsState state = buildSettingsStateBuilder(INTENT_ACTION).build();
-
- assertThat(state.isInstantTetherEnabled()).isEqualTo(INSTANT_TETHER_STATE);
- assertThat(state.getInstantTetherSettingsPendingIntent())
- .isEqualTo(buildPendingIntent(INTENT_ACTION));
- }
-
- @Test
- public void hashCodeCalculation() {
- SharedConnectivitySettingsState state1 = buildSettingsStateBuilder(INTENT_ACTION).build();
- SharedConnectivitySettingsState state2 = buildSettingsStateBuilder(INTENT_ACTION).build();
-
- assertThat(state1.hashCode()).isEqualTo(state2.hashCode());
- }
-
- private SharedConnectivitySettingsState.Builder buildSettingsStateBuilder(String intentAction) {
- return new SharedConnectivitySettingsState.Builder()
- .setInstantTetherEnabled(INSTANT_TETHER_STATE)
- .setInstantTetherSettingsPendingIntent(buildPendingIntent(intentAction));
- }
-
- private PendingIntent buildPendingIntent(String intentAction) {
- return PendingIntent.getActivity(
- ApplicationProvider.getApplicationContext(), 0,
- new Intent(intentAction), PendingIntent.FLAG_IMMUTABLE);
- }
-}