Merge "Remove SkCanvas::flush() and related code from RecordingCanvas" into main
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index d76e201..37a1e62 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -4699,8 +4699,14 @@
@UnsupportedAppUsage
public static int checkComponentPermission(String permission, int uid,
int owningUid, boolean exported) {
+ return checkComponentPermission(permission, uid, Context.DEVICE_ID_DEFAULT,
+ owningUid, exported);
+ }
+
+ /** @hide */
+ public static int checkComponentPermission(String permission, int uid, int deviceId,
+ int owningUid, boolean exported) {
// Root, system server get to do everything.
- final int appId = UserHandle.getAppId(uid);
if (canAccessUnexportedComponents(uid)) {
return PackageManager.PERMISSION_GRANTED;
}
@@ -4727,8 +4733,7 @@
return PackageManager.PERMISSION_GRANTED;
}
try {
- return AppGlobals.getPackageManager()
- .checkUidPermission(permission, uid);
+ return AppGlobals.getPermissionManager().checkUidPermission(uid, permission, deviceId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4737,8 +4742,8 @@
/** @hide */
public static int checkUidPermission(String permission, int uid) {
try {
- return AppGlobals.getPackageManager()
- .checkUidPermission(permission, uid);
+ return AppGlobals.getPermissionManager().checkUidPermission(
+ uid, permission, Context.DEVICE_ID_DEFAULT);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index d859f3f..7b3d017 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -460,6 +460,14 @@
*/
public static final int SUBREASON_SDK_SANDBOX_NOT_NEEDED = 28;
+ /**
+ * The process was killed because the binder proxy limit for system server was exceeded.
+ *
+ * For internal use only.
+ * @hide
+ */
+ public static final int SUBREASON_EXCESSIVE_BINDER_OBJECTS = 29;
+
// If there is any OEM code which involves additional app kill reasons, it should
// be categorized in {@link #REASON_OTHER}, with subreason code starting from 1000.
@@ -635,6 +643,7 @@
SUBREASON_KILL_BACKGROUND,
SUBREASON_PACKAGE_UPDATE,
SUBREASON_UNDELIVERED_BROADCAST,
+ SUBREASON_EXCESSIVE_BINDER_OBJECTS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SubReason {}
@@ -1360,6 +1369,8 @@
return "PACKAGE UPDATE";
case SUBREASON_UNDELIVERED_BROADCAST:
return "UNDELIVERED BROADCAST";
+ case SUBREASON_EXCESSIVE_BINDER_OBJECTS:
+ return "EXCESSIVE BINDER OBJECTS";
default:
return "UNKNOWN";
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 0e3a695..9121cf0 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -827,7 +827,8 @@
@Override
public int checkPermission(String permName, String pkgName) {
- return PermissionManager.checkPackageNamePermission(permName, pkgName, getUserId());
+ return PermissionManager.checkPackageNamePermission(permName, pkgName,
+ mContext.getDeviceId(), getUserId());
}
@Override
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 2056eca..ab567ac 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2262,7 +2262,7 @@
Log.v(TAG, "Treating renounced permission " + permission + " as denied");
return PERMISSION_DENIED;
}
- return PermissionManager.checkPermission(permission, pid, uid);
+ return PermissionManager.checkPermission(permission, pid, uid, getDeviceId());
}
/** @hide */
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 46260ea..a8b1688 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -924,4 +924,6 @@
void unregisterUidFrozenStateChangedCallback(in IUidFrozenStateChangedCallback callback);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)")
int[] getUidFrozenState(in int[] uids);
+
+ int checkPermissionForDevice(in String permission, int pid, int uid, int deviceId);
}
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index f7d2afb..e1c45d9 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -63,10 +63,11 @@
# Multiuser
per-file *User* = file:/MULTIUSER_OWNERS
-# Notification, DND, Status bar
+# Notification, DND, Status bar, UiModeManager
per-file *Notification* = file:/packages/SystemUI/OWNERS
per-file *Zen* = file:/packages/SystemUI/OWNERS
per-file *StatusBar* = file:/packages/SystemUI/OWNERS
+per-file *UiModeManager* = file:/packages/SystemUI/OWNERS
# PackageManager
per-file ApplicationPackageManager.java = file:/services/core/java/com/android/server/pm/OWNERS
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 52949d6..6f4abfd 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -343,6 +343,9 @@
}
}
+ /**
+ * Grants permission for the {@link Context#DEVICE_ID_DEFAULT default device}
+ */
@Override
public void grantRuntimePermission(String packageName, String permission, int userId)
throws RemoteException {
@@ -353,12 +356,16 @@
}
final long identity = Binder.clearCallingIdentity();
try {
- mPermissionManager.grantRuntimePermission(packageName, permission, userId);
+ mPermissionManager.grantRuntimePermission(packageName, permission,
+ Context.DEVICE_ID_DEFAULT, userId);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
+ /**
+ * Revokes permission for the {@link Context#DEVICE_ID_DEFAULT default device}
+ */
@Override
public void revokeRuntimePermission(String packageName, String permission, int userId)
throws RemoteException {
@@ -369,7 +376,8 @@
}
final long identity = Binder.clearCallingIdentity();
try {
- mPermissionManager.revokeRuntimePermission(packageName, permission, userId, null);
+ mPermissionManager.revokeRuntimePermission(packageName, permission,
+ Context.DEVICE_ID_DEFAULT, userId, null);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/core/java/android/app/admin/PasswordMetrics.java b/core/java/android/app/admin/PasswordMetrics.java
index 93c0c8a..dd31175 100644
--- a/core/java/android/app/admin/PasswordMetrics.java
+++ b/core/java/android/app/admin/PasswordMetrics.java
@@ -179,17 +179,11 @@
};
/**
- * Returns the {@code PasswordMetrics} for a given credential.
- *
- * If the credential is a pin or a password, equivalent to
- * {@link #computeForPasswordOrPin(byte[], boolean)}. {@code credential} cannot be null
- * when {@code type} is
- * {@link com.android.internal.widget.LockPatternUtils#CREDENTIAL_TYPE_PASSWORD}.
+ * Returns the {@code PasswordMetrics} for the given credential.
*/
public static PasswordMetrics computeForCredential(LockscreenCredential credential) {
if (credential.isPassword() || credential.isPin()) {
- return PasswordMetrics.computeForPasswordOrPin(credential.getCredential(),
- credential.isPin());
+ return computeForPasswordOrPin(credential.getCredential(), credential.isPin());
} else if (credential.isPattern()) {
PasswordMetrics metrics = new PasswordMetrics(CREDENTIAL_TYPE_PATTERN);
metrics.length = credential.size();
@@ -202,10 +196,10 @@
}
/**
- * Returns the {@code PasswordMetrics} for a given password or pin
+ * Returns the {@code PasswordMetrics} for the given password or pin.
*/
- public static PasswordMetrics computeForPasswordOrPin(byte[] password, boolean isPin) {
- // Analyse the characters used
+ private static PasswordMetrics computeForPasswordOrPin(byte[] credential, boolean isPin) {
+ // Analyze the characters used.
int letters = 0;
int upperCase = 0;
int lowerCase = 0;
@@ -213,8 +207,8 @@
int symbols = 0;
int nonLetter = 0;
int nonNumeric = 0;
- final int length = password.length;
- for (byte b : password) {
+ final int length = credential.length;
+ for (byte b : credential) {
switch (categoryChar((char) b)) {
case CHAR_LOWER_CASE:
letters++;
@@ -239,7 +233,7 @@
}
final int credType = isPin ? CREDENTIAL_TYPE_PIN : CREDENTIAL_TYPE_PASSWORD;
- final int seqLength = maxLengthSequence(password);
+ final int seqLength = maxLengthSequence(credential);
return new PasswordMetrics(credType, length, letters, upperCase, lowerCase,
numeric, symbols, nonLetter, nonNumeric, seqLength);
}
diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java
index c0877d3..e886f68 100644
--- a/core/java/android/hardware/input/InputManagerGlobal.java
+++ b/core/java/android/hardware/input/InputManagerGlobal.java
@@ -54,6 +54,7 @@
import android.view.PointerIcon;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import java.util.ArrayList;
@@ -140,23 +141,27 @@
}
/**
- * Gets an instance of the input manager.
- *
- * @return The input manager instance.
+ * A test session tracker for InputManagerGlobal.
+ * @see #createTestSession(IInputManager)
*/
- public static InputManagerGlobal resetInstance(IInputManager inputManagerService) {
- synchronized (InputManager.class) {
- sInstance = new InputManagerGlobal(inputManagerService);
- return sInstance;
- }
+ @VisibleForTesting
+ public interface TestSession extends AutoCloseable {
+ @Override
+ void close();
}
/**
- * Clear the instance of the input manager.
+ * Create and set a test instance of InputManagerGlobal.
+ *
+ * @return The test session. The session must be {@link TestSession#close()}-ed at the end
+ * of the test.
*/
- public static void clearInstance() {
+ @VisibleForTesting
+ public static TestSession createTestSession(IInputManager inputManagerService) {
synchronized (InputManagerGlobal.class) {
- sInstance = null;
+ final var oldInstance = sInstance;
+ sInstance = new InputManagerGlobal(inputManagerService);
+ return () -> sInstance = oldInstance;
}
}
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index d19fd8f..18ede44d 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -42,10 +42,10 @@
void removePermission(String permissionName);
- int getPermissionFlags(String packageName, String permissionName, int userId);
+ int getPermissionFlags(String packageName, String permissionName, int deviceId, int userId);
void updatePermissionFlags(String packageName, String permissionName, int flagMask,
- int flagValues, boolean checkAdjustPolicyFlagPermission, int userId);
+ int flagValues, boolean checkAdjustPolicyFlagPermission, int deviceId, int userId);
void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId);
@@ -62,17 +62,18 @@
boolean removeAllowlistedRestrictedPermission(String packageName, String permissionName,
int flags, int userId);
- void grantRuntimePermission(String packageName, String permissionName, int userId);
+ void grantRuntimePermission(String packageName, String permissionName, int deviceId, int userId);
- void revokeRuntimePermission(String packageName, String permissionName, int userId,
- String reason);
+ void revokeRuntimePermission(String packageName, String permissionName, int deviceId,
+ int userId, String reason);
void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId);
boolean shouldShowRequestPermissionRationale(String packageName, String permissionName,
- int userId);
+ int deviceId, int userId);
- boolean isPermissionRevokedByPolicy(String packageName, String permissionName, int userId);
+ boolean isPermissionRevokedByPolicy(String packageName, String permissionName, int deviceId,
+ int userId);
List<SplitPermissionInfoParcelable> getSplitPermissions();
@@ -94,4 +95,8 @@
void registerAttributionSource(in AttributionSourceState source);
boolean isRegisteredAttributionSource(in AttributionSourceState source);
+
+ int checkPermission(String packageName, String permissionName, int deviceId, int userId);
+
+ int checkUidPermission(int uid, String permissionName, int deviceId);
}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 9ae87de..7d39210 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -66,6 +66,7 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
@@ -571,7 +572,7 @@
@NonNull String permissionName) {
try {
return mPermissionManager.isPermissionRevokedByPolicy(packageName, permissionName,
- mContext.getUserId());
+ mContext.getDeviceId(), mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -615,7 +616,7 @@
}
try {
mPermissionManager.grantRuntimePermission(packageName, permissionName,
- user.getIdentifier());
+ mContext.getDeviceId(), user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -652,8 +653,8 @@
+ reason, new RuntimeException());
}
try {
- mPermissionManager
- .revokeRuntimePermission(packageName, permName, user.getIdentifier(), reason);
+ mPermissionManager.revokeRuntimePermission(packageName, permName,
+ mContext.getDeviceId(), user.getIdentifier(), reason);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -680,7 +681,7 @@
@NonNull UserHandle user) {
try {
return mPermissionManager.getPermissionFlags(packageName, permissionName,
- user.getIdentifier());
+ mContext.getDeviceId(), user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -719,7 +720,8 @@
final boolean checkAdjustPolicyFlagPermission =
mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q;
mPermissionManager.updatePermissionFlags(packageName, permissionName, flagMask,
- flagValues, checkAdjustPolicyFlagPermission, user.getIdentifier());
+ flagValues, checkAdjustPolicyFlagPermission,
+ mContext.getDeviceId(), user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -975,7 +977,7 @@
try {
final String packageName = mContext.getPackageName();
return mPermissionManager.shouldShowRequestPermissionRationale(packageName,
- permissionName, mContext.getUserId());
+ permissionName, mContext.getDeviceId(), mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1509,8 +1511,8 @@
// to reduce duplicate logcat output.
private static volatile boolean sShouldWarnMissingActivityManager = true;
- /* @hide */
- private static int checkPermissionUncached(@Nullable String permission, int pid, int uid) {
+ private static int checkPermissionUncached(@Nullable String permission, int pid, int uid,
+ int deviceId) {
final IActivityManager am = ActivityManager.getService();
if (am == null) {
// Well this is super awkward; we somehow don't have an active ActivityManager
@@ -1531,7 +1533,7 @@
}
try {
sShouldWarnMissingActivityManager = true;
- return am.checkPermission(permission, pid, uid);
+ return am.checkPermissionForDevice(permission, pid, uid, deviceId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1551,26 +1553,26 @@
final String permission;
final int pid;
final int uid;
+ final int deviceId;
- PermissionQuery(@Nullable String permission, int pid, int uid) {
+ PermissionQuery(@Nullable String permission, int pid, int uid, int deviceId) {
this.permission = permission;
this.pid = pid;
this.uid = uid;
+ this.deviceId = deviceId;
}
@Override
public String toString() {
- return String.format("PermissionQuery(permission=\"%s\", pid=%s, uid=%s)",
- permission, pid, uid);
+ return TextUtils.formatSimple("PermissionQuery(permission=\"%s\", pid=%d, uid=%d, "
+ + "deviceId=%d)", permission, pid, uid, deviceId);
}
@Override
public int hashCode() {
// N.B. pid doesn't count toward equality and therefore shouldn't count for
// hashing either.
- int hash = Objects.hashCode(permission);
- hash = hash * 13 + Objects.hashCode(uid);
- return hash;
+ return Objects.hash(permission, uid, deviceId);
}
@Override
@@ -1585,7 +1587,7 @@
} catch (ClassCastException ex) {
return false;
}
- return uid == other.uid
+ return uid == other.uid && deviceId == other.deviceId
&& Objects.equals(permission, other.permission);
}
}
@@ -1599,13 +1601,14 @@
2048, CACHE_KEY_PACKAGE_INFO, "checkPermission") {
@Override
public Integer recompute(PermissionQuery query) {
- return checkPermissionUncached(query.permission, query.pid, query.uid);
+ return checkPermissionUncached(query.permission, query.pid, query.uid,
+ query.deviceId);
}
};
/** @hide */
- public static int checkPermission(@Nullable String permission, int pid, int uid) {
- return sPermissionCache.query(new PermissionQuery(permission, pid, uid));
+ public static int checkPermission(@Nullable String permission, int pid, int uid, int deviceId) {
+ return sPermissionCache.query(new PermissionQuery(permission, pid, uid, deviceId));
}
/**
@@ -1625,26 +1628,29 @@
private static final class PackageNamePermissionQuery {
final String permName;
final String pkgName;
+ final int deviceId;
@UserIdInt
final int userId;
PackageNamePermissionQuery(@Nullable String permName, @Nullable String pkgName,
- @UserIdInt int userId) {
+ int deviceId, @UserIdInt int userId) {
this.permName = permName;
this.pkgName = pkgName;
+ this.deviceId = deviceId;
this.userId = userId;
}
@Override
public String toString() {
- return String.format(
- "PackageNamePermissionQuery(pkgName=\"%s\", permName=\"%s, userId=%s\")",
- pkgName, permName, userId);
+ return TextUtils.formatSimple(
+ "PackageNamePermissionQuery(pkgName=\"%s\", permName=\"%s\", "
+ + "deviceId=%s, userId=%s\")",
+ pkgName, permName, deviceId, userId);
}
@Override
public int hashCode() {
- return Objects.hash(permName, pkgName, userId);
+ return Objects.hash(permName, pkgName, deviceId, userId);
}
@Override
@@ -1660,16 +1666,17 @@
}
return Objects.equals(permName, other.permName)
&& Objects.equals(pkgName, other.pkgName)
+ && deviceId == other.deviceId
&& userId == other.userId;
}
}
/* @hide */
private static int checkPackageNamePermissionUncached(
- String permName, String pkgName, @UserIdInt int userId) {
+ String permName, String pkgName, int deviceId, @UserIdInt int userId) {
try {
- return ActivityThread.getPackageManager().checkPermission(
- permName, pkgName, userId);
+ return ActivityThread.getPermissionManager().checkPermission(
+ pkgName, permName, deviceId, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1683,7 +1690,7 @@
@Override
public Integer recompute(PackageNamePermissionQuery query) {
return checkPackageNamePermissionUncached(
- query.permName, query.pkgName, query.userId);
+ query.permName, query.pkgName, query.deviceId, query.userId);
}
@Override
public boolean bypass(PackageNamePermissionQuery query) {
@@ -1692,14 +1699,14 @@
};
/**
- * Check whether a package has a permission.
+ * Check whether a package has a permission for given device.
*
* @hide
*/
- public static int checkPackageNamePermission(String permName, String pkgName,
+ public static int checkPackageNamePermission(String permName, String pkgName, int deviceId,
@UserIdInt int userId) {
return sPackageNamePermissionCache.query(
- new PackageNamePermissionQuery(permName, pkgName, userId));
+ new PackageNamePermissionQuery(permName, pkgName, deviceId, userId));
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bf8c0d2..9f1cc71 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -32104,9 +32104,7 @@
return false;
}
- getLocationInWindow(mAttachInfo.mTmpLocation);
- return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
- && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
+ return true;
}
/**
diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java
index afc567e..c88048c 100644
--- a/core/java/android/view/WindowManagerPolicyConstants.java
+++ b/core/java/android/view/WindowManagerPolicyConstants.java
@@ -97,6 +97,12 @@
*/
String EXTRA_START_REASON = "android.intent.extra.EXTRA_START_REASON";
+ /**
+ * Set to {@code true} when intent was invoked from pressing one of the brightness keys.
+ * @hide
+ */
+ String EXTRA_FROM_BRIGHTNESS_KEY = "android.intent.extra.FROM_BRIGHTNESS_KEY";
+
// TODO: move this to a more appropriate place.
interface PointerEventListener {
/**
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index e098b63..a43906f 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -192,6 +192,8 @@
* <li>{@link #getEventTime()} - The event time.</li>
* <li>{@link #getScrollDeltaX()} - The difference in the horizontal position.</li>
* <li>{@link #getScrollDeltaY()} - The difference in the vertical position.</li>
+ * <li>{@link #getMaxScrollX()} ()} - The max scroll offset of the source left edge</li>
+ * <li>{@link #getMaxScrollY()} ()} - The max scroll offset of the source top edge.</li>
* </ul>
* </p>
* <p>
@@ -538,8 +540,18 @@
public static final int TYPE_WINDOW_CONTENT_CHANGED = 1 << 11;
/**
- * Represents the event of scrolling a view. This event type is generally not sent directly.
- * @see android.view.View#onScrollChanged(int, int, int, int)
+ * Represents the event of scrolling a view. This event type is generally not sent directly. In
+ * the View system, this is sent in
+ * {@link android.view.View#onScrollChanged(int, int, int, int)}
+ * <p>In addition to the source and package name, the event should populate scroll-specific
+ * properties like {@link #setScrollDeltaX(int)}, {@link #setScrollDeltaY(int)},
+ * {@link #setMaxScrollX(int)}, and {@link #setMaxScrollY(int)}.
+ * <p>Services are encouraged to rely on the source to query UI state over AccessibilityEvents
+ * properties. For example, to check after a scroll if the bottom of the scrolling UI element
+ * has been reached, check if the source node is scrollable and has the
+ * {@link AccessibilityNodeInfo.AccessibilityAction#ACTION_SCROLL_BACKWARD} action but not the
+ * {@link AccessibilityNodeInfo.AccessibilityAction#ACTION_SCROLL_FORWARD} action.
+ * For scrolling to a target, use {@link #TYPE_VIEW_TARGETED_BY_SCROLL}.
*/
public static final int TYPE_VIEW_SCROLLED = 1 << 12;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 2939954..e6a8b78 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -425,11 +425,13 @@
/**
* Action to scroll the node content forward.
+ * @see AccessibilityAction#ACTION_SCROLL_FORWARD
*/
public static final int ACTION_SCROLL_FORWARD = 1 << 12;
/**
* Action to scroll the node content backward.
+ * @see AccessibilityAction#ACTION_SCROLL_BACKWARD
*/
public static final int ACTION_SCROLL_BACKWARD = 1 << 13;
@@ -5404,6 +5406,42 @@
* <strong>Arguments:</strong>
* {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT}. This is an optional argument.
* </p>
+ * <p>The UI element that implements this should send a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. Depending on the orientation,
+ * this element should also add the relevant directional scroll actions of
+ * {@link #ACTION_SCROLL_LEFT}, {@link #ACTION_SCROLL_RIGHT},
+ * {@link #ACTION_SCROLL_UP}, and {@link #ACTION_SCROLL_DOWN}. If the scrolling brings
+ * the next or previous element into view as the center element, such as in a ViewPager2,
+ * use {@link #ACTION_PAGE_DOWN} and the other page actions instead of the directional
+ * actions.
+ * <p>Example: a scrolling UI of vertical orientation with a forward
+ * scroll action should also add the scroll down action:
+ * <pre class="prettyprint"><code>
+ * onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ * super.onInitializeAccessibilityNodeInfo(info);
+ * if (canScrollForward) {
+ * info.addAction(ACTION_SCROLL_FORWARD);
+ * info.addAction(ACTION_SCROLL_DOWN);
+ * }
+ * }
+ * performAccessibilityAction(int action, Bundle bundle) {
+ * if (action == ACTION_SCROLL_FORWARD || action == ACTION_SCROLL_DOWN) {
+ * scrollForward();
+ * }
+ * }
+ * scrollForward() {
+ * ...
+ * if (mAccessibilityManager.isEnabled()) {
+ * event = new AccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
+ * event.setScrollDeltaX(dx);
+ * event.setScrollDeltaY(dy);
+ * event.setMaxScrollX(maxDx);
+ * event.setMaxScrollY(maxDY);
+ * sendAccessibilityEventUnchecked(event);
+ * }
+ * }
+ * </code>
+ * </pre></p>
*/
public static final AccessibilityAction ACTION_SCROLL_FORWARD =
new AccessibilityAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
@@ -5414,6 +5452,54 @@
* <strong>Arguments:</strong>
* {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT}. This is an optional argument.
* </p>
+ * <p>The UI element that implements this should send a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. Depending on the orientation,
+ * this element should also add the relevant directional scroll actions of
+ * {@link #ACTION_SCROLL_LEFT}, {@link #ACTION_SCROLL_RIGHT},
+ * {@link #ACTION_SCROLL_UP}, and {@link #ACTION_SCROLL_DOWN}. If the scrolling brings
+ * the next or previous element into view as the center element, such as in a ViewPager2,
+ * use {@link #ACTION_PAGE_DOWN} and the other page actions instead of the directional
+ * actions.
+ * <p> Example: a scrolling UI of horizontal orientation with a backward
+ * scroll action should also add the scroll left/right action (LTR/RTL):
+ * <pre class="prettyprint"><code>
+ * onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ * super.onInitializeAccessibilityNodeInfo(info);
+ * if (canScrollBackward) {
+ * info.addAction(ACTION_SCROLL_FORWARD);
+ * if (leftToRight) {
+ * info.addAction(ACTION_SCROLL_LEFT);
+ * } else {
+ * info.addAction(ACTION_SCROLL_RIGHT);
+ * }
+ * }
+ * }
+ * performAccessibilityAction(int action, Bundle bundle) {
+ * if (action == ACTION_SCROLL_BACKWARD) {
+ * scrollBackward();
+ * } else if (action == ACTION_SCROLL_LEFT) {
+ * if (!isRTL()){
+ * scrollBackward();
+ * }
+ * } else if (action == ACTION_SCROLL_RIGHT) {
+ * if (isRTL()){
+ * scrollBackward();
+ * }
+ * }
+ * }
+ * scrollBackward() {
+ * ...
+ * if (mAccessibilityManager.isEnabled()) {
+ * event = new AccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
+ * event.setScrollDeltaX(dx);
+ * event.setScrollDeltaY(dy);
+ * event.setMaxScrollX(maxDx);
+ * event.setMaxScrollY(maxDY);
+ * sendAccessibilityEventUnchecked(event);
+ * }
+ * }
+ * </code>
+ * </pre></p>
*/
public static final AccessibilityAction ACTION_SCROLL_BACKWARD =
new AccessibilityAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
@@ -5509,6 +5595,8 @@
/**
* Action that requests the node make its bounding rectangle visible
* on the screen, scrolling if necessary just enough.
+ * <p>The UI element that implements this should send a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
*
* @see View#requestRectangleOnScreen(Rect)
*/
@@ -5524,6 +5612,8 @@
* <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_ROW_INT}</li>
* <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_COLUMN_INT}</li>
* <ul>
+ * <p>The UI element that implements this should send a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
*
* @see AccessibilityNodeInfo#getCollectionInfo()
*/
@@ -5562,6 +5652,8 @@
* <strong>Arguments:</strong>
* {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT}. This is an optional argument.
* </p>
+ * <p>The UI element that implements this should send a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
*/
public static final AccessibilityAction ACTION_SCROLL_UP =
new AccessibilityAction(R.id.accessibilityActionScrollUp);
@@ -5572,6 +5664,8 @@
* <strong>Arguments:</strong>
* {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT}. This is an optional argument.
* </p>
+ * <p>The UI element that implements this should send a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
*/
public static final AccessibilityAction ACTION_SCROLL_LEFT =
new AccessibilityAction(R.id.accessibilityActionScrollLeft);
@@ -5582,6 +5676,8 @@
* <strong>Arguments:</strong>
* {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT}. This is an optional argument.
* </p>
+ * <p>The UI element that implements this should send a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
*/
public static final AccessibilityAction ACTION_SCROLL_DOWN =
new AccessibilityAction(R.id.accessibilityActionScrollDown);
@@ -5592,30 +5688,40 @@
* <strong>Arguments:</strong>
* {@link #ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT}. This is an optional argument.
* </p>
+ * <p>The UI element that implements this should send a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
*/
public static final AccessibilityAction ACTION_SCROLL_RIGHT =
new AccessibilityAction(R.id.accessibilityActionScrollRight);
/**
* Action to move to the page above.
+ * <p>The UI element that implements this should send a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
*/
public static final AccessibilityAction ACTION_PAGE_UP =
new AccessibilityAction(R.id.accessibilityActionPageUp);
/**
* Action to move to the page below.
+ * <p>The UI element that implements this should send a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
*/
public static final AccessibilityAction ACTION_PAGE_DOWN =
new AccessibilityAction(R.id.accessibilityActionPageDown);
/**
* Action to move to the page left.
+ * <p>The UI element that implements this should send a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
*/
public static final AccessibilityAction ACTION_PAGE_LEFT =
new AccessibilityAction(R.id.accessibilityActionPageLeft);
/**
* Action to move to the page right.
+ * <p>The UI element that implements this should send a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
*/
public static final AccessibilityAction ACTION_PAGE_RIGHT =
new AccessibilityAction(R.id.accessibilityActionPageRight);
@@ -5720,8 +5826,9 @@
* This action initiates a drag & drop within the system. The source's dragged content is
* prepared before the drag begins. In View, this action should prepare the arguments to
* {@link View#startDragAndDrop(ClipData, View.DragShadowBuilder, Object, int)} and then
- * call {@link View#startDragAndDrop(ClipData, View.DragShadowBuilder, Object, int)}. The
- * equivalent should be performed for other UI toolkits.
+ * call {@link View#startDragAndDrop(ClipData, View.DragShadowBuilder, Object, int)} with
+ * {@link View#DRAG_FLAG_ACCESSIBILITY_ACTION}. The equivalent should be performed for other
+ * UI toolkits.
* </p>
*
* @see AccessibilityEvent#CONTENT_CHANGE_TYPE_DRAG_STARTED
@@ -5735,7 +5842,8 @@
* This action is added to potential drop targets if the source started a drag with
* {@link #ACTION_DRAG_START}. In View, these targets are Views that accepted
* {@link android.view.DragEvent#ACTION_DRAG_STARTED} and have an
- * {@link View.OnDragListener}.
+ * {@link View.OnDragListener}, and the drop occurs at the center location of the View's
+ * window bounds.
* </p>
*
* @see AccessibilityEvent#CONTENT_CHANGE_TYPE_DRAG_DROPPED
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index c9afdc0..2c7d326 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -414,7 +414,7 @@
/** @hide */
public static final boolean DEFAULT_ENABLE_CONTENT_PROTECTION_RECEIVER = false;
/** @hide */
- public static final int DEFAULT_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE = 1000;
+ public static final int DEFAULT_CONTENT_PROTECTION_APPS_BLOCKLIST_SIZE = 5000;
/** @hide */
public static final int DEFAULT_CONTENT_PROTECTION_BUFFER_SIZE = 150;
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index b7a2c71..0d1871d 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -99,12 +99,6 @@
(thread == null) ? BackgroundThread.getHandler() : new Handler(thread));
}
- public void register(Context context, UserHandle user,
- boolean externalStorage, Handler handler) {
- // Remove until all using code are updated to new method.
- register(context, user, handler);
- }
-
/**
* Register for notifications of package changes such as install, removal and other events.
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index e1be0cd..0b51a41 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -30,6 +30,8 @@
#include <media/AudioSystem.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/jni_macros.h>
#include <system/audio.h>
#include <system/audio_policy.h>
#include <utils/Log.h>
@@ -285,7 +287,7 @@
ALOGE("Can't find class %s", kEventHandlerClassPathName);
return;
}
- mClass = (jclass)env->NewGlobalRef(clazz);
+ mClass = static_cast<jclass>(env->NewGlobalRef(clazz));
// We use a weak reference so the AudioPortEventHandler object can be garbage collected.
// The reference is only used as a proxy for callbacks.
@@ -337,15 +339,16 @@
const sp<JNIAudioPortCallback>& callback)
{
Mutex::Autolock l(gLock);
- sp<JNIAudioPortCallback> old =
- (JNIAudioPortCallback*)env->GetLongField(thiz, gEventHandlerFields.mJniCallback);
+ sp<JNIAudioPortCallback> old = reinterpret_cast<JNIAudioPortCallback *>(
+ env->GetLongField(thiz, gEventHandlerFields.mJniCallback));
if (callback.get()) {
- callback->incStrong((void*)setJniCallback);
+ callback->incStrong(reinterpret_cast<void *>(setJniCallback));
}
if (old != 0) {
- old->decStrong((void*)setJniCallback);
+ old->decStrong(reinterpret_cast<void *>(setJniCallback));
}
- env->SetLongField(thiz, gEventHandlerFields.mJniCallback, (jlong)callback.get());
+ env->SetLongField(thiz, gEventHandlerFields.mJniCallback,
+ reinterpret_cast<jlong>(callback.get()));
return old;
}
@@ -374,43 +377,44 @@
jobjectArray deviceAddresses,
AudioDeviceTypeAddrVector &audioDeviceTypeAddrVector) {
if (deviceTypes == nullptr || deviceAddresses == nullptr) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
jsize deviceCount = env->GetArrayLength(deviceTypes);
if (deviceCount == 0 || deviceCount != env->GetArrayLength(deviceAddresses)) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
// retrieve all device types
std::vector<audio_devices_t> deviceTypesVector;
jint *typesPtr = nullptr;
typesPtr = env->GetIntArrayElements(deviceTypes, 0);
if (typesPtr == nullptr) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
for (jint i = 0; i < deviceCount; i++) {
- deviceTypesVector.push_back((audio_devices_t)typesPtr[i]);
+ deviceTypesVector.push_back(static_cast<audio_devices_t>(typesPtr[i]));
}
// check each address is a string and add device type/address to list
jclass stringClass = FindClassOrDie(env, "java/lang/String");
for (jint i = 0; i < deviceCount; i++) {
jobject addrJobj = env->GetObjectArrayElement(deviceAddresses, i);
if (!env->IsInstanceOf(addrJobj, stringClass)) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
- const char *address = env->GetStringUTFChars((jstring)addrJobj, NULL);
- AudioDeviceTypeAddr dev = AudioDeviceTypeAddr((audio_devices_t)typesPtr[i], address);
+ const char *address = env->GetStringUTFChars(static_cast<jstring>(addrJobj), NULL);
+ AudioDeviceTypeAddr dev =
+ AudioDeviceTypeAddr(static_cast<audio_devices_t>(typesPtr[i]), address);
audioDeviceTypeAddrVector.push_back(dev);
- env->ReleaseStringUTFChars((jstring)addrJobj, address);
+ env->ReleaseStringUTFChars(static_cast<jstring>(addrJobj), address);
}
env->ReleaseIntArrayElements(deviceTypes, typesPtr, 0);
- return (jint)NO_ERROR;
+ return NO_ERROR;
}
static jint
android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
{
- return (jint) check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
+ return check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
}
static jboolean
@@ -425,7 +429,7 @@
android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs)
{
bool state = false;
- AudioSystem::isStreamActive((audio_stream_type_t) stream, &state, inPastMs);
+ AudioSystem::isStreamActive(static_cast<audio_stream_type_t>(stream), &state, inPastMs);
return state;
}
@@ -434,7 +438,7 @@
jint inPastMs)
{
bool state = false;
- AudioSystem::isStreamActiveRemotely((audio_stream_type_t) stream, &state, inPastMs);
+ AudioSystem::isStreamActiveRemotely(static_cast<audio_stream_type_t>(stream), &state, inPastMs);
return state;
}
@@ -442,7 +446,7 @@
android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source)
{
bool state = false;
- AudioSystem::isSourceActive((audio_source_t) source, &state);
+ AudioSystem::isSourceActive(static_cast<audio_source_t>(source), &state);
return state;
}
@@ -478,7 +482,7 @@
env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
}
int status = check_AudioSystem_Command(AudioSystem::setParameters(c_keyValuePairs8));
- return (jint) status;
+ return status;
}
static jstring
@@ -558,15 +562,15 @@
return;
}
jint recParamData[REC_PARAM_SIZE];
- recParamData[0] = (jint) audioFormatFromNative(clientConfig->format);
+ recParamData[0] = audioFormatFromNative(clientConfig->format);
// FIXME this doesn't support index-based masks
- recParamData[1] = (jint) inChannelMaskFromNative(clientConfig->channel_mask);
- recParamData[2] = (jint) clientConfig->sample_rate;
- recParamData[3] = (jint) audioFormatFromNative(deviceConfig->format);
+ recParamData[1] = inChannelMaskFromNative(clientConfig->channel_mask);
+ recParamData[2] = clientConfig->sample_rate;
+ recParamData[3] = audioFormatFromNative(deviceConfig->format);
// FIXME this doesn't support index-based masks
- recParamData[4] = (jint) inChannelMaskFromNative(deviceConfig->channel_mask);
- recParamData[5] = (jint) deviceConfig->sample_rate;
- recParamData[6] = (jint) patchHandle;
+ recParamData[4] = inChannelMaskFromNative(deviceConfig->channel_mask);
+ recParamData[5] = deviceConfig->sample_rate;
+ recParamData[6] = patchHandle;
env->SetIntArrayRegion(recParamArray, 0, REC_PARAM_SIZE, recParamData);
jobjectArray jClientEffects;
@@ -580,10 +584,9 @@
env->CallStaticVoidMethod(clazz,
gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
- event, (jint) clientInfo->riid, (jint) clientInfo->uid,
- clientInfo->session, clientInfo->source, clientInfo->port_id,
- clientInfo->silenced, recParamArray, jClientEffects, jEffects,
- source);
+ event, clientInfo->riid, clientInfo->uid, clientInfo->session,
+ clientInfo->source, clientInfo->port_id, clientInfo->silenced,
+ recParamArray, jClientEffects, jEffects, source);
env->DeleteLocalRef(clazz);
env->DeleteLocalRef(recParamArray);
env->DeleteLocalRef(jClientEffects);
@@ -626,11 +629,9 @@
if (Parcel *parcel = parcelForJavaObject(env, jParcel); parcel != nullptr) {
android::media::audio::common::AudioPort port{};
if (status_t statusOfParcel = port.readFromParcel(parcel); statusOfParcel == OK) {
- status = check_AudioSystem_Command(
- AudioSystem::setDeviceConnectionState(static_cast<audio_policy_dev_state_t>(
- state),
- port,
- static_cast<audio_format_t>(codec)));
+ status = check_AudioSystem_Command(
+ AudioSystem::setDeviceConnectionState(static_cast<audio_policy_dev_state_t>(state),
+ port, static_cast<audio_format_t>(codec)));
} else {
ALOGE("Failed to read from parcel: %s", statusToString(statusOfParcel).c_str());
status = kAudioStatusError;
@@ -639,17 +640,17 @@
ALOGE("Failed to retrieve the native parcel from Java parcel");
status = kAudioStatusError;
}
- return (jint) status;
+ return status;
}
static jint
android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
{
const char *c_address = env->GetStringUTFChars(device_address, NULL);
- int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device),
- c_address));
+ int state = static_cast<int>(
+ AudioSystem::getDeviceConnectionState(static_cast<audio_devices_t>(device), c_address));
env->ReleaseStringUTFChars(device_address, c_address);
- return (jint) state;
+ return state;
}
static jint
@@ -658,38 +659,41 @@
{
const char *c_address = env->GetStringUTFChars(device_address, NULL);
const char *c_name = env->GetStringUTFChars(device_name, NULL);
- int status = check_AudioSystem_Command(AudioSystem::handleDeviceConfigChange(static_cast <audio_devices_t>(device),
- c_address, c_name, static_cast <audio_format_t>(codec)));
+ int status = check_AudioSystem_Command(
+ AudioSystem::handleDeviceConfigChange(static_cast<audio_devices_t>(device), c_address,
+ c_name, static_cast<audio_format_t>(codec)));
env->ReleaseStringUTFChars(device_address, c_address);
env->ReleaseStringUTFChars(device_name, c_name);
- return (jint) status;
+ return status;
}
static jint android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state,
jint uid) {
- return (jint)check_AudioSystem_Command(
- AudioSystem::setPhoneState((audio_mode_t)state, (uid_t)uid));
+ return check_AudioSystem_Command(
+ AudioSystem::setPhoneState(static_cast<audio_mode_t>(state), static_cast<uid_t>(uid)));
}
static jint
android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
{
- return (jint) check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
- static_cast <audio_policy_forced_cfg_t>(config)));
+ return check_AudioSystem_Command(
+ AudioSystem::setForceUse(static_cast<audio_policy_force_use_t>(usage),
+ static_cast<audio_policy_forced_cfg_t>(config)));
}
static jint
android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
{
- return static_cast <jint>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage)));
+ return static_cast<jint>(
+ AudioSystem::getForceUse(static_cast<audio_policy_force_use_t>(usage)));
}
static jint
android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
{
- return (jint) check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream),
- indexMin,
- indexMax));
+ return check_AudioSystem_Command(
+ AudioSystem::initStreamVolume(static_cast<audio_stream_type_t>(stream), indexMin,
+ indexMax));
}
static jint
@@ -699,10 +703,9 @@
jint index,
jint device)
{
- return (jint) check_AudioSystem_Command(
- AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
- index,
- (audio_devices_t)device));
+ return check_AudioSystem_Command(
+ AudioSystem::setStreamVolumeIndex(static_cast<audio_stream_type_t>(stream), index,
+ static_cast<audio_devices_t>(device)));
}
static jint
@@ -712,13 +715,11 @@
jint device)
{
int index;
- if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
- &index,
- (audio_devices_t)device)
- != NO_ERROR) {
+ if (AudioSystem::getStreamVolumeIndex(static_cast<audio_stream_type_t>(stream), &index,
+ static_cast<audio_devices_t>(device)) != NO_ERROR) {
index = -1;
}
- return (jint) index;
+ return index;
}
static jint
@@ -731,11 +732,12 @@
// read the AudioAttributes values
JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
- if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
return jStatus;
}
- return (jint) check_AudioSystem_Command(
- AudioSystem::setVolumeIndexForAttributes(*(paa.get()), index, (audio_devices_t)device));
+ return check_AudioSystem_Command(
+ AudioSystem::setVolumeIndexForAttributes(*(paa.get()), index,
+ static_cast<audio_devices_t>(device)));
}
static jint
@@ -747,15 +749,16 @@
// read the AudioAttributes values
JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
- if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
return jStatus;
}
int index;
- if (AudioSystem::getVolumeIndexForAttributes(*(paa.get()), index, (audio_devices_t)device)
- != NO_ERROR) {
+ if (AudioSystem::getVolumeIndexForAttributes(*(paa.get()), index,
+ static_cast<audio_devices_t>(device)) !=
+ NO_ERROR) {
index = -1;
}
- return (jint) index;
+ return index;
}
static jint
@@ -766,7 +769,7 @@
// read the AudioAttributes values
JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
- if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
return jStatus;
}
int index;
@@ -774,7 +777,7 @@
!= NO_ERROR) {
index = -1;
}
- return (jint) index;
+ return index;
}
static jint
@@ -785,7 +788,7 @@
// read the AudioAttributes values
JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
- if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
return jStatus;
}
int index;
@@ -793,13 +796,13 @@
!= NO_ERROR) {
index = -1;
}
- return (jint) index;
+ return index;
}
static jint
android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
{
- return (jint) check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
+ return check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
}
static jfloat
@@ -815,7 +818,7 @@
static jint
android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute)
{
- return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
+ return check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
}
static jboolean
@@ -831,7 +834,7 @@
static jint
android_media_AudioSystem_setMasterMono(JNIEnv *env, jobject thiz, jboolean mono)
{
- return (jint) check_AudioSystem_Command(AudioSystem::setMasterMono(mono));
+ return check_AudioSystem_Command(AudioSystem::setMasterMono(mono));
}
static jboolean
@@ -847,7 +850,7 @@
static jint
android_media_AudioSystem_setMasterBalance(JNIEnv *env, jobject thiz, jfloat balance)
{
- return (jint) check_AudioSystem_Command(AudioSystem::setMasterBalance(balance));
+ return check_AudioSystem_Command(AudioSystem::setMasterBalance(balance));
}
static jfloat
@@ -865,37 +868,37 @@
static jint
android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
{
- return (jint) AudioSystem::getPrimaryOutputSamplingRate();
+ return AudioSystem::getPrimaryOutputSamplingRate();
}
static jint
android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
{
- return (jint) AudioSystem::getPrimaryOutputFrameCount();
+ return AudioSystem::getPrimaryOutputFrameCount();
}
static jint
android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
{
uint32_t afLatency;
- if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
- != NO_ERROR) {
+ if (AudioSystem::getOutputLatency(&afLatency, static_cast<audio_stream_type_t>(stream)) !=
+ NO_ERROR) {
afLatency = -1;
}
- return (jint) afLatency;
+ return afLatency;
}
static jint
android_media_AudioSystem_setLowRamDevice(
JNIEnv *env, jobject clazz, jboolean isLowRamDevice, jlong totalMemory)
{
- return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice, (int64_t) totalMemory);
+ return AudioSystem::setLowRamDevice(isLowRamDevice, totalMemory);
}
static jint
android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
{
- return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
+ return check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
}
static void android_media_AudioSystem_setAudioFlingerBinder(JNIEnv *env, jobject clazz,
@@ -909,8 +912,8 @@
bool useInMask)
{
nAudioGainConfig->index = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mIndex);
- nAudioGainConfig->mode =
- (audio_gain_mode_t)env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
+ nAudioGainConfig->mode = static_cast<audio_gain_mode_t>(
+ env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode));
ALOGV("convertAudioGainConfigToNative got gain index %d", nAudioGainConfig->index);
jint jMask = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mChannelMask);
audio_channel_mask_t nMask;
@@ -924,8 +927,8 @@
nAudioGainConfig->channel_mask = nMask;
nAudioGainConfig->ramp_duration_ms = env->GetIntField(jAudioGainConfig,
gAudioGainConfigFields.mRampDurationMs);
- jintArray jValues = (jintArray)env->GetObjectField(jAudioGainConfig,
- gAudioGainConfigFields.mValues);
+ jintArray jValues = static_cast<jintArray>(
+ env->GetObjectField(jAudioGainConfig, gAudioGainConfigFields.mValues));
int *nValues = env->GetIntArrayElements(jValues, NULL);
size_t size = env->GetArrayLength(jValues);
memcpy(nAudioGainConfig->values, nValues, size * sizeof(int));
@@ -940,8 +943,8 @@
jobject jAudioPort = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mPort);
jobject jHandle = env->GetObjectField(jAudioPort, gAudioPortFields.mHandle);
nAudioPortConfig->id = env->GetIntField(jHandle, gAudioHandleFields.mId);
- nAudioPortConfig->role = (audio_port_role_t)env->GetIntField(jAudioPort,
- gAudioPortFields.mRole);
+ nAudioPortConfig->role =
+ static_cast<audio_port_role_t>(env->GetIntField(jAudioPort, gAudioPortFields.mRole));
if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
nAudioPortConfig->type = AUDIO_PORT_TYPE_DEVICE;
} else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
@@ -949,7 +952,7 @@
} else {
env->DeleteLocalRef(jAudioPort);
env->DeleteLocalRef(jHandle);
- return (jint)AUDIO_JAVA_ERROR;
+ return AUDIO_JAVA_ERROR;
}
ALOGV("convertAudioPortConfigToNative handle %d role %d type %d",
nAudioPortConfig->id, nAudioPortConfig->role, nAudioPortConfig->type);
@@ -1004,7 +1007,7 @@
}
env->DeleteLocalRef(jAudioPort);
env->DeleteLocalRef(jHandle);
- return (jint)AUDIO_JAVA_SUCCESS;
+ return AUDIO_JAVA_SUCCESS;
}
/**
@@ -1025,15 +1028,15 @@
}
// Supports AUDIO_PORT_TYPE_DEVICE only
if (nAudioPortConfig->type != AUDIO_PORT_TYPE_DEVICE) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
jobject jAudioDevicePort = env->GetObjectField(jAudioPortConfig,
gAudioPortConfigFields.mPort);
- nAudioPortConfig->ext.device.type =
- (audio_devices_t)env->GetIntField(jAudioDevicePort, gAudioPortFields.mType);
- jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioDevicePort,
- gAudioPortFields.mAddress);
+ nAudioPortConfig->ext.device.type = static_cast<audio_devices_t>(
+ env->GetIntField(jAudioDevicePort, gAudioPortFields.mType));
+ jstring jDeviceAddress =
+ static_cast<jstring>(env->GetObjectField(jAudioDevicePort, gAudioPortFields.mAddress));
const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
strncpy(nAudioPortConfig->ext.device.address,
nDeviceAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN - 1);
@@ -1043,45 +1046,41 @@
return jStatus;
}
-static jint convertAudioPortConfigFromNative(JNIEnv *env,
- jobject jAudioPort,
- jobject *jAudioPortConfig,
- const struct audio_port_config *nAudioPortConfig)
-{
- jint jStatus = AUDIO_JAVA_SUCCESS;
- jobject jAudioGainConfig = NULL;
- jobject jAudioGain = NULL;
+static jint convertAudioPortConfigFromNative(JNIEnv *env, ScopedLocalRef<jobject> *jAudioPort,
+ ScopedLocalRef<jobject> *jAudioPortConfig,
+ const struct audio_port_config *nAudioPortConfig) {
jintArray jGainValues;
bool audioportCreated = false;
ALOGV("convertAudioPortConfigFromNative jAudioPort %p", jAudioPort);
- if (jAudioPort == NULL) {
- jobject jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
- nAudioPortConfig->id);
+ if (*jAudioPort == nullptr) {
+ ScopedLocalRef<jobject> jHandle(env,
+ env->NewObject(gAudioHandleClass, gAudioHandleCstor,
+ nAudioPortConfig->id));
ALOGV("convertAudioPortConfigFromNative handle %d is a %s", nAudioPortConfig->id,
nAudioPortConfig->type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix");
if (jHandle == NULL) {
- return (jint)AUDIO_JAVA_ERROR;
+ return AUDIO_JAVA_ERROR;
}
// create placeholder port and port config objects with just the correct handle
// and configuration data. The actual AudioPortConfig objects will be
// constructed by java code with correct class type (device, mix etc...)
// and reference to AudioPort instance in this client
- jAudioPort = env->NewObject(gAudioPortClass, gAudioPortCstor,
- jHandle, // handle
- 0, // role
- NULL, // name
- NULL, // samplingRates
- NULL, // channelMasks
- NULL, // channelIndexMasks
- NULL, // formats
- NULL); // gains
- env->DeleteLocalRef(jHandle);
- if (jAudioPort == NULL) {
- return (jint)AUDIO_JAVA_ERROR;
+ jAudioPort->reset(env->NewObject(gAudioPortClass, gAudioPortCstor,
+ jHandle.get(), // handle
+ 0, // role
+ NULL, // name
+ NULL, // samplingRates
+ NULL, // channelMasks
+ NULL, // channelIndexMasks
+ NULL, // formats
+ NULL)); // gains
+
+ if (*jAudioPort == nullptr) {
+ return AUDIO_JAVA_ERROR;
}
ALOGV("convertAudioPortConfigFromNative jAudioPort created for handle %d",
nAudioPortConfig->id);
@@ -1089,6 +1088,9 @@
audioportCreated = true;
}
+ ScopedLocalRef<jobject> jAudioGainConfig(env, nullptr);
+ ScopedLocalRef<jobject> jAudioGain(env, nullptr);
+
bool useInMask = audio_port_config_has_input_direction(nAudioPortConfig);
audio_channel_mask_t nMask;
@@ -1102,36 +1104,26 @@
gainIndex, nAudioPortConfig->gain.mode);
if (audioportCreated) {
ALOGV("convertAudioPortConfigFromNative creating gain");
- jAudioGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
- gainIndex,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0);
+ jAudioGain.reset(env->NewObject(gAudioGainClass, gAudioGainCstor, gainIndex, 0, 0, 0, 0,
+ 0, 0, 0, 0));
if (jAudioGain == NULL) {
ALOGV("convertAudioPortConfigFromNative creating gain FAILED");
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ return AUDIO_JAVA_ERROR;
}
} else {
ALOGV("convertAudioPortConfigFromNative reading gain from port");
- jobjectArray jGains = (jobjectArray)env->GetObjectField(jAudioPort,
- gAudioPortFields.mGains);
+ ScopedLocalRef<jobjectArray>
+ jGains(env,
+ static_cast<jobjectArray>(env->GetObjectField(jAudioPort->get(),
+ gAudioPortFields.mGains)));
if (jGains == NULL) {
ALOGV("convertAudioPortConfigFromNative could not get gains from port");
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ return AUDIO_JAVA_ERROR;
}
- jAudioGain = env->GetObjectArrayElement(jGains, gainIndex);
- env->DeleteLocalRef(jGains);
+ jAudioGain.reset(env->GetObjectArrayElement(jGains.get(), gainIndex));
if (jAudioGain == NULL) {
ALOGV("convertAudioPortConfigFromNative could not get gain at index %d", gainIndex);
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ return AUDIO_JAVA_ERROR;
}
}
int numValues;
@@ -1143,8 +1135,7 @@
jGainValues = env->NewIntArray(numValues);
if (jGainValues == NULL) {
ALOGV("convertAudioPortConfigFromNative could not create gain values %d", numValues);
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ return AUDIO_JAVA_ERROR;
}
env->SetIntArrayRegion(jGainValues, 0, numValues,
nAudioPortConfig->gain.values);
@@ -1158,19 +1149,14 @@
ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
}
- jAudioGainConfig = env->NewObject(gAudioGainConfigClass,
- gAudioGainConfigCstor,
- gainIndex,
- jAudioGain,
- nAudioPortConfig->gain.mode,
- jMask,
- jGainValues,
- nAudioPortConfig->gain.ramp_duration_ms);
+ jAudioGainConfig.reset(env->NewObject(gAudioGainConfigClass, gAudioGainConfigCstor,
+ gainIndex, jAudioGain.get(),
+ nAudioPortConfig->gain.mode, jMask, jGainValues,
+ nAudioPortConfig->gain.ramp_duration_ms));
env->DeleteLocalRef(jGainValues);
if (jAudioGainConfig == NULL) {
ALOGV("convertAudioPortConfigFromNative could not create gain config");
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ return AUDIO_JAVA_ERROR;
}
}
jclass clazz;
@@ -1180,17 +1166,16 @@
methodID = gAudioPortConfigCstor;
ALOGV("convertAudioPortConfigFromNative building a generic port config");
} else {
- if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
+ if (env->IsInstanceOf(jAudioPort->get(), gAudioDevicePortClass)) {
clazz = gAudioDevicePortConfigClass;
methodID = gAudioDevicePortConfigCstor;
ALOGV("convertAudioPortConfigFromNative building a device config");
- } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
+ } else if (env->IsInstanceOf(jAudioPort->get(), gAudioMixPortClass)) {
clazz = gAudioMixPortConfigClass;
methodID = gAudioMixPortConfigCstor;
ALOGV("convertAudioPortConfigFromNative building a mix config");
} else {
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ return AUDIO_JAVA_ERROR;
}
}
nMask = (nAudioPortConfig->config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK)
@@ -1204,8 +1189,8 @@
ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
}
- *jAudioPortConfig =
- env->NewObject(clazz, methodID, jAudioPort,
+ jAudioPortConfig->reset(
+ env->NewObject(clazz, methodID, jAudioPort->get(),
(nAudioPortConfig->config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE)
? nAudioPortConfig->sample_rate
: AUDIO_CONFIG_BASE_INITIALIZER.sample_rate,
@@ -1214,31 +1199,14 @@
(nAudioPortConfig->config_mask & AUDIO_PORT_CONFIG_FORMAT)
? nAudioPortConfig->format
: AUDIO_CONFIG_BASE_INITIALIZER.format),
- jAudioGainConfig);
+ jAudioGainConfig.get()));
if (*jAudioPortConfig == NULL) {
ALOGV("convertAudioPortConfigFromNative could not create new port config");
- jStatus = (jint)AUDIO_JAVA_ERROR;
+ return AUDIO_JAVA_ERROR;
} else {
ALOGV("convertAudioPortConfigFromNative OK");
}
-
-exit:
- if (audioportCreated) {
- env->DeleteLocalRef(jAudioPort);
- if (jAudioGain != NULL) {
- env->DeleteLocalRef(jAudioGain);
- }
- }
- if (jAudioGainConfig != NULL) {
- env->DeleteLocalRef(jAudioGainConfig);
- }
- return jStatus;
-}
-
-// TODO: pull out to separate file
-template <typename T, size_t N>
-static constexpr size_t array_size(const T (&)[N]) {
- return N;
+ return AUDIO_JAVA_SUCCESS;
}
static jintArray convertEncapsulationInfoFromNative(JNIEnv *env, uint32_t encapsulationInfo) {
@@ -1252,7 +1220,8 @@
}
}
jintArray result = env->NewIntArray(encapsulation.size());
- env->SetIntArrayRegion(result, 0, encapsulation.size(), (jint *)encapsulation.data());
+ env->SetIntArrayRegion(result, 0, encapsulation.size(),
+ reinterpret_cast<jint *>(encapsulation.data()));
return result;
}
@@ -1260,8 +1229,8 @@
std::stringstream &ss) {
ss << " num_audio_profiles " << nAudioPort->num_audio_profiles << " num_gains "
<< nAudioPort->num_gains;
- if (nAudioPort->num_audio_profiles > array_size(nAudioPort->audio_profiles) ||
- nAudioPort->num_gains > array_size(nAudioPort->gains)) {
+ if (nAudioPort->num_audio_profiles > std::size(nAudioPort->audio_profiles) ||
+ nAudioPort->num_gains > std::size(nAudioPort->gains)) {
return true;
}
for (size_t i = 0; i < nAudioPort->num_audio_profiles; ++i) {
@@ -1269,9 +1238,9 @@
<< " num_sample_rates " << nAudioPort->audio_profiles[i].num_sample_rates
<< " num_channel_masks " << nAudioPort->audio_profiles[i].num_channel_masks;
if (nAudioPort->audio_profiles[i].num_sample_rates >
- array_size(nAudioPort->audio_profiles[i].sample_rates) ||
+ std::size(nAudioPort->audio_profiles[i].sample_rates) ||
nAudioPort->audio_profiles[i].num_channel_masks >
- array_size(nAudioPort->audio_profiles[i].channel_masks)) {
+ std::size(nAudioPort->audio_profiles[i].channel_masks)) {
return true;
}
}
@@ -1309,7 +1278,8 @@
if (nAudioProfile->num_sample_rates) {
env->SetIntArrayRegion(jSamplingRates.get(), 0 /*start*/, nAudioProfile->num_sample_rates,
- (jint *)nAudioProfile->sample_rates);
+ const_cast<jint *>(reinterpret_cast<const jint *>(
+ nAudioProfile->sample_rates)));
}
// put the masks in the output arrays
@@ -1342,18 +1312,8 @@
return AUDIO_JAVA_SUCCESS;
}
-static jint convertAudioPortFromNative(JNIEnv *env, jobject *jAudioPort,
+static jint convertAudioPortFromNative(JNIEnv *env, ScopedLocalRef<jobject> *jAudioPort,
const struct audio_port_v7 *nAudioPort) {
- jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
- jintArray jEncapsulationModes = NULL;
- jintArray jEncapsulationMetadataTypes = NULL;
- jobjectArray jGains = NULL;
- jobject jHandle = NULL;
- jobject jAudioPortConfig = NULL;
- jstring jDeviceName = NULL;
- jobject jAudioProfiles = NULL;
- jobject jAudioDescriptors = nullptr;
- ScopedLocalRef<jobject> jPcmFloatProfileFromExtendedInteger(env, nullptr);
bool hasFloat = false;
bool useInMask;
@@ -1377,19 +1337,21 @@
} else {
ALOGE("%s", s.c_str());
}
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ return AUDIO_JAVA_ERROR;
}
useInMask = audio_has_input_direction(nAudioPort->type, nAudioPort->role);
- jAudioProfiles = env->NewObject(gArrayListClass, gArrayListMethods.cstor);
+ ScopedLocalRef<jobject> jAudioProfiles(env,
+ env->NewObject(gArrayListClass,
+ gArrayListMethods.cstor));
if (jAudioProfiles == nullptr) {
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ return AUDIO_JAVA_ERROR;
}
+ ScopedLocalRef<jobject> jPcmFloatProfileFromExtendedInteger(env, nullptr);
for (size_t i = 0; i < nAudioPort->num_audio_profiles; ++i) {
jobject jAudioProfile = nullptr;
+ jint jStatus = AUDIO_JAVA_SUCCESS;
jStatus = convertAudioProfileFromNative(env, &jAudioProfile, &nAudioPort->audio_profiles[i],
useInMask);
if (jStatus == AUDIO_JAVA_BAD_VALUE) {
@@ -1397,10 +1359,9 @@
continue;
}
if (jStatus != NO_ERROR) {
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ return AUDIO_JAVA_ERROR;
}
- env->CallBooleanMethod(jAudioProfiles, gArrayListMethods.add, jAudioProfile);
+ env->CallBooleanMethod(jAudioProfiles.get(), gArrayListMethods.add, jAudioProfile);
if (nAudioPort->audio_profiles[i].format == AUDIO_FORMAT_PCM_FLOAT) {
hasFloat = true;
@@ -1409,19 +1370,21 @@
audio_bytes_per_sample(nAudioPort->audio_profiles[i].format) > 2) {
ScopedLocalRef<jintArray>
jSamplingRates(env,
- (jintArray)
+ static_cast<jintArray>(
env->GetObjectField(jAudioProfile,
- gAudioProfileFields.mSamplingRates));
+ gAudioProfileFields
+ .mSamplingRates)));
ScopedLocalRef<jintArray>
jChannelMasks(env,
- (jintArray)
+ static_cast<jintArray>(
env->GetObjectField(jAudioProfile,
- gAudioProfileFields.mChannelMasks));
+ gAudioProfileFields.mChannelMasks)));
ScopedLocalRef<jintArray>
jChannelIndexMasks(env,
- (jintArray)env->GetObjectField(jAudioProfile,
- gAudioProfileFields
- .mChannelIndexMasks));
+ static_cast<jintArray>(
+ env->GetObjectField(jAudioProfile,
+ gAudioProfileFields
+ .mChannelIndexMasks)));
int encapsulationType =
env->GetIntField(jAudioProfile, gAudioProfileFields.mEncapsulationType);
@@ -1441,14 +1404,15 @@
// (replacing the zero pad). This ensures pre-S apps that look
// for ENCODING_PCM_FLOAT continue to see that encoding if the device supports
// extended precision integers.
- env->CallBooleanMethod(jAudioProfiles, gArrayListMethods.add,
+ env->CallBooleanMethod(jAudioProfiles.get(), gArrayListMethods.add,
jPcmFloatProfileFromExtendedInteger.get());
}
- jAudioDescriptors = env->NewObject(gArrayListClass, gArrayListMethods.cstor);
+ ScopedLocalRef<jobject> jAudioDescriptors(env,
+ env->NewObject(gArrayListClass,
+ gArrayListMethods.cstor));
if (jAudioDescriptors == nullptr) {
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ return AUDIO_JAVA_ERROR;
}
for (size_t i = 0; i < nAudioPort->num_extra_audio_descriptors; ++i) {
const auto &extraAudioDescriptor = nAudioPort->extra_audio_descriptors[i];
@@ -1478,15 +1442,16 @@
env->NewObject(gAudioDescriptorClass, gAudioDescriptorCstor,
standard, encapsulationType,
jDescriptor.get()));
- env->CallBooleanMethod(jAudioDescriptors, gArrayListMethods.add, jAudioDescriptor.get());
+ env->CallBooleanMethod(jAudioDescriptors.get(), gArrayListMethods.add,
+ jAudioDescriptor.get());
}
// gains
- jGains = env->NewObjectArray(nAudioPort->num_gains,
- gAudioGainClass, NULL);
- if (jGains == NULL) {
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ ScopedLocalRef<jobjectArray> jGains(env,
+ env->NewObjectArray(nAudioPort->num_gains, gAudioGainClass,
+ NULL));
+ if (jGains == nullptr) {
+ return AUDIO_JAVA_ERROR;
}
for (size_t j = 0; j < nAudioPort->num_gains; j++) {
@@ -1511,88 +1476,71 @@
nAudioPort->gains[j].min_ramp_ms,
nAudioPort->gains[j].max_ramp_ms);
if (jGain == NULL) {
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ return AUDIO_JAVA_ERROR;
}
- env->SetObjectArrayElement(jGains, j, jGain);
+ env->SetObjectArrayElement(jGains.get(), j, jGain);
env->DeleteLocalRef(jGain);
}
- jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
- nAudioPort->id);
- if (jHandle == NULL) {
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ ScopedLocalRef<jobject> jHandle(env,
+ env->NewObject(gAudioHandleClass, gAudioHandleCstor,
+ nAudioPort->id));
+ if (jHandle == nullptr) {
+ return AUDIO_JAVA_ERROR;
}
- jDeviceName = env->NewStringUTF(nAudioPort->name);
-
+ ScopedLocalRef<jstring> jDeviceName(env, env->NewStringUTF(nAudioPort->name));
if (nAudioPort->type == AUDIO_PORT_TYPE_DEVICE) {
- ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
- jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
- jEncapsulationModes =
- convertEncapsulationInfoFromNative(env, nAudioPort->ext.device.encapsulation_modes);
- jEncapsulationMetadataTypes =
+ ScopedLocalRef<jintArray> jEncapsulationModes(
+ env,
+ convertEncapsulationInfoFromNative(env,
+ nAudioPort->ext.device.encapsulation_modes));
+ ScopedLocalRef<jintArray> jEncapsulationMetadataTypes(
+ env,
convertEncapsulationInfoFromNative(env,
nAudioPort->ext.device
- .encapsulation_metadata_types);
- *jAudioPort =
- env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor, jHandle, jDeviceName,
- jAudioProfiles, jGains, nAudioPort->ext.device.type, jAddress,
- jEncapsulationModes, jEncapsulationMetadataTypes, jAudioDescriptors);
+ .encapsulation_metadata_types));
+ ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
+ jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
+ jAudioPort->reset(
+ env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor, jHandle.get(),
+ jDeviceName.get(), jAudioProfiles.get(), jGains.get(),
+ nAudioPort->ext.device.type, jAddress, jEncapsulationModes.get(),
+ jEncapsulationMetadataTypes.get(), jAudioDescriptors.get()));
env->DeleteLocalRef(jAddress);
} else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
ALOGV("convertAudioPortFromNative is a mix");
- *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor, jHandle,
- nAudioPort->ext.mix.handle, nAudioPort->role, jDeviceName,
- jAudioProfiles, jGains);
+ jAudioPort->reset(env->NewObject(gAudioMixPortClass, gAudioMixPortCstor, jHandle.get(),
+ nAudioPort->ext.mix.handle, nAudioPort->role,
+ jDeviceName.get(), jAudioProfiles.get(), jGains.get()));
} else {
ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ return AUDIO_JAVA_ERROR;
}
if (*jAudioPort == NULL) {
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ return AUDIO_JAVA_ERROR;
}
- jStatus = convertAudioPortConfigFromNative(env,
- *jAudioPort,
- &jAudioPortConfig,
+ ScopedLocalRef<jobject> jAudioPortConfig(env, nullptr);
+
+ if (int jStatus = convertAudioPortConfigFromNative(env, jAudioPort, &jAudioPortConfig,
&nAudioPort->active_config);
- if (jStatus != AUDIO_JAVA_SUCCESS) {
- goto exit;
+ jStatus != AUDIO_JAVA_SUCCESS) {
+ return jStatus;
}
- env->SetObjectField(*jAudioPort, gAudioPortFields.mActiveConfig, jAudioPortConfig);
+ env->SetObjectField(jAudioPort->get(), gAudioPortFields.mActiveConfig, jAudioPortConfig.get());
+ return AUDIO_JAVA_SUCCESS;
+}
-exit:
- if (jDeviceName != NULL) {
- env->DeleteLocalRef(jDeviceName);
+static bool setGeneration(JNIEnv *env, jintArray jGeneration, unsigned int generation1) {
+ ScopedIntArrayRW nGeneration(env, jGeneration);
+ if (nGeneration.get() == nullptr) {
+ return false;
+ } else {
+ nGeneration[0] = generation1;
+ return true;
}
- if (jEncapsulationModes != NULL) {
- env->DeleteLocalRef(jEncapsulationModes);
- }
- if (jEncapsulationMetadataTypes != NULL) {
- env->DeleteLocalRef(jEncapsulationMetadataTypes);
- }
- if (jAudioProfiles != NULL) {
- env->DeleteLocalRef(jAudioProfiles);
- }
- if (jGains != NULL) {
- env->DeleteLocalRef(jGains);
- }
- if (jHandle != NULL) {
- env->DeleteLocalRef(jHandle);
- }
- if (jAudioPortConfig != NULL) {
- env->DeleteLocalRef(jAudioPortConfig);
- }
- if (jAudioDescriptors != nullptr) {
- env->DeleteLocalRef(jAudioDescriptors);
- }
-
- return jStatus;
}
static jint
@@ -1603,23 +1551,22 @@
if (jPorts == NULL) {
ALOGE("listAudioPorts NULL AudioPort ArrayList");
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
if (!env->IsInstanceOf(jPorts, gArrayListClass)) {
ALOGE("listAudioPorts not an arraylist");
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
status_t status;
unsigned int generation1;
unsigned int generation;
unsigned int numPorts;
- jint *nGeneration;
- struct audio_port_v7 *nPorts = nullptr;
+ std::vector<audio_port_v7> nPorts;
int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
jint jStatus;
@@ -1638,43 +1585,39 @@
break;
}
if (numPorts == 0) {
- jStatus = (jint)AUDIO_JAVA_SUCCESS;
- goto exit;
+ return setGeneration(env, jGeneration, generation1) ? AUDIO_JAVA_SUCCESS
+ : AUDIO_JAVA_ERROR;
}
- nPorts = (struct audio_port_v7 *)realloc(nPorts, numPorts * sizeof(struct audio_port_v7));
+ nPorts.resize(numPorts);
status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_NONE, &numPorts,
- nPorts, &generation);
+ &nPorts[0], &generation);
ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d",
numPorts, generation, generation1);
} while (generation1 != generation && status == NO_ERROR);
jStatus = nativeToJavaStatus(status);
if (jStatus != AUDIO_JAVA_SUCCESS) {
- goto exit;
+ if (!setGeneration(env, jGeneration, generation1)) {
+ jStatus = AUDIO_JAVA_ERROR;
+ }
+ return jStatus;
}
for (size_t i = 0; i < numPorts; i++) {
- jobject jAudioPort = NULL;
+ ScopedLocalRef<jobject> jAudioPort(env, nullptr);
jStatus = convertAudioPortFromNative(env, &jAudioPort, &nPorts[i]);
if (jStatus != AUDIO_JAVA_SUCCESS) {
- goto exit;
+ if (!setGeneration(env, jGeneration, generation1)) {
+ jStatus = AUDIO_JAVA_ERROR;
+ }
+ return jStatus;
}
- env->CallBooleanMethod(jPorts, gArrayListMethods.add, jAudioPort);
- if (jAudioPort != NULL) {
- env->DeleteLocalRef(jAudioPort);
- }
+ env->CallBooleanMethod(jPorts, gArrayListMethods.add, jAudioPort.get());
}
-
-exit:
- nGeneration = env->GetIntArrayElements(jGeneration, NULL);
- if (nGeneration == NULL) {
- jStatus = (jint)AUDIO_JAVA_ERROR;
- } else {
- nGeneration[0] = generation1;
- env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
+ if (!setGeneration(env, jGeneration, generation1)) {
+ jStatus = AUDIO_JAVA_ERROR;
}
- free(nPorts);
return jStatus;
}
@@ -1687,64 +1630,56 @@
ALOGV("createAudioPatch");
if (jPatches == NULL || jSources == NULL || jSinks == NULL) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
if (env->GetArrayLength(jPatches) != 1) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
jint numSources = env->GetArrayLength(jSources);
if (numSources == 0 || numSources > AUDIO_PATCH_PORTS_MAX) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
jint numSinks = env->GetArrayLength(jSinks);
if (numSinks == 0 || numSinks > AUDIO_PATCH_PORTS_MAX) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
- audio_patch_handle_t handle = (audio_patch_handle_t)0;
- jobject jPatch = env->GetObjectArrayElement(jPatches, 0);
- jobject jPatchHandle = NULL;
+ audio_patch_handle_t handle = static_cast<audio_patch_handle_t>(AUDIO_PATCH_HANDLE_NONE);
+ ScopedLocalRef<jobject> jPatch(env, env->GetObjectArrayElement(jPatches, 0));
+ ScopedLocalRef<jobject> jPatchHandle(env, nullptr);
if (jPatch != NULL) {
- if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ if (!env->IsInstanceOf(jPatch.get(), gAudioPatchClass)) {
+ return AUDIO_JAVA_BAD_VALUE;
}
- jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
- handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
+ jPatchHandle.reset(env->GetObjectField(jPatch.get(), gAudioPatchFields.mHandle));
+ handle = static_cast<audio_patch_handle_t>(
+ env->GetIntField(jPatchHandle.get(), gAudioHandleFields.mId));
}
struct audio_patch nPatch = { .id = handle };
- jobject jSource = NULL;
- jobject jSink = NULL;
-
for (jint i = 0; i < numSources; i++) {
- jSource = env->GetObjectArrayElement(jSources, i);
- if (!env->IsInstanceOf(jSource, gAudioPortConfigClass)) {
- jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
- goto exit;
+ ScopedLocalRef<jobject> jSource(env, env->GetObjectArrayElement(jSources, i));
+ if (!env->IsInstanceOf(jSource.get(), gAudioPortConfigClass)) {
+ return AUDIO_JAVA_BAD_VALUE;
}
- jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource, false);
- env->DeleteLocalRef(jSource);
- jSource = NULL;
+ jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource.get(), false);
if (jStatus != AUDIO_JAVA_SUCCESS) {
- goto exit;
+ return jStatus;
}
nPatch.num_sources++;
}
for (jint i = 0; i < numSinks; i++) {
- jSink = env->GetObjectArrayElement(jSinks, i);
- if (!env->IsInstanceOf(jSink, gAudioPortConfigClass)) {
- jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
- goto exit;
+ ScopedLocalRef<jobject> jSink(env, env->GetObjectArrayElement(jSinks, i));
+ if (!env->IsInstanceOf(jSink.get(), gAudioPortConfigClass)) {
+ return AUDIO_JAVA_BAD_VALUE;
}
- jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink, false);
- env->DeleteLocalRef(jSink);
- jSink = NULL;
+ jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink.get(), false);
if (jStatus != AUDIO_JAVA_SUCCESS) {
- goto exit;
+ return jStatus;
}
nPatch.num_sinks++;
}
@@ -1755,38 +1690,22 @@
jStatus = nativeToJavaStatus(status);
if (jStatus != AUDIO_JAVA_SUCCESS) {
- goto exit;
+ return jStatus;
}
- if (jPatchHandle == NULL) {
- jPatchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
- handle);
- if (jPatchHandle == NULL) {
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ if (jPatchHandle == nullptr) {
+ jPatchHandle.reset(env->NewObject(gAudioHandleClass, gAudioHandleCstor, handle));
+ if (jPatchHandle == nullptr) {
+ return AUDIO_JAVA_ERROR;
}
- jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor, jPatchHandle, jSources, jSinks);
- if (jPatch == NULL) {
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
+ jPatch.reset(env->NewObject(gAudioPatchClass, gAudioPatchCstor, jPatchHandle.get(),
+ jSources, jSinks));
+ if (jPatch == nullptr) {
+ return AUDIO_JAVA_ERROR;
}
- env->SetObjectArrayElement(jPatches, 0, jPatch);
+ env->SetObjectArrayElement(jPatches, 0, jPatch.get());
} else {
- env->SetIntField(jPatchHandle, gAudioHandleFields.mId, handle);
- }
-
-exit:
- if (jPatchHandle != NULL) {
- env->DeleteLocalRef(jPatchHandle);
- }
- if (jPatch != NULL) {
- env->DeleteLocalRef(jPatch);
- }
- if (jSource != NULL) {
- env->DeleteLocalRef(jSource);
- }
- if (jSink != NULL) {
- env->DeleteLocalRef(jSink);
+ env->SetIntField(jPatchHandle.get(), gAudioHandleFields.mId, handle);
}
return jStatus;
}
@@ -1797,16 +1716,17 @@
{
ALOGV("releaseAudioPatch");
if (jPatch == NULL) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
- audio_patch_handle_t handle = (audio_patch_handle_t)0;
+ audio_patch_handle_t handle = static_cast<audio_patch_handle_t>(AUDIO_PATCH_HANDLE_NONE);
jobject jPatchHandle = NULL;
if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
- handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
+ handle = static_cast<audio_patch_handle_t>(
+ env->GetIntField(jPatchHandle, gAudioHandleFields.mId));
env->DeleteLocalRef(jPatchHandle);
ALOGV("AudioSystem::releaseAudioPatch");
@@ -1823,28 +1743,22 @@
ALOGV("listAudioPatches");
if (jPatches == NULL) {
ALOGE("listAudioPatches NULL AudioPatch ArrayList");
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
if (!env->IsInstanceOf(jPatches, gArrayListClass)) {
ALOGE("listAudioPatches not an arraylist");
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
status_t status;
unsigned int generation1;
unsigned int generation;
unsigned int numPatches;
- jint *nGeneration;
- struct audio_patch *nPatches = NULL;
- jobjectArray jSources = NULL;
- jobject jSource = NULL;
- jobjectArray jSinks = NULL;
- jobject jSink = NULL;
- jobject jPatch = NULL;
+ std::vector<audio_patch> nPatches;
int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
jint jStatus;
@@ -1865,15 +1779,13 @@
break;
}
if (numPatches == 0) {
- jStatus = (jint)AUDIO_JAVA_SUCCESS;
- goto exit;
+ return setGeneration(env, jGeneration, generation1) ? AUDIO_JAVA_SUCCESS
+ : AUDIO_JAVA_ERROR;
}
- nPatches = (struct audio_patch *)realloc(nPatches, numPatches * sizeof(struct audio_patch));
+ nPatches.resize(numPatches);
- status = AudioSystem::listAudioPatches(&numPatches,
- nPatches,
- &generation);
+ status = AudioSystem::listAudioPatches(&numPatches, &nPatches[0], &generation);
ALOGV("listAudioPatches AudioSystem::listAudioPatches numPatches %d generation %d generation1 %d",
numPatches, generation, generation1);
@@ -1881,15 +1793,21 @@
jStatus = nativeToJavaStatus(status);
if (jStatus != AUDIO_JAVA_SUCCESS) {
- goto exit;
+ if (!setGeneration(env, jGeneration, generation1)) {
+ jStatus = AUDIO_JAVA_ERROR;
+ }
+ return jStatus;
}
for (size_t i = 0; i < numPatches; i++) {
+ ScopedLocalRef<jobject> jPatch(env, nullptr);
+ ScopedLocalRef<jobjectArray> jSources(env, nullptr);
+ ScopedLocalRef<jobjectArray> jSinks(env, nullptr);
jobject patchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
nPatches[i].id);
if (patchHandle == NULL) {
- jStatus = AUDIO_JAVA_ERROR;
- goto exit;
+ setGeneration(env, jGeneration, generation1);
+ return AUDIO_JAVA_ERROR;
}
ALOGV("listAudioPatches patch %zu num_sources %d num_sinks %d",
i, nPatches[i].num_sources, nPatches[i].num_sinks);
@@ -1897,96 +1815,67 @@
env->SetIntField(patchHandle, gAudioHandleFields.mId, nPatches[i].id);
// load sources
- jSources = env->NewObjectArray(nPatches[i].num_sources,
- gAudioPortConfigClass, NULL);
- if (jSources == NULL) {
- jStatus = AUDIO_JAVA_ERROR;
- goto exit;
+ jSources.reset(env->NewObjectArray(nPatches[i].num_sources, gAudioPortConfigClass, NULL));
+ if (jSources == nullptr) {
+ setGeneration(env, jGeneration, generation1);
+ return AUDIO_JAVA_ERROR;
}
for (size_t j = 0; j < nPatches[i].num_sources; j++) {
- jStatus = convertAudioPortConfigFromNative(env,
- NULL,
- &jSource,
- &nPatches[i].sources[j]);
+ ScopedLocalRef<jobject> jSource(env, nullptr);
+ ScopedLocalRef<jobject> jAudioPort(env, nullptr);
+ jStatus = convertAudioPortConfigFromNative(env, &jAudioPort, &jSource,
+ &nPatches[i].sources[j]);
if (jStatus != AUDIO_JAVA_SUCCESS) {
- goto exit;
+ if (!setGeneration(env, jGeneration, generation1)) {
+ jStatus = AUDIO_JAVA_ERROR;
+ }
+ return jStatus;
}
- env->SetObjectArrayElement(jSources, j, jSource);
- env->DeleteLocalRef(jSource);
- jSource = NULL;
+ env->SetObjectArrayElement(jSources.get(), j, jSource.get());
ALOGV("listAudioPatches patch %zu source %zu is a %s handle %d",
i, j,
nPatches[i].sources[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
nPatches[i].sources[j].id);
}
// load sinks
- jSinks = env->NewObjectArray(nPatches[i].num_sinks,
- gAudioPortConfigClass, NULL);
- if (jSinks == NULL) {
- jStatus = AUDIO_JAVA_ERROR;
- goto exit;
+ jSinks.reset(env->NewObjectArray(nPatches[i].num_sinks, gAudioPortConfigClass, NULL));
+ if (jSinks == nullptr) {
+ setGeneration(env, jGeneration, generation1);
+ return AUDIO_JAVA_ERROR;
}
for (size_t j = 0; j < nPatches[i].num_sinks; j++) {
- jStatus = convertAudioPortConfigFromNative(env,
- NULL,
- &jSink,
- &nPatches[i].sinks[j]);
+ ScopedLocalRef<jobject> jSink(env, nullptr);
+ ScopedLocalRef<jobject> jAudioPort(env, nullptr);
+ jStatus = convertAudioPortConfigFromNative(env, &jAudioPort, &jSink,
+ &nPatches[i].sinks[j]);
if (jStatus != AUDIO_JAVA_SUCCESS) {
- goto exit;
+ if (!setGeneration(env, jGeneration, generation1)) {
+ jStatus = AUDIO_JAVA_ERROR;
+ }
+ return jStatus;
}
- env->SetObjectArrayElement(jSinks, j, jSink);
- env->DeleteLocalRef(jSink);
- jSink = NULL;
+ env->SetObjectArrayElement(jSinks.get(), j, jSink.get());
ALOGV("listAudioPatches patch %zu sink %zu is a %s handle %d",
i, j,
nPatches[i].sinks[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
nPatches[i].sinks[j].id);
}
- jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor,
- patchHandle, jSources, jSinks);
- env->DeleteLocalRef(jSources);
- jSources = NULL;
- env->DeleteLocalRef(jSinks);
- jSinks = NULL;
- if (jPatch == NULL) {
+ jPatch.reset(env->NewObject(gAudioPatchClass, gAudioPatchCstor, patchHandle, jSources.get(),
+ jSinks.get()));
+ if (jPatch == nullptr) {
jStatus = AUDIO_JAVA_ERROR;
- goto exit;
+ setGeneration(env, jGeneration, generation1);
+ return AUDIO_JAVA_ERROR;
}
- env->CallBooleanMethod(jPatches, gArrayListMethods.add, jPatch);
- env->DeleteLocalRef(jPatch);
- jPatch = NULL;
+ env->CallBooleanMethod(jPatches, gArrayListMethods.add, jPatch.get());
}
-
-exit:
-
- nGeneration = env->GetIntArrayElements(jGeneration, NULL);
- if (nGeneration == NULL) {
+ if (!setGeneration(env, jGeneration, generation1)) {
jStatus = AUDIO_JAVA_ERROR;
- } else {
- nGeneration[0] = generation1;
- env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
}
-
- if (jSources != NULL) {
- env->DeleteLocalRef(jSources);
- }
- if (jSource != NULL) {
- env->DeleteLocalRef(jSource);
- }
- if (jSinks != NULL) {
- env->DeleteLocalRef(jSinks);
- }
- if (jSink != NULL) {
- env->DeleteLocalRef(jSink);
- }
- if (jPatch != NULL) {
- env->DeleteLocalRef(jPatch);
- }
- free(nPatches);
return jStatus;
}
@@ -2035,7 +1924,7 @@
}
auto paa = JNIAudioAttributeHelper::makeUnique();
jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jAudioAttributes, paa.get());
- if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
return jStatus;
}
audio_port_handle_t handle;
@@ -2052,8 +1941,7 @@
android_media_AudioSystem_stopAudioSource(JNIEnv *env, jobject clazz, jint handle)
{
ALOGV("stopAudioSource");
- status_t status = AudioSystem::stopAudioSource(
- static_cast <audio_port_handle_t>(handle));
+ status_t status = AudioSystem::stopAudioSource(static_cast<audio_port_handle_t>(handle));
ALOGV("AudioSystem::stopAudioSource() returned %d", status);
return nativeToJavaStatus(status);
}
@@ -2085,7 +1973,7 @@
static jint
android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId)
{
- return (jint) AudioSystem::getAudioHwSyncForSession((audio_session_t) sessionId);
+ return AudioSystem::getAudioHwSyncForSession(static_cast<audio_session_t>(sessionId));
}
static void
@@ -2204,11 +2092,11 @@
{
nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
- nAudioMix->mDeviceType = (audio_devices_t)
- env->GetIntField(jAudioMix, gAudioMixFields.mDeviceType);
+ nAudioMix->mDeviceType =
+ static_cast<audio_devices_t>(env->GetIntField(jAudioMix, gAudioMixFields.mDeviceType));
- jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioMix,
- gAudioMixFields.mDeviceAddress);
+ jstring jDeviceAddress =
+ static_cast<jstring>(env->GetObjectField(jAudioMix, gAudioMixFields.mDeviceAddress));
const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
nAudioMix->mDeviceAddress = String8(nDeviceAddress);
env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
@@ -2227,8 +2115,8 @@
nAudioMix->mVoiceCommunicationCaptureAllowed =
env->GetBooleanField(jRule, gAudioMixingRuleFields.mVoiceCommunicationCaptureAllowed);
env->DeleteLocalRef(jRule);
- jobjectArray jCriteria = (jobjectArray)env->CallObjectMethod(jRuleCriteria,
- gArrayListMethods.toArray);
+ jobjectArray jCriteria = static_cast<jobjectArray>(
+ env->CallObjectMethod(jRuleCriteria, gArrayListMethods.toArray));
env->DeleteLocalRef(jRuleCriteria);
jint numCriteria = env->GetArrayLength(jCriteria);
@@ -2264,8 +2152,8 @@
auto paa = JNIAudioAttributeHelper::makeUnique();
jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jAttributes, paa.get());
- if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
- return jStatus;
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
+ return jStatus;
}
if (match_rule == RULE_MATCH_ATTRIBUTE_USAGE) {
nCriterion.mValue.mUsage = paa->usage;
@@ -2283,7 +2171,7 @@
env->DeleteLocalRef(jCriteria);
- return (jint)AUDIO_JAVA_SUCCESS;
+ return AUDIO_JAVA_SUCCESS;
}
static jint
@@ -2293,34 +2181,29 @@
ALOGV("registerPolicyMixes");
if (jMixesList == NULL) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
if (!env->IsInstanceOf(jMixesList, gArrayListClass)) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
- jobjectArray jMixes = (jobjectArray)env->CallObjectMethod(jMixesList,
- gArrayListMethods.toArray);
+ jobjectArray jMixes =
+ static_cast<jobjectArray>(env->CallObjectMethod(jMixesList, gArrayListMethods.toArray));
jint numMixes = env->GetArrayLength(jMixes);
if (numMixes > MAX_MIXES_PER_POLICY) {
numMixes = MAX_MIXES_PER_POLICY;
}
status_t status;
- jint jStatus;
- jobject jAudioMix = NULL;
Vector <AudioMix> mixes;
for (jint i = 0; i < numMixes; i++) {
- jAudioMix = env->GetObjectArrayElement(jMixes, i);
- if (!env->IsInstanceOf(jAudioMix, gAudioMixClass)) {
- jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
- goto exit;
+ ScopedLocalRef<jobject> jAudioMix(env, env->GetObjectArrayElement(jMixes, i));
+ if (!env->IsInstanceOf(jAudioMix.get(), gAudioMixClass)) {
+ return AUDIO_JAVA_BAD_VALUE;
}
AudioMix mix;
- jStatus = convertAudioMixToNative(env, &mix, jAudioMix);
- env->DeleteLocalRef(jAudioMix);
- jAudioMix = NULL;
- if (jStatus != AUDIO_JAVA_SUCCESS) {
- goto exit;
+ if (jint jStatus = convertAudioMixToNative(env, &mix, jAudioMix.get());
+ jStatus != AUDIO_JAVA_SUCCESS) {
+ return jStatus;
}
mixes.add(mix);
}
@@ -2329,16 +2212,7 @@
status = AudioSystem::registerPolicyMixes(mixes, registration);
ALOGV("AudioSystem::registerPolicyMixes() returned %d", status);
- jStatus = nativeToJavaStatus(status);
- if (jStatus != AUDIO_JAVA_SUCCESS) {
- goto exit;
- }
-
-exit:
- if (jAudioMix != NULL) {
- env->DeleteLocalRef(jAudioMix);
- }
- return jStatus;
+ return nativeToJavaStatus(status);
}
static jint android_media_AudioSystem_setUidDeviceAffinities(JNIEnv *env, jobject clazz,
@@ -2348,14 +2222,14 @@
if (results != NO_ERROR) {
return results;
}
- status_t status = AudioSystem::setUidDeviceAffinities((uid_t) uid, deviceVector);
- return (jint) nativeToJavaStatus(status);
+ status_t status = AudioSystem::setUidDeviceAffinities(uid, deviceVector);
+ return nativeToJavaStatus(status);
}
static jint android_media_AudioSystem_removeUidDeviceAffinities(JNIEnv *env, jobject clazz,
jint uid) {
- status_t status = AudioSystem::removeUidDeviceAffinities((uid_t) uid);
- return (jint) nativeToJavaStatus(status);
+ status_t status = AudioSystem::removeUidDeviceAffinities(static_cast<uid_t>(uid));
+ return nativeToJavaStatus(status);
}
static jint android_media_AudioSystem_setUserIdDeviceAffinities(JNIEnv *env, jobject clazz,
@@ -2366,14 +2240,14 @@
if (results != NO_ERROR) {
return results;
}
- status_t status = AudioSystem::setUserIdDeviceAffinities((int)userId, deviceVector);
- return (jint)nativeToJavaStatus(status);
+ status_t status = AudioSystem::setUserIdDeviceAffinities(userId, deviceVector);
+ return nativeToJavaStatus(status);
}
static jint android_media_AudioSystem_removeUserIdDeviceAffinities(JNIEnv *env, jobject clazz,
jint userId) {
- status_t status = AudioSystem::removeUserIdDeviceAffinities((int)userId);
- return (jint)nativeToJavaStatus(status);
+ status_t status = AudioSystem::removeUserIdDeviceAffinities(userId);
+ return nativeToJavaStatus(status);
}
static jint
@@ -2386,19 +2260,18 @@
android_media_AudioSystem_getStreamVolumeDB(JNIEnv *env, jobject thiz,
jint stream, jint index, jint device)
{
- return (jfloat)AudioSystem::getStreamVolumeDB((audio_stream_type_t)stream,
- (int)index,
- (audio_devices_t)device);
+ return AudioSystem::getStreamVolumeDB(static_cast<audio_stream_type_t>(stream), index,
+ static_cast<audio_devices_t>(device));
}
static jint android_media_AudioSystem_getOffloadSupport(JNIEnv *env, jobject thiz, jint encoding,
jint sampleRate, jint channelMask,
jint channelIndexMask, jint streamType) {
audio_offload_info_t format = AUDIO_INFO_INITIALIZER;
- format.format = (audio_format_t) audioFormatToNative(encoding);
- format.sample_rate = (uint32_t) sampleRate;
+ format.format = static_cast<audio_format_t>(audioFormatToNative(encoding));
+ format.sample_rate = sampleRate;
format.channel_mask = nativeChannelMaskFromJavaChannelMasks(channelMask, channelIndexMask);
- format.stream_type = (audio_stream_type_t) streamType;
+ format.stream_type = static_cast<audio_stream_type_t>(streamType);
format.has_video = false;
format.is_streaming = false;
// offload duration unknown at this point:
@@ -2415,11 +2288,11 @@
if (jMicrophonesInfo == NULL) {
ALOGE("jMicrophonesInfo NULL MicrophoneInfo ArrayList");
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
if (!env->IsInstanceOf(jMicrophonesInfo, gArrayListClass)) {
ALOGE("getMicrophones not an arraylist");
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
jint jStatus;
@@ -2431,7 +2304,7 @@
return jStatus;
}
if (microphones.size() == 0) {
- jStatus = (jint)AUDIO_JAVA_SUCCESS;
+ jStatus = AUDIO_JAVA_SUCCESS;
return jStatus;
}
for (size_t i = 0; i < microphones.size(); i++) {
@@ -2453,7 +2326,7 @@
jint jStatus = AUDIO_JAVA_SUCCESS;
if (!env->IsInstanceOf(jEncodingFormatList, gArrayListClass)) {
ALOGE("%s: jEncodingFormatList not an ArrayList", __FUNCTION__);
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
std::vector<audio_format_t> encodingFormats;
status_t status =
@@ -2572,12 +2445,12 @@
android_media_AudioSystem_setSurroundFormatEnabled(JNIEnv *env, jobject thiz,
jint audioFormat, jboolean enabled)
{
- status_t status = AudioSystem::setSurroundFormatEnabled(audioFormatToNative(audioFormat),
- (bool)enabled);
+ status_t status =
+ AudioSystem::setSurroundFormatEnabled(audioFormatToNative(audioFormat), enabled);
if (status != NO_ERROR) {
ALOGE_IF(status != NO_ERROR, "AudioSystem::setSurroundFormatEnabled error %d", status);
}
- return (jint)nativeToJavaStatus(status);
+ return nativeToJavaStatus(status);
}
static jint android_media_AudioSystem_getMaxChannelCount(JNIEnv *env, jobject thiz) {
@@ -2618,7 +2491,7 @@
status_t status = AudioSystem::setAssistantServicesUids(nativeUidsVector);
- return (jint)nativeToJavaStatus(status);
+ return nativeToJavaStatus(status);
}
static jint android_media_AudioSystem_setActiveAssistantServicesUids(JNIEnv *env, jobject thiz,
@@ -2627,7 +2500,7 @@
status_t status = AudioSystem::setActiveAssistantServicesUids(nativeActiveUidsVector);
- return (jint)nativeToJavaStatus(status);
+ return nativeToJavaStatus(status);
}
static jint
@@ -2635,12 +2508,12 @@
std::vector<uid_t> nativeUidsVector = convertJIntArrayToUidVector(env, uids);
status_t status = AudioSystem::setA11yServicesUids(nativeUidsVector);
- return (jint)nativeToJavaStatus(status);
+ return nativeToJavaStatus(status);
}
static jint android_media_AudioSystem_setCurrentImeUid(JNIEnv *env, jobject thiz, jint uid) {
status_t status = AudioSystem::setCurrentImeUid(uid);
- return (jint)nativeToJavaStatus(status);
+ return nativeToJavaStatus(status);
}
static jboolean
@@ -2658,7 +2531,7 @@
std::vector<audio_usage_t> nativeSystemUsagesVector;
if (systemUsages == nullptr) {
- return (jint) AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
int *nativeSystemUsages = nullptr;
@@ -2675,7 +2548,7 @@
}
status_t status = AudioSystem::setSupportedSystemUsages(nativeSystemUsagesVector);
- return (jint)nativeToJavaStatus(status);
+ return nativeToJavaStatus(status);
}
static jint
@@ -2686,16 +2559,16 @@
static jint
android_media_AudioSystem_setRttEnabled(JNIEnv *env, jobject thiz, jboolean enabled)
{
- return (jint) check_AudioSystem_Command(AudioSystem::setRttEnabled(enabled));
+ return check_AudioSystem_Command(AudioSystem::setRttEnabled(enabled));
}
static jint
android_media_AudioSystem_setAudioHalPids(JNIEnv *env, jobject clazz, jintArray jPids)
{
if (jPids == NULL) {
- return (jint) AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
- pid_t *nPidsArray = (pid_t *) env->GetIntArrayElements(jPids, NULL);
+ pid_t *nPidsArray = reinterpret_cast<pid_t *>(env->GetIntArrayElements(jPids, NULL));
std::vector<pid_t> nPids(nPidsArray, nPidsArray + env->GetArrayLength(jPids));
status_t status = AudioSystem::setAudioHalPids(nPids);
env->ReleaseIntArrayElements(jPids, nPidsArray, 0);
@@ -2719,9 +2592,9 @@
return results;
}
int status = check_AudioSystem_Command(
- AudioSystem::setDevicesRoleForStrategy((product_strategy_t)strategy,
- (device_role_t)role, nDevices));
- return (jint) status;
+ AudioSystem::setDevicesRoleForStrategy(static_cast<product_strategy_t>(strategy),
+ static_cast<device_role_t>(role), nDevices));
+ return status;
}
static jint android_media_AudioSystem_removeDevicesRoleForStrategy(JNIEnv *env, jobject thiz,
@@ -2734,8 +2607,8 @@
return results;
}
int status = check_AudioSystem_Command(
- AudioSystem::removeDevicesRoleForStrategy((product_strategy_t)strategy,
- (device_role_t)role, nDevices));
+ AudioSystem::removeDevicesRoleForStrategy(static_cast<product_strategy_t>(strategy),
+ static_cast<device_role_t>(role), nDevices));
return (jint)status;
}
@@ -2753,10 +2626,10 @@
jobject jDevices) {
AudioDeviceTypeAddrVector nDevices;
status_t status = check_AudioSystem_Command(
- AudioSystem::getDevicesForRoleAndStrategy((product_strategy_t)strategy,
- (device_role_t)role, nDevices));
+ AudioSystem::getDevicesForRoleAndStrategy(static_cast<product_strategy_t>(strategy),
+ static_cast<device_role_t>(role), nDevices));
if (status != NO_ERROR) {
- return (jint) status;
+ return status;
}
for (const auto &device : nDevices) {
jobject jAudioDeviceAttributes = NULL;
@@ -2779,9 +2652,10 @@
return results;
}
int status = check_AudioSystem_Command(
- AudioSystem::setDevicesRoleForCapturePreset((audio_source_t)capturePreset,
- (device_role_t)role, nDevices));
- return (jint)status;
+ AudioSystem::setDevicesRoleForCapturePreset(static_cast<audio_source_t>(capturePreset),
+ static_cast<device_role_t>(role),
+ nDevices));
+ return status;
}
static jint android_media_AudioSystem_addDevicesRoleForCapturePreset(
@@ -2793,9 +2667,10 @@
return results;
}
int status = check_AudioSystem_Command(
- AudioSystem::addDevicesRoleForCapturePreset((audio_source_t)capturePreset,
- (device_role_t)role, nDevices));
- return (jint)status;
+ AudioSystem::addDevicesRoleForCapturePreset(static_cast<audio_source_t>(capturePreset),
+ static_cast<device_role_t>(role),
+ nDevices));
+ return status;
}
static jint android_media_AudioSystem_removeDevicesRoleForCapturePreset(
@@ -2807,17 +2682,20 @@
return results;
}
int status = check_AudioSystem_Command(
- AudioSystem::removeDevicesRoleForCapturePreset((audio_source_t)capturePreset,
- (device_role_t)role, nDevices));
- return (jint)status;
+ AudioSystem::removeDevicesRoleForCapturePreset(static_cast<audio_source_t>(
+ capturePreset),
+ static_cast<device_role_t>(role),
+ nDevices));
+ return status;
}
static jint android_media_AudioSystem_clearDevicesRoleForCapturePreset(JNIEnv *env, jobject thiz,
jint capturePreset,
jint role) {
- return (jint)check_AudioSystem_Command(
- AudioSystem::clearDevicesRoleForCapturePreset((audio_source_t)capturePreset,
- (device_role_t)role));
+ return static_cast<jint>(check_AudioSystem_Command(
+ AudioSystem::clearDevicesRoleForCapturePreset(static_cast<audio_source_t>(
+ capturePreset),
+ static_cast<device_role_t>(role))));
}
static jint android_media_AudioSystem_getDevicesForRoleAndCapturePreset(JNIEnv *env, jobject thiz,
@@ -2826,10 +2704,12 @@
jobject jDevices) {
AudioDeviceTypeAddrVector nDevices;
status_t status = check_AudioSystem_Command(
- AudioSystem::getDevicesForRoleAndCapturePreset((audio_source_t)capturePreset,
- (device_role_t)role, nDevices));
+ AudioSystem::getDevicesForRoleAndCapturePreset(static_cast<audio_source_t>(
+ capturePreset),
+ static_cast<device_role_t>(role),
+ nDevices));
if (status != NO_ERROR) {
- return (jint)status;
+ return status;
}
for (const auto &device : nDevices) {
jobject jAudioDeviceAttributes = NULL;
@@ -2854,12 +2734,12 @@
// components call this method often
if (jDeviceArray == nullptr || maxResultSize == 0) {
ALOGE("%s invalid array to store AudioDeviceAttributes", __FUNCTION__);
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
- if (jStatus != (jint) AUDIO_JAVA_SUCCESS) {
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
return jStatus;
}
@@ -2888,7 +2768,7 @@
static jint android_media_AudioSystem_setVibratorInfos(JNIEnv *env, jobject thiz,
jobject jVibrators) {
if (!env->IsInstanceOf(jVibrators, gListClass)) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
const jint size = env->CallIntMethod(jVibrators, gListMethods.size);
std::vector<media::AudioVibratorInfo> vibratorInfos;
@@ -2896,7 +2776,7 @@
ScopedLocalRef<jobject> jVibrator(env,
env->CallObjectMethod(jVibrators, gListMethods.get, i));
if (!env->IsInstanceOf(jVibrator.get(), gVibratorClass)) {
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
media::AudioVibratorInfo vibratorInfo;
vibratorInfo.id = env->CallIntMethod(jVibrator.get(), gVibratorMethods.getId);
@@ -2907,7 +2787,7 @@
env->CallFloatMethod(jVibrator.get(), gVibratorMethods.getMaxAmplitude);
vibratorInfos.push_back(vibratorInfo);
}
- return (jint)check_AudioSystem_Command(AudioSystem::setVibratorInfos(vibratorInfos));
+ return check_AudioSystem_Command(AudioSystem::setVibratorInfos(vibratorInfos));
}
static jobject android_media_AudioSystem_getSpatializer(JNIEnv *env, jobject thiz,
@@ -2929,8 +2809,8 @@
jobjectArray jDeviceArray) {
JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
- if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
- return false;
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
+ return false;
}
AudioDeviceTypeAddrVector nDevices;
@@ -2943,7 +2823,7 @@
return false;
}
jStatus = createAudioDeviceTypeAddrFromJava(env, &device, jDevice);
- if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
return false;
}
nDevices.push_back(device);
@@ -3000,7 +2880,7 @@
jobject jFormat, jobject jaa) {
JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
- if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
return DIRECT_NOT_SUPPORTED;
}
@@ -3023,20 +2903,20 @@
if (jAudioAttributes == nullptr) {
ALOGE("jAudioAttributes is NULL");
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
if (jAudioProfilesList == nullptr) {
ALOGE("jAudioProfilesList is NULL");
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
if (!env->IsInstanceOf(jAudioProfilesList, gArrayListClass)) {
ALOGE("jAudioProfilesList not an ArrayList");
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return AUDIO_JAVA_BAD_VALUE;
}
JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jAudioAttributes, paa.get());
- if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
return jStatus;
}
@@ -3212,8 +3092,7 @@
static int android_media_AudioSystem_setBluetoothVariableLatencyEnabled(JNIEnv *env, jobject thiz,
jboolean enabled) {
- return (jint)check_AudioSystem_Command(
- AudioSystem::setBluetoothVariableLatencyEnabled(enabled));
+ return check_AudioSystem_Command(AudioSystem::setBluetoothVariableLatencyEnabled(enabled));
}
static jboolean android_media_AudioSystem_isBluetoothVariableLatencyEnabled(JNIEnv *env,
@@ -3227,191 +3106,182 @@
// ----------------------------------------------------------------------------
+#define MAKE_AUDIO_SYSTEM_METHOD(x) \
+ MAKE_JNI_NATIVE_METHOD_AUTOSIG(#x, android_media_AudioSystem_##x)
+
static const JNINativeMethod gMethods[] =
- {{"setParameters", "(Ljava/lang/String;)I",
- (void *)android_media_AudioSystem_setParameters},
- {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;",
- (void *)android_media_AudioSystem_getParameters},
- {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone},
- {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted},
- {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive},
- {"isStreamActiveRemotely", "(II)Z",
- (void *)android_media_AudioSystem_isStreamActiveRemotely},
- {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive},
- {"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId},
- {"newAudioPlayerId", "()I", (void *)android_media_AudioSystem_newAudioPlayerId},
- {"newAudioRecorderId", "()I", (void *)android_media_AudioSystem_newAudioRecorderId},
- {"setDeviceConnectionState", "(ILandroid/os/Parcel;I)I",
- (void *)android_media_AudioSystem_setDeviceConnectionState},
- {"getDeviceConnectionState", "(ILjava/lang/String;)I",
- (void *)android_media_AudioSystem_getDeviceConnectionState},
- {"handleDeviceConfigChange", "(ILjava/lang/String;Ljava/lang/String;I)I",
- (void *)android_media_AudioSystem_handleDeviceConfigChange},
- {"setPhoneState", "(II)I", (void *)android_media_AudioSystem_setPhoneState},
- {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse},
- {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse},
- {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume},
- {"setStreamVolumeIndex", "(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex},
- {"getStreamVolumeIndex", "(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex},
- {"setVolumeIndexForAttributes", "(Landroid/media/AudioAttributes;II)I",
- (void *)android_media_AudioSystem_setVolumeIndexForAttributes},
- {"getVolumeIndexForAttributes", "(Landroid/media/AudioAttributes;I)I",
- (void *)android_media_AudioSystem_getVolumeIndexForAttributes},
- {"getMinVolumeIndexForAttributes", "(Landroid/media/AudioAttributes;)I",
- (void *)android_media_AudioSystem_getMinVolumeIndexForAttributes},
- {"getMaxVolumeIndexForAttributes", "(Landroid/media/AudioAttributes;)I",
- (void *)android_media_AudioSystem_getMaxVolumeIndexForAttributes},
- {"setMasterVolume", "(F)I", (void *)android_media_AudioSystem_setMasterVolume},
- {"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume},
- {"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute},
- {"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute},
- {"setMasterMono", "(Z)I", (void *)android_media_AudioSystem_setMasterMono},
- {"getMasterMono", "()Z", (void *)android_media_AudioSystem_getMasterMono},
- {"setMasterBalance", "(F)I", (void *)android_media_AudioSystem_setMasterBalance},
- {"getMasterBalance", "()F", (void *)android_media_AudioSystem_getMasterBalance},
- {"getPrimaryOutputSamplingRate", "()I",
- (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
- {"getPrimaryOutputFrameCount", "()I",
- (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
- {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
- {"setLowRamDevice", "(ZJ)I", (void *)android_media_AudioSystem_setLowRamDevice},
- {"checkAudioFlinger", "()I", (void *)android_media_AudioSystem_checkAudioFlinger},
- {"setAudioFlingerBinder", "(Landroid/os/IBinder;)V",
- (void *)android_media_AudioSystem_setAudioFlingerBinder},
- {"listAudioPorts", "(Ljava/util/ArrayList;[I)I",
- (void *)android_media_AudioSystem_listAudioPorts},
- {"createAudioPatch",
- "([Landroid/media/AudioPatch;[Landroid/media/AudioPortConfig;[Landroid/media/"
- "AudioPortConfig;)I",
- (void *)android_media_AudioSystem_createAudioPatch},
- {"releaseAudioPatch", "(Landroid/media/AudioPatch;)I",
- (void *)android_media_AudioSystem_releaseAudioPatch},
- {"listAudioPatches", "(Ljava/util/ArrayList;[I)I",
- (void *)android_media_AudioSystem_listAudioPatches},
- {"setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I",
- (void *)android_media_AudioSystem_setAudioPortConfig},
- {"startAudioSource", "(Landroid/media/AudioPortConfig;Landroid/media/AudioAttributes;)I",
- (void *)android_media_AudioSystem_startAudioSource},
- {"stopAudioSource", "(I)I", (void *)android_media_AudioSystem_stopAudioSource},
- {"getAudioHwSyncForSession", "(I)I",
- (void *)android_media_AudioSystem_getAudioHwSyncForSession},
- {"registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
- (void *)android_media_AudioSystem_registerPolicyMixes},
- {"setUidDeviceAffinities", "(I[I[Ljava/lang/String;)I",
- (void *)android_media_AudioSystem_setUidDeviceAffinities},
- {"removeUidDeviceAffinities", "(I)I",
- (void *)android_media_AudioSystem_removeUidDeviceAffinities},
- {"native_register_dynamic_policy_callback", "()V",
- (void *)android_media_AudioSystem_registerDynPolicyCallback},
- {"native_register_recording_callback", "()V",
- (void *)android_media_AudioSystem_registerRecordingCallback},
- {"native_register_routing_callback", "()V",
- (void *)android_media_AudioSystem_registerRoutingCallback},
- {"native_register_vol_range_init_req_callback", "()V",
- (void *)android_media_AudioSystem_registerVolRangeInitReqCallback},
- {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
- {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB},
- {"native_get_offload_support", "(IIIII)I",
- (void *)android_media_AudioSystem_getOffloadSupport},
- {"getMicrophones", "(Ljava/util/ArrayList;)I",
- (void *)android_media_AudioSystem_getMicrophones},
- {"getSurroundFormats", "(Ljava/util/Map;)I",
- (void *)android_media_AudioSystem_getSurroundFormats},
- {"getReportedSurroundFormats", "(Ljava/util/ArrayList;)I",
- (void *)android_media_AudioSystem_getReportedSurroundFormats},
- {"setSurroundFormatEnabled", "(IZ)I",
- (void *)android_media_AudioSystem_setSurroundFormatEnabled},
- {"setAssistantServicesUids", "([I)I",
- (void *)android_media_AudioSystem_setAssistantServicesUids},
- {"setActiveAssistantServicesUids", "([I)I",
- (void *)android_media_AudioSystem_setActiveAssistantServicesUids},
- {"setA11yServicesUids", "([I)I", (void *)android_media_AudioSystem_setA11yServicesUids},
- {"isHapticPlaybackSupported", "()Z",
- (void *)android_media_AudioSystem_isHapticPlaybackSupported},
- {"isUltrasoundSupported", "()Z", (void *)android_media_AudioSystem_isUltrasoundSupported},
- {"getHwOffloadFormatsSupportedForBluetoothMedia", "(ILjava/util/ArrayList;)I",
- (void *)android_media_AudioSystem_getHwOffloadFormatsSupportedForBluetoothMedia},
- {"setSupportedSystemUsages", "([I)I",
- (void *)android_media_AudioSystem_setSupportedSystemUsages},
- {"setAllowedCapturePolicy", "(II)I",
- (void *)android_media_AudioSystem_setAllowedCapturePolicy},
- {"setRttEnabled", "(Z)I", (void *)android_media_AudioSystem_setRttEnabled},
- {"setAudioHalPids", "([I)I", (void *)android_media_AudioSystem_setAudioHalPids},
- {"isCallScreeningModeSupported", "()Z",
- (void *)android_media_AudioSystem_isCallScreeningModeSupported},
- {"setDevicesRoleForStrategy", "(II[I[Ljava/lang/String;)I",
- (void *)android_media_AudioSystem_setDevicesRoleForStrategy},
- {"removeDevicesRoleForStrategy", "(II[I[Ljava/lang/String;)I",
- (void *)android_media_AudioSystem_removeDevicesRoleForStrategy},
- {"clearDevicesRoleForStrategy", "(II)I",
- (void *)android_media_AudioSystem_clearDevicesRoleForStrategy},
- {"getDevicesForRoleAndStrategy", "(IILjava/util/List;)I",
- (void *)android_media_AudioSystem_getDevicesForRoleAndStrategy},
- {"setDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I",
- (void *)android_media_AudioSystem_setDevicesRoleForCapturePreset},
- {"addDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I",
- (void *)android_media_AudioSystem_addDevicesRoleForCapturePreset},
- {"removeDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I",
- (void *)android_media_AudioSystem_removeDevicesRoleForCapturePreset},
- {"clearDevicesRoleForCapturePreset", "(II)I",
- (void *)android_media_AudioSystem_clearDevicesRoleForCapturePreset},
- {"getDevicesForRoleAndCapturePreset", "(IILjava/util/List;)I",
- (void *)android_media_AudioSystem_getDevicesForRoleAndCapturePreset},
- {"getDevicesForAttributes",
- "(Landroid/media/AudioAttributes;[Landroid/media/AudioDeviceAttributes;Z)I",
- (void *)android_media_AudioSystem_getDevicesForAttributes},
- {"setUserIdDeviceAffinities", "(I[I[Ljava/lang/String;)I",
- (void *)android_media_AudioSystem_setUserIdDeviceAffinities},
- {"removeUserIdDeviceAffinities", "(I)I",
- (void *)android_media_AudioSystem_removeUserIdDeviceAffinities},
- {"setCurrentImeUid", "(I)I", (void *)android_media_AudioSystem_setCurrentImeUid},
- {"setVibratorInfos", "(Ljava/util/List;)I",
- (void *)android_media_AudioSystem_setVibratorInfos},
- {"nativeGetSpatializer",
- "(Landroid/media/INativeSpatializerCallback;)Landroid/os/IBinder;",
- (void *)android_media_AudioSystem_getSpatializer},
- {"canBeSpatialized",
- "(Landroid/media/AudioAttributes;Landroid/media/AudioFormat;"
- "[Landroid/media/AudioDeviceAttributes;)Z",
- (void *)android_media_AudioSystem_canBeSpatialized},
- {"nativeGetSoundDose", "(Landroid/media/ISoundDoseCallback;)Landroid/os/IBinder;",
- (void *)android_media_AudioSystem_nativeGetSoundDose},
- {"getDirectPlaybackSupport",
- "(Landroid/media/AudioFormat;Landroid/media/AudioAttributes;)I",
- (void *)android_media_AudioSystem_getDirectPlaybackSupport},
- {"getDirectProfilesForAttributes",
- "(Landroid/media/AudioAttributes;Ljava/util/ArrayList;)I",
- (void *)android_media_AudioSystem_getDirectProfilesForAttributes},
- {"getSupportedMixerAttributes", "(ILjava/util/List;)I",
- (void *)android_media_AudioSystem_getSupportedMixerAttributes},
- {"setPreferredMixerAttributes",
- "(Landroid/media/AudioAttributes;IILandroid/media/AudioMixerAttributes;)I",
- (void *)android_media_AudioSystem_setPreferredMixerAttributes},
- {"getPreferredMixerAttributes", "(Landroid/media/AudioAttributes;ILjava/util/List;)I",
- (void *)android_media_AudioSystem_getPreferredMixerAttributes},
- {"clearPreferredMixerAttributes", "(Landroid/media/AudioAttributes;II)I",
- (void *)android_media_AudioSystem_clearPreferredMixerAttributes},
- {"supportsBluetoothVariableLatency", "()Z",
- (void *)android_media_AudioSystem_supportsBluetoothVariableLatency},
- {"setBluetoothVariableLatencyEnabled", "(Z)I",
- (void *)android_media_AudioSystem_setBluetoothVariableLatencyEnabled},
- {"isBluetoothVariableLatencyEnabled", "()Z",
- (void *)android_media_AudioSystem_isBluetoothVariableLatencyEnabled}};
+ {MAKE_AUDIO_SYSTEM_METHOD(setParameters),
+ MAKE_AUDIO_SYSTEM_METHOD(getParameters),
+ MAKE_AUDIO_SYSTEM_METHOD(muteMicrophone),
+ MAKE_AUDIO_SYSTEM_METHOD(isMicrophoneMuted),
+ MAKE_AUDIO_SYSTEM_METHOD(isStreamActive),
+ MAKE_AUDIO_SYSTEM_METHOD(isStreamActiveRemotely),
+ MAKE_AUDIO_SYSTEM_METHOD(isSourceActive),
+ MAKE_AUDIO_SYSTEM_METHOD(newAudioSessionId),
+ MAKE_AUDIO_SYSTEM_METHOD(newAudioPlayerId),
+ MAKE_AUDIO_SYSTEM_METHOD(newAudioRecorderId),
+ MAKE_JNI_NATIVE_METHOD("setDeviceConnectionState", "(ILandroid/os/Parcel;I)I",
+ android_media_AudioSystem_setDeviceConnectionState),
+ MAKE_AUDIO_SYSTEM_METHOD(getDeviceConnectionState),
+ MAKE_AUDIO_SYSTEM_METHOD(handleDeviceConfigChange),
+ MAKE_AUDIO_SYSTEM_METHOD(setPhoneState),
+ MAKE_AUDIO_SYSTEM_METHOD(setForceUse),
+ MAKE_AUDIO_SYSTEM_METHOD(getForceUse),
+ MAKE_AUDIO_SYSTEM_METHOD(initStreamVolume),
+ MAKE_AUDIO_SYSTEM_METHOD(setStreamVolumeIndex),
+ MAKE_AUDIO_SYSTEM_METHOD(getStreamVolumeIndex),
+ MAKE_JNI_NATIVE_METHOD("setVolumeIndexForAttributes",
+ "(Landroid/media/AudioAttributes;II)I",
+ android_media_AudioSystem_setVolumeIndexForAttributes),
+ MAKE_JNI_NATIVE_METHOD("getVolumeIndexForAttributes",
+ "(Landroid/media/AudioAttributes;I)I",
+ android_media_AudioSystem_getVolumeIndexForAttributes),
+ MAKE_JNI_NATIVE_METHOD("getMinVolumeIndexForAttributes",
+ "(Landroid/media/AudioAttributes;)I",
+ android_media_AudioSystem_getMinVolumeIndexForAttributes),
+ MAKE_JNI_NATIVE_METHOD("getMaxVolumeIndexForAttributes",
+ "(Landroid/media/AudioAttributes;)I",
+ android_media_AudioSystem_getMaxVolumeIndexForAttributes),
+ MAKE_AUDIO_SYSTEM_METHOD(setMasterVolume),
+ MAKE_AUDIO_SYSTEM_METHOD(getMasterVolume),
+ MAKE_AUDIO_SYSTEM_METHOD(setMasterMute),
+ MAKE_AUDIO_SYSTEM_METHOD(getMasterMute),
+ MAKE_AUDIO_SYSTEM_METHOD(setMasterMono),
+ MAKE_AUDIO_SYSTEM_METHOD(getMasterMono),
+ MAKE_AUDIO_SYSTEM_METHOD(setMasterBalance),
+ MAKE_AUDIO_SYSTEM_METHOD(getMasterBalance),
+ MAKE_AUDIO_SYSTEM_METHOD(getPrimaryOutputSamplingRate),
+ MAKE_AUDIO_SYSTEM_METHOD(getPrimaryOutputFrameCount),
+ MAKE_AUDIO_SYSTEM_METHOD(getOutputLatency),
+ MAKE_AUDIO_SYSTEM_METHOD(setLowRamDevice),
+ MAKE_AUDIO_SYSTEM_METHOD(checkAudioFlinger),
+ MAKE_JNI_NATIVE_METHOD("setAudioFlingerBinder", "(Landroid/os/IBinder;)V",
+ android_media_AudioSystem_setAudioFlingerBinder),
+ MAKE_JNI_NATIVE_METHOD("listAudioPorts", "(Ljava/util/ArrayList;[I)I",
+ android_media_AudioSystem_listAudioPorts),
+ MAKE_JNI_NATIVE_METHOD("createAudioPatch",
+ "([Landroid/media/AudioPatch;[Landroid/media/"
+ "AudioPortConfig;[Landroid/media/AudioPortConfig;)I",
+ android_media_AudioSystem_createAudioPatch),
+ MAKE_JNI_NATIVE_METHOD("releaseAudioPatch", "(Landroid/media/AudioPatch;)I",
+ android_media_AudioSystem_releaseAudioPatch),
+ MAKE_JNI_NATIVE_METHOD("listAudioPatches", "(Ljava/util/ArrayList;[I)I",
+ android_media_AudioSystem_listAudioPatches),
+ MAKE_JNI_NATIVE_METHOD("setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I",
+ android_media_AudioSystem_setAudioPortConfig),
+ MAKE_JNI_NATIVE_METHOD("startAudioSource",
+ "(Landroid/media/AudioPortConfig;Landroid/media/AudioAttributes;)I",
+ android_media_AudioSystem_startAudioSource),
+ MAKE_AUDIO_SYSTEM_METHOD(stopAudioSource),
+ MAKE_AUDIO_SYSTEM_METHOD(getAudioHwSyncForSession),
+ MAKE_JNI_NATIVE_METHOD("registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
+ android_media_AudioSystem_registerPolicyMixes),
+ MAKE_JNI_NATIVE_METHOD("setUidDeviceAffinities", "(I[I[Ljava/lang/String;)I",
+ android_media_AudioSystem_setUidDeviceAffinities),
+ MAKE_AUDIO_SYSTEM_METHOD(removeUidDeviceAffinities),
+ MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_register_dynamic_policy_callback",
+ android_media_AudioSystem_registerDynPolicyCallback),
+ MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_register_recording_callback",
+ android_media_AudioSystem_registerRecordingCallback),
+ MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_register_routing_callback",
+ android_media_AudioSystem_registerRoutingCallback),
+ MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_register_vol_range_init_req_callback",
+ android_media_AudioSystem_registerVolRangeInitReqCallback),
+ MAKE_AUDIO_SYSTEM_METHOD(systemReady),
+ MAKE_AUDIO_SYSTEM_METHOD(getStreamVolumeDB),
+ MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_get_offload_support",
+ android_media_AudioSystem_getOffloadSupport),
+ MAKE_JNI_NATIVE_METHOD("getMicrophones", "(Ljava/util/ArrayList;)I",
+ android_media_AudioSystem_getMicrophones),
+ MAKE_JNI_NATIVE_METHOD("getSurroundFormats", "(Ljava/util/Map;)I",
+ android_media_AudioSystem_getSurroundFormats),
+ MAKE_JNI_NATIVE_METHOD("getReportedSurroundFormats", "(Ljava/util/ArrayList;)I",
+ android_media_AudioSystem_getReportedSurroundFormats),
+ MAKE_AUDIO_SYSTEM_METHOD(setSurroundFormatEnabled),
+ MAKE_AUDIO_SYSTEM_METHOD(setAssistantServicesUids),
+ MAKE_AUDIO_SYSTEM_METHOD(setActiveAssistantServicesUids),
+ MAKE_AUDIO_SYSTEM_METHOD(setA11yServicesUids),
+ MAKE_AUDIO_SYSTEM_METHOD(isHapticPlaybackSupported),
+ MAKE_AUDIO_SYSTEM_METHOD(isUltrasoundSupported),
+ MAKE_JNI_NATIVE_METHOD(
+ "getHwOffloadFormatsSupportedForBluetoothMedia", "(ILjava/util/ArrayList;)I",
+ android_media_AudioSystem_getHwOffloadFormatsSupportedForBluetoothMedia),
+ MAKE_AUDIO_SYSTEM_METHOD(setSupportedSystemUsages),
+ MAKE_AUDIO_SYSTEM_METHOD(setAllowedCapturePolicy),
+ MAKE_AUDIO_SYSTEM_METHOD(setRttEnabled),
+ MAKE_AUDIO_SYSTEM_METHOD(setAudioHalPids),
+ MAKE_AUDIO_SYSTEM_METHOD(isCallScreeningModeSupported),
+ MAKE_JNI_NATIVE_METHOD("setDevicesRoleForStrategy", "(II[I[Ljava/lang/String;)I",
+ android_media_AudioSystem_setDevicesRoleForStrategy),
+ MAKE_JNI_NATIVE_METHOD("removeDevicesRoleForStrategy", "(II[I[Ljava/lang/String;)I",
+ android_media_AudioSystem_removeDevicesRoleForStrategy),
+ MAKE_AUDIO_SYSTEM_METHOD(clearDevicesRoleForStrategy),
+ MAKE_JNI_NATIVE_METHOD("getDevicesForRoleAndStrategy", "(IILjava/util/List;)I",
+ android_media_AudioSystem_getDevicesForRoleAndStrategy),
+ MAKE_JNI_NATIVE_METHOD("setDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I",
+ android_media_AudioSystem_setDevicesRoleForCapturePreset),
+ MAKE_JNI_NATIVE_METHOD("addDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I",
+ android_media_AudioSystem_addDevicesRoleForCapturePreset),
+ MAKE_JNI_NATIVE_METHOD("removeDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I",
+ android_media_AudioSystem_removeDevicesRoleForCapturePreset),
+ MAKE_AUDIO_SYSTEM_METHOD(clearDevicesRoleForCapturePreset),
+ MAKE_JNI_NATIVE_METHOD("getDevicesForRoleAndCapturePreset", "(IILjava/util/List;)I",
+ android_media_AudioSystem_getDevicesForRoleAndCapturePreset),
+ MAKE_JNI_NATIVE_METHOD("getDevicesForAttributes",
+ "(Landroid/media/AudioAttributes;[Landroid/media/"
+ "AudioDeviceAttributes;Z)I",
+ android_media_AudioSystem_getDevicesForAttributes),
+ MAKE_JNI_NATIVE_METHOD("setUserIdDeviceAffinities", "(I[I[Ljava/lang/String;)I",
+ android_media_AudioSystem_setUserIdDeviceAffinities),
+ MAKE_AUDIO_SYSTEM_METHOD(removeUserIdDeviceAffinities),
+ MAKE_AUDIO_SYSTEM_METHOD(setCurrentImeUid),
+ MAKE_JNI_NATIVE_METHOD("setVibratorInfos", "(Ljava/util/List;)I",
+ android_media_AudioSystem_setVibratorInfos),
+ MAKE_JNI_NATIVE_METHOD("nativeGetSpatializer",
+ "(Landroid/media/INativeSpatializerCallback;)Landroid/os/IBinder;",
+ android_media_AudioSystem_getSpatializer),
+ MAKE_JNI_NATIVE_METHOD("canBeSpatialized",
+ "(Landroid/media/AudioAttributes;Landroid/media/AudioFormat;"
+ "[Landroid/media/AudioDeviceAttributes;)Z",
+ android_media_AudioSystem_canBeSpatialized),
+ MAKE_JNI_NATIVE_METHOD("nativeGetSoundDose",
+ "(Landroid/media/ISoundDoseCallback;)Landroid/os/IBinder;",
+ android_media_AudioSystem_nativeGetSoundDose),
+ MAKE_JNI_NATIVE_METHOD("getDirectPlaybackSupport",
+ "(Landroid/media/AudioFormat;Landroid/media/AudioAttributes;)I",
+ android_media_AudioSystem_getDirectPlaybackSupport),
+ MAKE_JNI_NATIVE_METHOD("getDirectProfilesForAttributes",
+ "(Landroid/media/AudioAttributes;Ljava/util/ArrayList;)I",
+ android_media_AudioSystem_getDirectProfilesForAttributes),
+ MAKE_JNI_NATIVE_METHOD("getSupportedMixerAttributes", "(ILjava/util/List;)I",
+ android_media_AudioSystem_getSupportedMixerAttributes),
+ MAKE_JNI_NATIVE_METHOD("setPreferredMixerAttributes",
+ "(Landroid/media/AudioAttributes;IILandroid/media/"
+ "AudioMixerAttributes;)I",
+ android_media_AudioSystem_setPreferredMixerAttributes),
+ MAKE_JNI_NATIVE_METHOD("getPreferredMixerAttributes",
+ "(Landroid/media/AudioAttributes;ILjava/util/List;)I",
+ android_media_AudioSystem_getPreferredMixerAttributes),
+ MAKE_JNI_NATIVE_METHOD("clearPreferredMixerAttributes",
+ "(Landroid/media/AudioAttributes;II)I",
+ android_media_AudioSystem_clearPreferredMixerAttributes),
+ MAKE_AUDIO_SYSTEM_METHOD(supportsBluetoothVariableLatency),
+ MAKE_AUDIO_SYSTEM_METHOD(setBluetoothVariableLatencyEnabled),
+ MAKE_AUDIO_SYSTEM_METHOD(isBluetoothVariableLatencyEnabled)};
-static const JNINativeMethod gEventHandlerMethods[] = {
- {"native_setup",
- "(Ljava/lang/Object;)V",
- (void *)android_media_AudioSystem_eventHandlerSetup},
- {"native_finalize",
- "()V",
- (void *)android_media_AudioSystem_eventHandlerFinalize},
-};
+static const JNINativeMethod gEventHandlerMethods[] =
+ {MAKE_JNI_NATIVE_METHOD("native_setup", "(Ljava/lang/Object;)V",
+ android_media_AudioSystem_eventHandlerSetup),
+ MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_finalize",
+ android_media_AudioSystem_eventHandlerFinalize)};
-static const JNINativeMethod gFrameworkCapabilities[] = {
- {"native_getMaxChannelCount", "()I", (void *)android_media_AudioSystem_getMaxChannelCount},
- {"native_getMaxSampleRate", "()I", (void *)android_media_AudioSystem_getMaxSampleRate},
- {"native_getMinSampleRate", "()I", (void *)android_media_AudioSystem_getMinSampleRate},
-};
+static const JNINativeMethod gFrameworkCapabilities[] =
+ {MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_getMaxChannelCount",
+ android_media_AudioSystem_getMaxChannelCount),
+ MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_getMaxSampleRate",
+ android_media_AudioSystem_getMaxSampleRate),
+ MAKE_JNI_NATIVE_METHOD_AUTOSIG("native_getMinSampleRate",
+ android_media_AudioSystem_getMinSampleRate)};
int register_android_media_AudioSystem(JNIEnv *env)
{
@@ -3589,7 +3459,7 @@
gClsAudioTrackRoutingProxy =
android::FindClassOrDie(env, "android/media/AudioTrackRoutingProxy");
// make sure this reference doesn't get deleted
- gClsAudioTrackRoutingProxy = (jclass)env->NewGlobalRef(gClsAudioTrackRoutingProxy);
+ gClsAudioTrackRoutingProxy = static_cast<jclass>(env->NewGlobalRef(gClsAudioTrackRoutingProxy));
gMidAudioTrackRoutingProxy_ctor =
android::GetMethodIDOrDie(env, gClsAudioTrackRoutingProxy, "<init>", "(J)V");
@@ -3600,7 +3470,8 @@
gClsAudioRecordRoutingProxy =
android::FindClassOrDie(env, "android/media/AudioRecordRoutingProxy");
// make sure this reference doesn't get deleted
- gClsAudioRecordRoutingProxy = (jclass)env->NewGlobalRef(gClsAudioRecordRoutingProxy);
+ gClsAudioRecordRoutingProxy =
+ static_cast<jclass>(env->NewGlobalRef(gClsAudioRecordRoutingProxy));
gMidAudioRecordRoutingProxy_ctor =
android::GetMethodIDOrDie(env, gClsAudioRecordRoutingProxy, "<init>", "(J)V");
diff --git a/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java b/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
index 3c47630..33e81c1 100644
--- a/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
+++ b/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
@@ -97,8 +97,7 @@
@Test
public void testComputeForPassword_metrics() {
- final PasswordMetrics metrics = PasswordMetrics.computeForPasswordOrPin(
- "6B~0z1Z3*8A".getBytes(), /* isPin */ false);
+ final PasswordMetrics metrics = metricsForPassword("6B~0z1Z3*8A");
assertEquals(11, metrics.length);
assertEquals(4, metrics.letters);
assertEquals(3, metrics.upperCase);
@@ -136,72 +135,54 @@
@Test
public void testDetermineComplexity_lowNumeric() {
- assertEquals(PASSWORD_COMPLEXITY_LOW,
- PasswordMetrics.computeForPasswordOrPin("1234".getBytes(),
- /* isPin */true).determineComplexity());
+ assertEquals(PASSWORD_COMPLEXITY_LOW, metricsForPin("1234").determineComplexity());
}
@Test
public void testDetermineComplexity_lowNumericComplex() {
- assertEquals(PASSWORD_COMPLEXITY_LOW,
- PasswordMetrics.computeForPasswordOrPin("124".getBytes(),
- /* isPin */ true).determineComplexity());
+ assertEquals(PASSWORD_COMPLEXITY_LOW, metricsForPin("124").determineComplexity());
}
@Test
public void testDetermineComplexity_lowAlphabetic() {
- assertEquals(PASSWORD_COMPLEXITY_LOW,
- PasswordMetrics.computeForPasswordOrPin("a!".getBytes(),
- /* isPin */ false).determineComplexity());
+ assertEquals(PASSWORD_COMPLEXITY_LOW, metricsForPassword("a!").determineComplexity());
}
@Test
public void testDetermineComplexity_lowAlphanumeric() {
- assertEquals(PASSWORD_COMPLEXITY_LOW,
- PasswordMetrics.computeForPasswordOrPin("a!1".getBytes(),
- /* isPin */ false).determineComplexity());
+ assertEquals(PASSWORD_COMPLEXITY_LOW, metricsForPassword("a!1").determineComplexity());
}
@Test
public void testDetermineComplexity_mediumNumericComplex() {
- assertEquals(PASSWORD_COMPLEXITY_MEDIUM,
- PasswordMetrics.computeForPasswordOrPin("1238".getBytes(),
- /* isPin */ true).determineComplexity());
+ assertEquals(PASSWORD_COMPLEXITY_MEDIUM, metricsForPin("1238").determineComplexity());
}
@Test
public void testDetermineComplexity_mediumAlphabetic() {
- assertEquals(PASSWORD_COMPLEXITY_MEDIUM,
- PasswordMetrics.computeForPasswordOrPin("ab!c".getBytes(),
- /* isPin */ false).determineComplexity());
+ assertEquals(PASSWORD_COMPLEXITY_MEDIUM, metricsForPassword("ab!c").determineComplexity());
}
@Test
public void testDetermineComplexity_mediumAlphanumeric() {
- assertEquals(PASSWORD_COMPLEXITY_MEDIUM,
- PasswordMetrics.computeForPasswordOrPin("ab!1".getBytes(),
- /* isPin */ false).determineComplexity());
+ assertEquals(PASSWORD_COMPLEXITY_MEDIUM, metricsForPassword("ab!1").determineComplexity());
}
@Test
public void testDetermineComplexity_highNumericComplex() {
- assertEquals(PASSWORD_COMPLEXITY_HIGH,
- PasswordMetrics.computeForPasswordOrPin("12389647!".getBytes(),
- /* isPin */ true).determineComplexity());
+ assertEquals(PASSWORD_COMPLEXITY_HIGH, metricsForPin("12389647!").determineComplexity());
}
@Test
public void testDetermineComplexity_highAlphabetic() {
assertEquals(PASSWORD_COMPLEXITY_HIGH,
- PasswordMetrics.computeForPasswordOrPin("alphabetic!".getBytes(),
- /* isPin */ false).determineComplexity());
+ metricsForPassword("alphabetic!").determineComplexity());
}
@Test
public void testDetermineComplexity_highAlphanumeric() {
assertEquals(PASSWORD_COMPLEXITY_HIGH,
- PasswordMetrics.computeForPasswordOrPin("alphanumeric123!".getBytes(),
- /* isPin */ false).determineComplexity());
+ metricsForPassword("alphanumeric123!").determineComplexity());
}
@Test
@@ -425,6 +406,14 @@
patternString.getBytes()));
}
+ private static PasswordMetrics metricsForPassword(String password) {
+ return PasswordMetrics.computeForCredential(LockscreenCredential.createPassword(password));
+ }
+
+ private static PasswordMetrics metricsForPin(String pin) {
+ return PasswordMetrics.computeForCredential(LockscreenCredential.createPin(pin));
+ }
+
@Test
public void testValidateCredential_pattern() {
PasswordMetrics adminMetrics = new PasswordMetrics(CREDENTIAL_TYPE_NONE);
diff --git a/core/tests/coretests/src/android/view/ViewAttachTest.java b/core/tests/coretests/src/android/view/ViewAttachTest.java
index 1a8dd99..1da724a 100644
--- a/core/tests/coretests/src/android/view/ViewAttachTest.java
+++ b/core/tests/coretests/src/android/view/ViewAttachTest.java
@@ -92,4 +92,43 @@
assertFalse(shouldDrawRoundScrollbars);
}
}
+
+ /**
+ * Make sure that on any attached view, if the view is full-screen and hosted
+ * on a round device, the round scrollbars will be displayed even if the activity
+ * window is offset.
+ *
+ * @throws Throwable
+ */
+ @UiThreadTest
+ public void testRoundScrollbarsWithMargins() throws Throwable {
+ final ViewAttachTestActivity activity = getActivity();
+ final View rootView = activity.getWindow().getDecorView();
+ final WindowManager.LayoutParams params =
+ new WindowManager.LayoutParams(
+ rootView.getWidth(),
+ rootView.getHeight(),
+ 50, /* xPosition */
+ 0, /* yPosition */
+ WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+ PixelFormat.TRANSLUCENT);
+
+ rootView.setLayoutParams(params);
+
+ // Configure margins to make sure they don't cause issues configuring rounded scrollbars.
+ final ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(1, 1);
+ lp.setMargins(1, 2, 3, 4);
+ rootView.setLayoutParams(lp);
+
+ View contentView = activity.findViewById(R.id.view_attach_view);
+ boolean shouldDrawRoundScrollbars = contentView.shouldDrawRoundScrollbar();
+
+ if (activity.getResources().getConfiguration().isScreenRound()) {
+ assertTrue(shouldDrawRoundScrollbars);
+ } else {
+ // Never draw round scrollbars on non-round devices.
+ assertFalse(shouldDrawRoundScrollbars);
+ }
+ }
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
index a45a8a1..0059577 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -98,14 +98,6 @@
mTaskFragmentOrganizer = taskFragmentOrganizer;
}
- /** Registers to listen to {@link CommonFoldingFeature} changes */
- public void addFoldingStateChangedCallback(
- java.util.function.Consumer<List<CommonFoldingFeature>> consumer) {
- synchronized (mLock) {
- mFoldingFeatureProducer.addDataChangedCallback(consumer);
- }
- }
-
/**
* Adds a listener interested in receiving updates to {@link WindowLayoutInfo}
*
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index 5e43ac2..bcfa4f3 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -64,12 +64,13 @@
void unregisterCanvasContext(CanvasContext* context);
void onContextStopped(CanvasContext* context);
+ bool areAllContextsStopped();
+
private:
friend class RenderThread;
explicit CacheManager(RenderThread& thread);
void setupCacheLimits();
- bool areAllContextsStopped();
void checkUiHidden();
void scheduleDestroyContext();
void cancelDestroyContext();
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index a5518eb..2ef7802 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -125,6 +125,7 @@
, mRenderPipeline(std::move(renderPipeline))
, mHintSessionWrapper(uiThreadId, renderThreadId) {
mRenderThread.cacheManager().registerCanvasContext(this);
+ mRenderThread.renderState().registerContextCallback(this);
rootRenderNode->makeRoot();
mRenderNodes.emplace_back(rootRenderNode);
mProfiler.setDensity(DeviceInfo::getDensity());
@@ -137,6 +138,7 @@
}
mRenderNodes.clear();
mRenderThread.cacheManager().unregisterCanvasContext(this);
+ mRenderThread.renderState().removeContextCallback(this);
}
void CanvasContext::addRenderNode(RenderNode* node, bool placeFront) {
@@ -963,6 +965,10 @@
}
}
+void CanvasContext::onContextDestroyed() {
+ destroyHardwareResources();
+}
+
DeferredLayerUpdater* CanvasContext::createTextureLayer() {
return mRenderPipeline->createTextureLayer();
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 32ac5af..3f02674 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -43,6 +43,7 @@
#include "Lighting.h"
#include "ReliableSurface.h"
#include "RenderNode.h"
+#include "renderstate/RenderState.h"
#include "renderthread/RenderTask.h"
#include "renderthread/RenderThread.h"
#include "utils/RingBuffer.h"
@@ -64,7 +65,7 @@
// This per-renderer class manages the bridge between the global EGL context
// and the render surface.
// TODO: Rename to Renderer or some other per-window, top-level manager
-class CanvasContext : public IFrameCallback {
+class CanvasContext : public IFrameCallback, public IGpuContextCallback {
public:
static CanvasContext* create(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
IContextFactory* contextFactory, pid_t uiThreadId,
@@ -154,6 +155,7 @@
void markLayerInUse(RenderNode* node);
void destroyHardwareResources();
+ void onContextDestroyed() override;
DeferredLayerUpdater* createTextureLayer();
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 81ecfe5..7ef82a7 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -307,13 +307,21 @@
int destroyed = 0;
int removeOverlays = 0;
int glesDraw = 0;
+ int vkInitialize = 0;
+ int vkDraw = 0;
+ int vkPostDraw = 0;
};
static void expectOnRenderThread(const std::string_view& function = "unknown") {
EXPECT_EQ(gettid(), TestUtils::getRenderThreadTid()) << "Called on wrong thread: " << function;
}
- static WebViewFunctorCallbacks createMockFunctor(RenderMode mode) {
+ static int createMockFunctor() {
+ const auto renderMode = WebViewFunctor_queryPlatformRenderMode();
+ return WebViewFunctor_create(nullptr, createMockFunctorCallbacks(renderMode), renderMode);
+ }
+
+ static WebViewFunctorCallbacks createMockFunctorCallbacks(RenderMode mode) {
auto callbacks = WebViewFunctorCallbacks{
.onSync =
[](int functor, void* client_data, const WebViewSyncData& data) {
@@ -345,9 +353,22 @@
sMockFunctorCounts[functor].glesDraw++;
};
break;
- default:
- ADD_FAILURE();
- return WebViewFunctorCallbacks{};
+ case RenderMode::Vulkan:
+ callbacks.vk.initialize = [](int functor, void* data,
+ const VkFunctorInitParams& params) {
+ expectOnRenderThread("initialize");
+ sMockFunctorCounts[functor].vkInitialize++;
+ };
+ callbacks.vk.draw = [](int functor, void* data, const VkFunctorDrawParams& params,
+ const WebViewOverlayData& overlayParams) {
+ expectOnRenderThread("draw");
+ sMockFunctorCounts[functor].vkDraw++;
+ };
+ callbacks.vk.postDraw = [](int functor, void* data) {
+ expectOnRenderThread("postDraw");
+ sMockFunctorCounts[functor].vkPostDraw++;
+ };
+ break;
}
return callbacks;
}
diff --git a/libs/hwui/tests/unit/CanvasContextTests.cpp b/libs/hwui/tests/unit/CanvasContextTests.cpp
index 9e376e3..47a4105 100644
--- a/libs/hwui/tests/unit/CanvasContextTests.cpp
+++ b/libs/hwui/tests/unit/CanvasContextTests.cpp
@@ -19,6 +19,7 @@
#include "AnimationContext.h"
#include "IContextFactory.h"
#include "renderthread/CanvasContext.h"
+#include "renderthread/VulkanManager.h"
#include "tests/common/TestUtils.h"
using namespace android;
@@ -42,3 +43,38 @@
canvasContext->destroy();
}
+
+RENDERTHREAD_TEST(CanvasContext, buildLayerDoesntLeak) {
+ auto node = TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
+ canvas.drawColor(0xFFFF0000, SkBlendMode::kSrc);
+ });
+ ASSERT_TRUE(node->isValid());
+ EXPECT_EQ(LayerType::None, node->stagingProperties().effectiveLayerType());
+ node->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
+
+ auto& cacheManager = renderThread.cacheManager();
+ EXPECT_TRUE(cacheManager.areAllContextsStopped());
+ ContextFactory contextFactory;
+ std::unique_ptr<CanvasContext> canvasContext(
+ CanvasContext::create(renderThread, false, node.get(), &contextFactory, 0, 0));
+ canvasContext->buildLayer(node.get());
+ EXPECT_TRUE(node->hasLayer());
+ if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
+ auto instance = VulkanManager::peekInstance();
+ if (instance) {
+ EXPECT_TRUE(instance->hasVkContext());
+ } else {
+ ADD_FAILURE() << "VulkanManager wasn't initialized to buildLayer?";
+ }
+ }
+ renderThread.destroyRenderingContext();
+ EXPECT_FALSE(node->hasLayer()) << "Node still has a layer after rendering context destroyed";
+
+ if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
+ auto instance = VulkanManager::peekInstance();
+ if (instance) {
+ ADD_FAILURE() << "VulkanManager still exists";
+ EXPECT_FALSE(instance->hasVkContext());
+ }
+ }
+}
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index 80796f4..8273524 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -231,8 +231,7 @@
}
TEST(RenderNode, releasedCallback) {
- int functor = WebViewFunctor_create(
- nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
+ int functor = TestUtils::createMockFunctor();
auto node = TestUtils::createNode(0, 0, 200, 400, [&](RenderProperties& props, Canvas& canvas) {
canvas.drawWebViewFunctor(functor);
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index f825d7c..1a1ce1e 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -48,8 +48,7 @@
SkCanvas dummyCanvas;
RenderNodeDrawable drawable(nullptr, &dummyCanvas);
skiaDL->mChildNodes.emplace_back(nullptr, &dummyCanvas);
- int functor1 = WebViewFunctor_create(
- nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
+ int functor1 = TestUtils::createMockFunctor();
GLFunctorDrawable functorDrawable{functor1, &dummyCanvas};
WebViewFunctor_release(functor1);
skiaDL->mChildFunctors.push_back(&functorDrawable);
@@ -101,8 +100,7 @@
SkCanvas dummyCanvas;
- int functor1 = WebViewFunctor_create(
- nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
+ int functor1 = TestUtils::createMockFunctor();
auto& counts = TestUtils::countsForFunctor(functor1);
skiaDL.mChildFunctors.push_back(
skiaDL.allocateDrawable<GLFunctorDrawable>(functor1, &dummyCanvas));
diff --git a/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp b/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp
index e1fb8b7..5e8f13d 100644
--- a/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp
+++ b/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp
@@ -26,9 +26,15 @@
using namespace android;
using namespace android::uirenderer;
+#define ASSUME_GLES() \
+ if (WebViewFunctor_queryPlatformRenderMode() != RenderMode::OpenGL_ES) \
+ GTEST_SKIP() << "Not in GLES, skipping test"
+
TEST(WebViewFunctor, createDestroyGLES) {
+ ASSUME_GLES();
int functor = WebViewFunctor_create(
- nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
+ nullptr, TestUtils::createMockFunctorCallbacks(RenderMode::OpenGL_ES),
+ RenderMode::OpenGL_ES);
ASSERT_NE(-1, functor);
WebViewFunctor_release(functor);
TestUtils::runOnRenderThreadUnmanaged([](renderthread::RenderThread&) {
@@ -41,8 +47,10 @@
}
TEST(WebViewFunctor, createSyncHandleGLES) {
+ ASSUME_GLES();
int functor = WebViewFunctor_create(
- nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
+ nullptr, TestUtils::createMockFunctorCallbacks(RenderMode::OpenGL_ES),
+ RenderMode::OpenGL_ES);
ASSERT_NE(-1, functor);
auto handle = WebViewFunctorManager::instance().handleFor(functor);
ASSERT_TRUE(handle);
@@ -82,8 +90,10 @@
}
TEST(WebViewFunctor, createSyncDrawGLES) {
+ ASSUME_GLES();
int functor = WebViewFunctor_create(
- nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
+ nullptr, TestUtils::createMockFunctorCallbacks(RenderMode::OpenGL_ES),
+ RenderMode::OpenGL_ES);
ASSERT_NE(-1, functor);
auto handle = WebViewFunctorManager::instance().handleFor(functor);
ASSERT_TRUE(handle);
@@ -108,9 +118,11 @@
EXPECT_EQ(1, counts.destroyed);
}
-TEST(WebViewFunctor, contextDestroyed) {
+TEST(WebViewFunctor, contextDestroyedGLES) {
+ ASSUME_GLES();
int functor = WebViewFunctor_create(
- nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
+ nullptr, TestUtils::createMockFunctorCallbacks(RenderMode::OpenGL_ES),
+ RenderMode::OpenGL_ES);
ASSERT_NE(-1, functor);
auto handle = WebViewFunctorManager::instance().handleFor(functor);
ASSERT_TRUE(handle);
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 4633a65..7be6043 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -123,6 +123,7 @@
],
static_libs: [
"SystemUISharedLib",
+ "SystemUICustomizationLib",
"SettingsLib",
"androidx.leanback_leanback",
"androidx.slice_slice-core",
diff --git a/packages/SystemUI/customization/res/values-h800dp/dimens.xml b/packages/SystemUI/customization/res/values-h800dp/dimens.xml
index 60afc8a..cb49945 100644
--- a/packages/SystemUI/customization/res/values-h800dp/dimens.xml
+++ b/packages/SystemUI/customization/res/values-h800dp/dimens.xml
@@ -17,4 +17,7 @@
<resources>
<!-- Large clock maximum font size (dp is intentional, to prevent any further scaling) -->
<dimen name="large_clock_text_size">200dp</dimen>
+
+ <!-- With the large clock, move up slightly from the center -->
+ <dimen name="keyguard_large_clock_top_margin">-112dp</dimen>
</resources>
diff --git a/packages/SystemUI/customization/res/values/dimens.xml b/packages/SystemUI/customization/res/values/dimens.xml
index ba8f284..8eb8132 100644
--- a/packages/SystemUI/customization/res/values/dimens.xml
+++ b/packages/SystemUI/customization/res/values/dimens.xml
@@ -24,4 +24,12 @@
<item name="keyguard_clock_line_spacing_scale" type="dimen" format="float">.7</item>
<!-- Burmese line spacing multiplier between hours and minutes of the keyguard clock -->
<item name="keyguard_clock_line_spacing_scale_burmese" type="dimen" format="float">1</item>
+
+ <!-- With the large clock, move up slightly from the center -->
+ <dimen name="keyguard_large_clock_top_margin">-60dp</dimen>
+
+ <!-- additional offset for clock switch area items -->
+ <dimen name="small_clock_height">114dp</dimen>
+ <dimen name="small_clock_padding_top">28dp</dimen>
+ <dimen name="clock_padding_start">28dp</dimen>
</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 39dd90e..8c81733 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -95,9 +95,6 @@
<dimen name="num_pad_key_margin_end">12dp</dimen>
<!-- additional offset for clock switch area items -->
- <dimen name="small_clock_height">114dp</dimen>
- <dimen name="small_clock_padding_top">28dp</dimen>
- <dimen name="clock_padding_start">28dp</dimen>
<dimen name="below_clock_padding_start">32dp</dimen>
<dimen name="below_clock_padding_end">16dp</dimen>
<dimen name="below_clock_padding_start_icons">28dp</dimen>
diff --git a/packages/SystemUI/res/color/brightness_slider_overlay_color.xml b/packages/SystemUI/res/color/brightness_slider_overlay_color.xml
new file mode 100644
index 0000000..a8abd79
--- /dev/null
+++ b/packages/SystemUI/res/color/brightness_slider_overlay_color.xml
@@ -0,0 +1,22 @@
+<?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.
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true" android:color="?attr/onShadeActive" android:alpha="0.12" />
+ <item android:state_hovered="true" android:color="?attr/onShadeActive" android:alpha="0.09" />
+ <item android:color="@color/transparent" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
index 2ea90c7..a9e7adf 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
@@ -26,6 +26,13 @@
<corners android:radius="@dimen/rounded_slider_corner_radius"/>
</shape>
</item>
+ <item>
+ <shape>
+ <corners android:radius="@dimen/rounded_slider_corner_radius" />
+ <size android:height="@dimen/rounded_slider_height" />
+ <solid android:color="@color/brightness_slider_overlay_color" />
+ </shape>
+ </item>
<item
android:id="@+id/slider_icon"
android:gravity="center_vertical|right"
diff --git a/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml b/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml
index 87b5a4c..32dc4b3 100644
--- a/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml
+++ b/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml
@@ -20,7 +20,7 @@
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/materialColorSurfaceContainerHigh"/>
<size
android:width="@dimen/keyguard_affordance_fixed_width"
android:height="@dimen/keyguard_affordance_fixed_height"/>
diff --git a/packages/SystemUI/res/layout/biometric_prompt_layout.xml b/packages/SystemUI/res/layout/biometric_prompt_layout.xml
index 05ff1b1..8eb62ec 100644
--- a/packages/SystemUI/res/layout/biometric_prompt_layout.xml
+++ b/packages/SystemUI/res/layout/biometric_prompt_layout.xml
@@ -39,6 +39,7 @@
android:singleLine="true"
android:marqueeRepeatLimit="1"
android:ellipsize="marquee"
+ android:importantForAccessibility="no"
style="@style/TextAppearance.AuthCredential.Subtitle"/>
<TextView
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index e95c6a7..91550b3 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -34,5 +34,6 @@
android:paddingEnd="0dp"
android:progressDrawable="@drawable/brightness_progress_drawable"
android:splitTrack="false"
+ android:clickable="true"
/>
</com.android.systemui.settings.brightness.BrightnessSliderView>
diff --git a/packages/SystemUI/res/values-h800dp/dimens.xml b/packages/SystemUI/res/values-h800dp/dimens.xml
index 3a71994..829ef98 100644
--- a/packages/SystemUI/res/values-h800dp/dimens.xml
+++ b/packages/SystemUI/res/values-h800dp/dimens.xml
@@ -15,9 +15,6 @@
-->
<resources>
- <!-- With the large clock, move up slightly from the center -->
- <dimen name="keyguard_large_clock_top_margin">-112dp</dimen>
-
<!-- Margin above the ambient indication container -->
<dimen name="ambient_indication_container_margin_top">20dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 9aef9ed..47cd1e7 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -747,8 +747,6 @@
<dimen name="keyguard_clock_switch_y_shift">14dp</dimen>
<!-- When large clock is showing, offset the smartspace by this amount -->
<dimen name="keyguard_smartspace_top_offset">12dp</dimen>
- <!-- With the large clock, move up slightly from the center -->
- <dimen name="keyguard_large_clock_top_margin">-60dp</dimen>
<dimen name="notification_scrim_corner_radius">32dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricModality.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/BiometricModality.kt
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricModality.kt
rename to packages/SystemUI/src/com/android/systemui/biometrics/shared/model/BiometricModality.kt
index 3197c09..fb580ca 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricModality.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/BiometricModality.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.biometrics.domain.model
+package com.android.systemui.biometrics.shared.model
import android.hardware.biometrics.BiometricAuthenticator
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
index 64df6a0..e5a4d1a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
@@ -46,9 +46,9 @@
import com.android.systemui.biometrics.AuthPanelController
import com.android.systemui.biometrics.Utils
import com.android.systemui.biometrics.domain.model.BiometricModalities
-import com.android.systemui.biometrics.domain.model.BiometricModality
-import com.android.systemui.biometrics.domain.model.asBiometricModality
+import com.android.systemui.biometrics.shared.model.BiometricModality
import com.android.systemui.biometrics.shared.model.PromptKind
+import com.android.systemui.biometrics.shared.model.asBiometricModality
import com.android.systemui.biometrics.ui.BiometricPromptLayout
import com.android.systemui.biometrics.ui.viewmodel.FingerprintStartMode
import com.android.systemui.biometrics.ui.viewmodel.PromptMessage
@@ -396,7 +396,6 @@
private var lifecycleScope: CoroutineScope? = null
private var modalities: BiometricModalities = BiometricModalities()
- private var faceFailedAtLeastOnce = false
private var legacyCallback: Callback? = null
override var legacyIconController: AuthIconController? = null
@@ -476,19 +475,15 @@
viewModel.ensureFingerprintHasStarted(isDelayed = true)
applicationScope.launch {
- val suppress =
- modalities.hasFaceAndFingerprint &&
- (failedModality == BiometricModality.Face) &&
- faceFailedAtLeastOnce
- if (failedModality == BiometricModality.Face) {
- faceFailedAtLeastOnce = true
- }
-
viewModel.showTemporaryError(
failureReason,
messageAfterError = modalities.asDefaultHelpMessage(applicationContext),
authenticateAfterError = modalities.hasFingerprint,
- suppressIfErrorShowing = suppress,
+ suppressIf = { currentMessage ->
+ modalities.hasFaceAndFingerprint &&
+ failedModality == BiometricModality.Face &&
+ currentMessage.isError
+ },
failedModality = failedModality,
)
}
@@ -501,11 +496,10 @@
}
applicationScope.launch {
- val suppress =
- modalities.hasFaceAndFingerprint && (errorModality == BiometricModality.Face)
viewModel.showTemporaryError(
error,
- suppressIfErrorShowing = suppress,
+ messageAfterError = modalities.asDefaultHelpMessage(applicationContext),
+ authenticateAfterError = modalities.hasFingerprint,
)
delay(BiometricPrompt.HIDE_DIALOG_DELAY.toLong())
legacyCallback?.onAction(Callback.ACTION_ERROR)
@@ -522,6 +516,7 @@
viewModel.showTemporaryError(
help,
messageAfterError = modalities.asDefaultHelpMessage(applicationContext),
+ authenticateAfterError = modalities.hasFingerprint,
hapticFeedback = false,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthState.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthState.kt
index 444082c..2f9557f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthState.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthState.kt
@@ -16,7 +16,7 @@
package com.android.systemui.biometrics.ui.viewmodel
-import com.android.systemui.biometrics.domain.model.BiometricModality
+import com.android.systemui.biometrics.shared.model.BiometricModality
/**
* The authenticated state with the [authenticatedModality] (when [isAuthenticated]) with an
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptMessage.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptMessage.kt
index 219da71..50f4911 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptMessage.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptMessage.kt
@@ -33,9 +33,9 @@
else -> ""
}
- /** If this is an [Error] or [Help] message. */
- val isErrorOrHelp: Boolean
- get() = this is Error || this is Help
+ /** If this is an [Error]. */
+ val isError: Boolean
+ get() = this is Error
/** An error message. */
data class Error(val errorMessage: String) : PromptMessage
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index d63bf57..8a2e405 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -20,7 +20,7 @@
import com.android.systemui.biometrics.AuthBiometricView
import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor
import com.android.systemui.biometrics.domain.model.BiometricModalities
-import com.android.systemui.biometrics.domain.model.BiometricModality
+import com.android.systemui.biometrics.shared.model.BiometricModality
import com.android.systemui.biometrics.shared.model.PromptKind
import com.android.systemui.statusbar.VibratorHelper
import javax.inject.Inject
@@ -210,35 +210,33 @@
* Show a temporary error [message] associated with an optional [failedModality] and play
* [hapticFeedback].
*
- * An optional [messageAfterError] will be shown via [showAuthenticating] when
- * [authenticateAfterError] is set (or via [showHelp] when not set) after the error is
- * dismissed.
+ * The [messageAfterError] will be shown via [showAuthenticating] when [authenticateAfterError]
+ * is set (or via [showHelp] when not set) after the error is dismissed.
*
- * The error is ignored if the user has already authenticated or if [suppressIfErrorShowing] is
- * set and an error message is already showing.
+ * The error is ignored if the user has already authenticated or if [suppressIf] is true given
+ * the currently showing [PromptMessage].
*/
suspend fun showTemporaryError(
message: String,
+ messageAfterError: String,
+ authenticateAfterError: Boolean,
+ suppressIf: (PromptMessage) -> Boolean = { false },
hapticFeedback: Boolean = true,
- messageAfterError: String = "",
- authenticateAfterError: Boolean = false,
- suppressIfErrorShowing: Boolean = false,
failedModality: BiometricModality = BiometricModality.None,
) = coroutineScope {
if (_isAuthenticated.value.isAuthenticated) {
return@coroutineScope
}
- if (_message.value.isErrorOrHelp && suppressIfErrorShowing) {
- if (_isAuthenticated.value.isNotAuthenticated) {
- _canTryAgainNow.value = supportsRetry(failedModality)
- }
+
+ _canTryAgainNow.value = supportsRetry(failedModality)
+
+ if (suppressIf(_message.value)) {
return@coroutineScope
}
_isAuthenticating.value = false
_isAuthenticated.value = PromptAuthState(false)
_forceMediumSize.value = true
- _canTryAgainNow.value = supportsRetry(failedModality)
_message.value = PromptMessage.Error(message)
_legacyState.value = AuthBiometricView.STATE_ERROR
@@ -374,7 +372,9 @@
AuthBiometricView.STATE_AUTHENTICATED
}
- vibrator.success(modality)
+ if (!needsUserConfirmation) {
+ vibrator.success(modality)
+ }
messageJob?.cancel()
messageJob = null
@@ -420,6 +420,8 @@
_message.value = PromptMessage.Empty
_legacyState.value = AuthBiometricView.STATE_AUTHENTICATED
+ vibrator.success(authState.authenticatedModality)
+
messageJob?.cancel()
messageJob = null
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index 2513c81..62a484d 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -25,6 +25,8 @@
import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
import com.android.systemui.bouncer.data.repository.BouncerRepository
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
@@ -38,9 +40,6 @@
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
@@ -53,6 +52,7 @@
private val repository: BouncerRepository,
private val authenticationInteractor: AuthenticationInteractor,
private val sceneInteractor: SceneInteractor,
+ featureFlags: FeatureFlags,
@Assisted private val containerName: String,
) {
@@ -95,36 +95,14 @@
val isPatternVisible: StateFlow<Boolean> = authenticationInteractor.isPatternVisible
init {
- // UNLOCKING SHOWS Gone.
- //
- // Move to the gone scene if the device becomes unlocked while on the bouncer scene.
- applicationScope.launch {
- sceneInteractor
- .currentScene(containerName)
- .flatMapLatest { currentScene ->
- if (currentScene.key == SceneKey.Bouncer) {
- authenticationInteractor.isUnlocked
- } else {
- flowOf(false)
+ if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ // Clear the message if moved from throttling to no-longer throttling.
+ applicationScope.launch {
+ isThrottled.pairwise().collect { (wasThrottled, currentlyThrottled) ->
+ if (wasThrottled && !currentlyThrottled) {
+ clearMessage()
}
}
- .distinctUntilChanged()
- .collect { isUnlocked ->
- if (isUnlocked) {
- sceneInteractor.setCurrentScene(
- containerName = containerName,
- scene = SceneModel(SceneKey.Gone),
- )
- }
- }
- }
-
- // Clear the message if moved from throttling to no-longer throttling.
- applicationScope.launch {
- isThrottled.pairwise().collect { (wasThrottled, currentlyThrottled) ->
- if (wasThrottled && !currentlyThrottled) {
- clearMessage()
- }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
index 5425022..a4ef5ce 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
@@ -23,6 +23,8 @@
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.util.kotlin.pairwise
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@@ -49,6 +51,7 @@
@Application private val applicationContext: Context,
@Application private val applicationScope: CoroutineScope,
interactorFactory: BouncerInteractor.Factory,
+ featureFlags: FeatureFlags,
@Assisted containerName: String,
) {
private val interactor: BouncerInteractor = interactorFactory.create(containerName)
@@ -102,15 +105,48 @@
)
init {
- applicationScope.launch {
- _authMethod.subscriptionCount
- .pairwise()
- .map { (previousCount, currentCount) -> currentCount > previousCount }
- .collect { subscriberAdded ->
- if (subscriberAdded) {
- reloadAuthMethod()
+ if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
+ applicationScope.launch {
+ interactor.isThrottled
+ .map { isThrottled ->
+ if (isThrottled) {
+ when (interactor.getAuthenticationMethod()) {
+ is AuthenticationMethodModel.Pin ->
+ R.string.kg_too_many_failed_pin_attempts_dialog_message
+ is AuthenticationMethodModel.Password ->
+ R.string.kg_too_many_failed_password_attempts_dialog_message
+ is AuthenticationMethodModel.Pattern ->
+ R.string.kg_too_many_failed_pattern_attempts_dialog_message
+ else -> null
+ }?.let { stringResourceId ->
+ applicationContext.getString(
+ stringResourceId,
+ interactor.throttling.value.failedAttemptCount,
+ ceil(interactor.throttling.value.remainingMs / 1000f).toInt(),
+ )
+ }
+ } else {
+ null
+ }
}
- }
+ .distinctUntilChanged()
+ .collect { dialogMessageOrNull ->
+ if (dialogMessageOrNull != null) {
+ _throttlingDialogMessage.value = dialogMessageOrNull
+ }
+ }
+ }
+
+ applicationScope.launch {
+ _authMethod.subscriptionCount
+ .pairwise()
+ .map { (previousCount, currentCount) -> currentCount > previousCount }
+ .collect { subscriberAdded ->
+ if (subscriberAdded) {
+ reloadAuthMethod()
+ }
+ }
+ }
}
}
@@ -144,39 +180,6 @@
*/
val throttlingDialogMessage: StateFlow<String?> = _throttlingDialogMessage.asStateFlow()
- init {
- applicationScope.launch {
- interactor.isThrottled
- .map { isThrottled ->
- if (isThrottled) {
- when (interactor.getAuthenticationMethod()) {
- is AuthenticationMethodModel.Pin ->
- R.string.kg_too_many_failed_pin_attempts_dialog_message
- is AuthenticationMethodModel.Password ->
- R.string.kg_too_many_failed_password_attempts_dialog_message
- is AuthenticationMethodModel.Pattern ->
- R.string.kg_too_many_failed_pattern_attempts_dialog_message
- else -> null
- }?.let { stringResourceId ->
- applicationContext.getString(
- stringResourceId,
- interactor.throttling.value.failedAttemptCount,
- ceil(interactor.throttling.value.remainingMs / 1000f).toInt(),
- )
- }
- } else {
- null
- }
- }
- .distinctUntilChanged()
- .collect { dialogMessageOrNull ->
- if (dialogMessageOrNull != null) {
- _throttlingDialogMessage.value = dialogMessageOrNull
- }
- }
- }
- }
-
/** Notifies that the emergency services button was clicked. */
fun onEmergencyServicesButtonClicked() {
// TODO(b/280877228): implement this
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/PackageUpdateMonitor.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/PackageUpdateMonitor.kt
index 1973b62..840225e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/PackageUpdateMonitor.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/PackageUpdateMonitor.kt
@@ -52,7 +52,7 @@
/** Start monitoring for package updates. No-op if already monitoring. */
fun startMonitoring() {
if (monitoring.compareAndSet(/* expected */ false, /* new */ true)) {
- register(context, user, false, bgHandler)
+ register(context, user, bgHandler)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
index 5493cea..94b2ab1 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSysUIComponent.java
@@ -19,6 +19,7 @@
import com.android.systemui.globalactions.ShutdownUiModule;
import com.android.systemui.keyguard.CustomizationProvider;
import com.android.systemui.scene.startable.SceneContainerStartableModule;
+import com.android.systemui.shade.ShadeModule;
import com.android.systemui.statusbar.NotificationInsetsModule;
import com.android.systemui.statusbar.QsFrameTranslateModule;
@@ -33,6 +34,7 @@
DependencyProvider.class,
NotificationInsetsModule.class,
QsFrameTranslateModule.class,
+ ShadeModule.class,
ShutdownUiModule.class,
SceneContainerStartableModule.class,
SystemUIBinder.class,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index eef8508..18b5612 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -81,7 +81,6 @@
import com.android.systemui.security.data.repository.SecurityRepositoryModule;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.shade.ShadeController;
-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;
@@ -198,7 +197,6 @@
SecurityRepositoryModule.class,
ScreenRecordModule.class,
SettingsUtilModule.class,
- ShadeModule.class,
SmartRepliesInflationModule.class,
SmartspaceModule.class,
StatusBarPipelineModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 45a8f13..a5a7995 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -91,6 +91,11 @@
val NOTIFICATION_SHELF_REFACTOR =
unreleasedFlag(271161129, "notification_shelf_refactor", teamfood = true)
+ // TODO(b/290787599): Tracking Bug
+ @JvmField
+ val NOTIFICATION_ICON_CONTAINER_REFACTOR =
+ unreleasedFlag(278765923, "notification_icon_container_refactor")
+
// TODO(b/288326013): Tracking Bug
@JvmField
val NOTIFICATION_ASYNC_HYBRID_VIEW_INFLATION =
@@ -258,6 +263,16 @@
@JvmField
val MIGRATE_INDICATION_AREA = unreleasedFlag(236, "migrate_indication_area", teamfood = true)
+ /**
+ * Migrate the bottom area to the new keyguard root view.
+ * Because there is no such thing as a "bottom area" after this, this also breaks it up into
+ * many smaller, modular pieces.
+ */
+ // TODO(b/290652751): Tracking bug.
+ @JvmField
+ val MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA =
+ unreleasedFlag(290652751, "migrate_split_keyguard_bottom_area")
+
/** Whether to listen for fingerprint authentication over keyguard occluding activities. */
// TODO(b/283260512): Tracking bug.
@JvmField
@@ -277,6 +292,10 @@
@JvmField
val MIGRATE_LOCK_ICON = unreleasedFlag(240, "migrate_lock_icon")
+ // TODO(b/288276738): Tracking bug.
+ @JvmField
+ val WIDGET_ON_KEYGUARD = unreleasedFlag(241, "widget_on_keyguard")
+
// 300 - power menu
// TODO(b/254512600): Tracking Bug
@JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite")
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractor.kt
index c8f7efb..1c200b0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractor.kt
@@ -20,20 +20,14 @@
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.scene.domain.interactor.SceneInteractor
-import com.android.systemui.scene.shared.model.SceneKey
-import com.android.systemui.scene.shared.model.SceneModel
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.launch
/** Hosts business and application state accessing logic for the lockscreen scene. */
class LockscreenSceneInteractor
@@ -42,7 +36,6 @@
@Application applicationScope: CoroutineScope,
private val authenticationInteractor: AuthenticationInteractor,
bouncerInteractorFactory: BouncerInteractor.Factory,
- private val sceneInteractor: SceneInteractor,
@Assisted private val containerName: String,
) {
private val bouncerInteractor: BouncerInteractor =
@@ -72,46 +65,6 @@
initialValue = false,
)
- init {
- // LOCKING SHOWS Lockscreen.
- //
- // Move to the lockscreen scene if the device becomes locked while in any scene.
- applicationScope.launch {
- authenticationInteractor.isUnlocked
- .map { !it }
- .distinctUntilChanged()
- .collect { isLocked ->
- if (isLocked) {
- sceneInteractor.setCurrentScene(
- containerName = containerName,
- scene = SceneModel(SceneKey.Lockscreen),
- )
- }
- }
- }
-
- // BYPASS UNLOCK.
- //
- // Moves to the gone scene if bypass is enabled and the device becomes unlocked while in the
- // lockscreen scene.
- applicationScope.launch {
- combine(
- authenticationInteractor.isBypassEnabled,
- authenticationInteractor.isUnlocked,
- sceneInteractor.currentScene(containerName),
- ::Triple,
- )
- .collect { (isBypassEnabled, isUnlocked, currentScene) ->
- if (isBypassEnabled && isUnlocked && currentScene.key == SceneKey.Lockscreen) {
- sceneInteractor.setCurrentScene(
- containerName = containerName,
- scene = SceneModel(SceneKey.Gone),
- )
- }
- }
- }
- }
-
/** Attempts to dismiss the lockscreen. This will cause the bouncer to show, if needed. */
fun dismissLockscreen() {
bouncerInteractor.showOrUnlockDevice(containerName = containerName)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
index 7d14198..db84268 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
@@ -343,9 +343,9 @@
Utils.getColorAttrDefaultColor(
view.context,
if (viewModel.isActivated) {
- com.android.internal.R.attr.textColorPrimaryInverse
+ com.android.internal.R.attr.materialColorOnPrimaryFixed
} else {
- com.android.internal.R.attr.textColorPrimary
+ com.android.internal.R.attr.materialColorOnSurface
},
)
)
@@ -355,9 +355,9 @@
Utils.getColorAttr(
view.context,
if (viewModel.isActivated) {
- com.android.internal.R.attr.colorAccentPrimary
+ com.android.internal.R.attr.materialColorPrimaryFixed
} else {
- com.android.internal.R.attr.colorSurface
+ com.android.internal.R.attr.materialColorSurfaceContainerHigh
}
)
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartable.kt
index 9140019..59f82f0 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartable.kt
@@ -17,6 +17,7 @@
package com.android.systemui.scene.domain.startable
import com.android.systemui.CoreStartable
+import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.flags.FeatureFlags
@@ -24,9 +25,11 @@
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.SceneContainerNames
import com.android.systemui.scene.shared.model.SceneKey
+import com.android.systemui.scene.shared.model.SceneModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
@@ -41,17 +44,19 @@
constructor(
@Application private val applicationScope: CoroutineScope,
private val sceneInteractor: SceneInteractor,
+ private val authenticationInteractor: AuthenticationInteractor,
private val featureFlags: FeatureFlags,
) : CoreStartable {
override fun start() {
if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) {
- keepVisibilityUpdated()
+ hydrateVisibility()
+ automaticallySwitchScenes()
}
}
- /** Drives visibility of the scene container. */
- private fun keepVisibilityUpdated() {
+ /** Updates the visibility of the scene container based on the current scene. */
+ private fun hydrateVisibility() {
applicationScope.launch {
sceneInteractor
.currentScene(CONTAINER_NAME)
@@ -63,6 +68,48 @@
}
}
+ /** Switches between scenes based on ever-changing application state. */
+ private fun automaticallySwitchScenes() {
+ applicationScope.launch {
+ authenticationInteractor.isUnlocked
+ .map { isUnlocked ->
+ val currentSceneKey = sceneInteractor.currentScene(CONTAINER_NAME).value.key
+ val isBypassEnabled = authenticationInteractor.isBypassEnabled.value
+ when {
+ isUnlocked ->
+ when (currentSceneKey) {
+ // When the device becomes unlocked in Bouncer, go to the Gone.
+ is SceneKey.Bouncer -> SceneKey.Gone
+ // When the device becomes unlocked in Lockscreen, go to Gone if
+ // bypass is enabled.
+ is SceneKey.Lockscreen -> SceneKey.Gone.takeIf { isBypassEnabled }
+ // We got unlocked while on a scene that's not Lockscreen or
+ // Bouncer, no need to change scenes.
+ else -> null
+ }
+ // When the device becomes locked, to Lockscreen.
+ !isUnlocked ->
+ when (currentSceneKey) {
+ // Already on lockscreen or bouncer, no need to change scenes.
+ is SceneKey.Lockscreen,
+ is SceneKey.Bouncer -> null
+ // We got locked while on a scene that's not Lockscreen or Bouncer,
+ // go to Lockscreen.
+ else -> SceneKey.Lockscreen
+ }
+ else -> null
+ }
+ }
+ .filterNotNull()
+ .collect { targetSceneKey ->
+ sceneInteractor.setCurrentScene(
+ containerName = CONTAINER_NAME,
+ scene = SceneModel(targetSceneKey),
+ )
+ }
+ }
+ }
+
companion object {
private const val CONTAINER_NAME = SceneContainerNames.SYSTEM_UI_DEFAULT
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
index 5199bd4..182e456 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
@@ -18,6 +18,7 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static android.view.WindowManagerPolicyConstants.EXTRA_FROM_BRIGHTNESS_KEY;
import android.app.Activity;
import android.graphics.Rect;
@@ -29,8 +30,10 @@
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
import android.widget.FrameLayout;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
@@ -38,34 +41,42 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+import com.android.systemui.util.concurrency.DelayableExecutor;
import java.util.List;
-import java.util.concurrent.Executor;
import javax.inject.Inject;
/** A dialog that provides controls for adjusting the screen brightness. */
public class BrightnessDialog extends Activity {
+ @VisibleForTesting
+ static final int DIALOG_TIMEOUT_MILLIS = 3000;
+
private BrightnessController mBrightnessController;
private final BrightnessSliderController.Factory mToggleSliderFactory;
private final UserTracker mUserTracker;
private final DisplayTracker mDisplayTracker;
- private final Executor mMainExecutor;
+ private final DelayableExecutor mMainExecutor;
private final Handler mBackgroundHandler;
+ private final AccessibilityManagerWrapper mAccessibilityMgr;
+ private Runnable mCancelTimeoutRunnable;
@Inject
public BrightnessDialog(
UserTracker userTracker,
DisplayTracker displayTracker,
BrightnessSliderController.Factory factory,
- @Main Executor mainExecutor,
- @Background Handler bgHandler) {
+ @Main DelayableExecutor mainExecutor,
+ @Background Handler bgHandler,
+ AccessibilityManagerWrapper accessibilityMgr) {
mUserTracker = userTracker;
mDisplayTracker = displayTracker;
mToggleSliderFactory = factory;
mMainExecutor = mainExecutor;
mBackgroundHandler = bgHandler;
+ mAccessibilityMgr = accessibilityMgr;
}
@@ -122,6 +133,14 @@
}
@Override
+ protected void onResume() {
+ super.onResume();
+ if (triggeredByBrightnessKey()) {
+ scheduleTimeout();
+ }
+ }
+
+ @Override
protected void onPause() {
super.onPause();
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
@@ -139,9 +158,25 @@
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_VOLUME_UP
|| keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
+ if (mCancelTimeoutRunnable != null) {
+ mCancelTimeoutRunnable.run();
+ }
finish();
}
return super.onKeyDown(keyCode, event);
}
+
+ private boolean triggeredByBrightnessKey() {
+ return getIntent().getBooleanExtra(EXTRA_FROM_BRIGHTNESS_KEY, false);
+ }
+
+ private void scheduleTimeout() {
+ if (mCancelTimeoutRunnable != null) {
+ mCancelTimeoutRunnable.run();
+ }
+ final int timeout = mAccessibilityMgr.getRecommendedTimeoutMillis(DIALOG_TIMEOUT_MILLIS,
+ AccessibilityManager.FLAG_CONTENT_CONTROLS);
+ mCancelTimeoutRunnable = mMainExecutor.executeDelayed(this::finish, timeout);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java
index ebb9888..02f337a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeController.java
@@ -18,6 +18,7 @@
import android.view.MotionEvent;
+import com.android.systemui.CoreStartable;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.StatusBarState;
@@ -31,7 +32,7 @@
* these are coordinated with {@link StatusBarKeyguardViewManager} via
* {@link com.android.systemui.keyguard.KeyguardViewMediator} and others.
*/
-public interface ShadeController {
+public interface ShadeController extends CoreStartable {
/** Make our window larger and the shade expanded */
void instantExpandShade();
@@ -164,17 +165,14 @@
void onLaunchAnimationEnd(boolean launchIsFullScreen);
/** Sets the listener for when the visibility of the shade changes. */
- default void setVisibilityListener(ShadeVisibilityListener listener) {};
+ default void setVisibilityListener(ShadeVisibilityListener listener) {}
/** */
- default void setNotificationPresenter(NotificationPresenter presenter) {};
+ default void setNotificationPresenter(NotificationPresenter presenter) {}
/** */
default void setNotificationShadeWindowViewController(
- NotificationShadeWindowViewController notificationShadeWindowViewController) {};
-
- /** */
- default void setShadeViewController(ShadeViewController shadeViewController) {};
+ NotificationShadeWindowViewController notificationShadeWindowViewController) {}
/** Listens for shade visibility changes. */
interface ShadeVisibilityListener {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerEmptyImpl.kt
index 4d05007..5f95bca 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerEmptyImpl.kt
@@ -1,3 +1,19 @@
+/*
+ * 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
import android.view.MotionEvent
@@ -7,6 +23,7 @@
/** Empty implementation of ShadeController for variants of Android without shades. */
@SysUISingleton
open class ShadeControllerEmptyImpl @Inject constructor() : ShadeController {
+ override fun start() {}
override fun instantExpandShade() {}
override fun instantCollapseShade() {}
override fun animateCollapseShade(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
index af74a8d..22c63817 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
@@ -63,6 +63,7 @@
private final StatusBarWindowController mStatusBarWindowController;
private final DeviceProvisionedController mDeviceProvisionedController;
+ private final Lazy<ShadeViewController> mShadeViewControllerLazy;
private final Lazy<AssistManager> mAssistManagerLazy;
private final Lazy<NotificationGutsManager> mGutsManager;
@@ -70,8 +71,6 @@
private boolean mExpandedVisible;
- // TODO(b/237661616): Rename this variable to mShadeViewController.
- private ShadeViewController mNotificationPanelViewController;
private NotificationPresenter mPresenter;
private NotificationShadeWindowViewController mNotificationShadeWindowViewController;
private ShadeVisibilityListener mShadeVisibilityListener;
@@ -87,11 +86,13 @@
DeviceProvisionedController deviceProvisionedController,
NotificationShadeWindowController notificationShadeWindowController,
WindowManager windowManager,
+ Lazy<ShadeViewController> shadeViewControllerLazy,
Lazy<AssistManager> assistManagerLazy,
Lazy<NotificationGutsManager> gutsManager
) {
mCommandQueue = commandQueue;
mMainExecutor = mainExecutor;
+ mShadeViewControllerLazy = shadeViewControllerLazy;
mStatusBarStateController = statusBarStateController;
mStatusBarWindowController = statusBarWindowController;
mDeviceProvisionedController = deviceProvisionedController;
@@ -107,7 +108,7 @@
public void instantExpandShade() {
// Make our window larger and the panel expanded.
makeExpandedVisible(true /* force */);
- mNotificationPanelViewController.expand(false /* animate */);
+ getShadeViewController().expand(false /* animate */);
mCommandQueue.recomputeDisableFlags(mDisplayId, false /* animate */);
}
@@ -123,13 +124,13 @@
"animateCollapse(): mExpandedVisible=" + mExpandedVisible + "flags=" + flags);
}
if (getNotificationShadeWindowView() != null
- && mNotificationPanelViewController.canBeCollapsed()
+ && getShadeViewController().canBeCollapsed()
&& (flags & CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL) == 0) {
// release focus immediately to kick off focus change transition
mNotificationShadeWindowController.setNotificationShadeFocusable(false);
mNotificationShadeWindowViewController.cancelExpandHelper();
- mNotificationPanelViewController.collapse(true, delayed, speedUpFactor);
+ getShadeViewController().collapse(true, delayed, speedUpFactor);
}
}
@@ -138,7 +139,7 @@
if (!mCommandQueue.panelsEnabled()) {
return;
}
- mNotificationPanelViewController.expandToNotifications();
+ getShadeViewController().expandToNotifications();
}
@Override
@@ -149,12 +150,12 @@
// Settings are not available in setup
if (!mDeviceProvisionedController.isCurrentUserSetup()) return;
- mNotificationPanelViewController.expandToQs();
+ getShadeViewController().expandToQs();
}
@Override
public boolean closeShadeIfOpen() {
- if (!mNotificationPanelViewController.isFullyCollapsed()) {
+ if (!getShadeViewController().isFullyCollapsed()) {
mCommandQueue.animateCollapsePanels(
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
notifyVisibilityChanged(false);
@@ -170,12 +171,12 @@
@Override
public boolean isShadeFullyOpen() {
- return mNotificationPanelViewController.isShadeFullyExpanded();
+ return getShadeViewController().isShadeFullyExpanded();
}
@Override
public boolean isExpandingOrCollapsing() {
- return mNotificationPanelViewController.isExpandingOrCollapsing();
+ return getShadeViewController().isExpandingOrCollapsing();
}
@Override
public void postAnimateCollapseShade() {
@@ -194,13 +195,13 @@
@Override
public void postOnShadeExpanded(Runnable executable) {
- mNotificationPanelViewController.addOnGlobalLayoutListener(
+ getShadeViewController().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (getNotificationShadeWindowView().isVisibleToUser()) {
- mNotificationPanelViewController.removeOnGlobalLayoutListener(this);
- mNotificationPanelViewController.postToView(executable);
+ getShadeViewController().removeOnGlobalLayoutListener(this);
+ getShadeViewController().postToView(executable);
}
}
});
@@ -224,7 +225,7 @@
@Override
public boolean collapseShade() {
- if (!mNotificationPanelViewController.isFullyCollapsed()) {
+ if (!getShadeViewController().isFullyCollapsed()) {
// close the shade if it was open
animateCollapseShadeForcedDelayed();
notifyVisibilityChanged(false);
@@ -252,10 +253,10 @@
@Override
public void cancelExpansionAndCollapseShade() {
- if (mNotificationPanelViewController.isTracking()) {
+ if (getShadeViewController().isTracking()) {
mNotificationShadeWindowViewController.cancelCurrentTouch();
}
- if (mNotificationPanelViewController.isPanelExpanded()
+ if (getShadeViewController().isPanelExpanded()
&& mStatusBarStateController.getState() == StatusBarState.SHADE) {
animateCollapseShade();
}
@@ -311,7 +312,7 @@
@Override
public void instantCollapseShade() {
- mNotificationPanelViewController.instantCollapse();
+ getShadeViewController().instantCollapse();
runPostCollapseRunnables();
}
@@ -342,7 +343,7 @@
}
// Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
- mNotificationPanelViewController.collapse(false, false, 1.0f);
+ getShadeViewController().collapse(false, false, 1.0f);
mExpandedVisible = false;
notifyVisibilityChanged(false);
@@ -364,7 +365,7 @@
notifyExpandedVisibleChanged(false);
mCommandQueue.recomputeDisableFlags(
mDisplayId,
- mNotificationPanelViewController.shouldHideStatusBarIconsWhenExpanded());
+ getShadeViewController().shouldHideStatusBarIconsWhenExpanded());
// Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
// the bouncer appear animation.
@@ -406,11 +407,14 @@
return mNotificationShadeWindowViewController.getView();
}
+ private ShadeViewController getShadeViewController() {
+ return mShadeViewControllerLazy.get();
+ }
+
@Override
- public void setShadeViewController(ShadeViewController shadeViewController) {
- mNotificationPanelViewController = shadeViewController;
- mNotificationPanelViewController.setTrackingStartedListener(this::runPostCollapseRunnables);
- mNotificationPanelViewController.setOpenCloseListener(
+ public void start() {
+ getShadeViewController().setTrackingStartedListener(this::runPostCollapseRunnables);
+ getShadeViewController().setOpenCloseListener(
new OpenCloseListener() {
@Override
public void onClosingFinished() {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
index 2c560c9..e2e633a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
@@ -59,7 +59,7 @@
import javax.inject.Provider
/** Module for classes related to the notification shade. */
-@Module
+@Module(includes = [StartShadeModule::class])
abstract class ShadeModule {
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/shade/StartShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/StartShadeModule.kt
new file mode 100644
index 0000000..c50693c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/StartShadeModule.kt
@@ -0,0 +1,31 @@
+/*
+ * 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
+
+import com.android.systemui.CoreStartable
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+
+@Module
+internal abstract class StartShadeModule {
+ @Binds
+ @IntoMap
+ @ClassKey(ShadeController::class)
+ abstract fun bind(shadeController: ShadeController): CoreStartable
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
index 776956a..5639000 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
@@ -30,9 +30,11 @@
import androidx.core.animation.AnimatorListenerAdapter
import androidx.core.animation.AnimatorSet
import androidx.core.animation.ValueAnimator
+import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.R
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsChangedListener
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.window.StatusBarWindowController
import com.android.systemui.util.animation.AnimationUtil.Companion.frames
@@ -46,7 +48,7 @@
private val context: Context,
private val statusBarWindowController: StatusBarWindowController,
private val contentInsetsProvider: StatusBarContentInsetsProvider,
- private val featureFlags: FeatureFlags
+ private val featureFlags: FeatureFlags,
) : SystemStatusAnimationCallback {
private lateinit var animationWindowView: FrameLayout
@@ -56,7 +58,8 @@
// Left for LTR, Right for RTL
private var animationDirection = LEFT
- private var chipBounds = Rect()
+
+ @VisibleForTesting var chipBounds = Rect()
private val chipWidth get() = chipBounds.width()
private val chipRight get() = chipBounds.right
private val chipLeft get() = chipBounds.left
@@ -69,7 +72,7 @@
private var animRect = Rect()
// TODO: move to dagger
- private var initialized = false
+ @VisibleForTesting var initialized = false
/**
* Give the chip controller a chance to inflate and configure the chip view before we start
@@ -98,23 +101,7 @@
View.MeasureSpec.makeMeasureSpec(
(animationWindowView.parent as View).height, AT_MOST))
- // decide which direction we're animating from, and then set some screen coordinates
- val contentRect = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation()
- val chipTop = ((animationWindowView.parent as View).height - it.view.measuredHeight) / 2
- val chipBottom = chipTop + it.view.measuredHeight
- val chipRight: Int
- val chipLeft: Int
- when (animationDirection) {
- LEFT -> {
- chipRight = contentRect.right
- chipLeft = contentRect.right - it.chipWidth
- }
- else /* RIGHT */ -> {
- chipLeft = contentRect.left
- chipRight = contentRect.left + it.chipWidth
- }
- }
- chipBounds = Rect(chipLeft, chipTop, chipRight, chipBottom)
+ updateChipBounds(it, contentInsetsProvider.getStatusBarContentAreaForCurrentRotation())
}
}
@@ -253,16 +240,67 @@
return animSet
}
- private fun init() {
+ fun init() {
initialized = true
themedContext = ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings)
animationWindowView = LayoutInflater.from(themedContext)
.inflate(R.layout.system_event_animation_window, null) as FrameLayout
- val lp = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
- lp.gravity = Gravity.END or Gravity.CENTER_VERTICAL
+ // Matches status_bar.xml
+ val height = themedContext.resources.getDimensionPixelSize(R.dimen.status_bar_height)
+ val lp = FrameLayout.LayoutParams(MATCH_PARENT, height)
+ lp.gravity = Gravity.END or Gravity.TOP
statusBarWindowController.addViewToWindow(animationWindowView, lp)
animationWindowView.clipToPadding = false
animationWindowView.clipChildren = false
+
+ // Use contentInsetsProvider rather than configuration controller, since we only care
+ // about status bar dimens
+ contentInsetsProvider.addCallback(object : StatusBarContentInsetsChangedListener {
+ override fun onStatusBarContentInsetsChanged() {
+ val newContentArea = contentInsetsProvider
+ .getStatusBarContentAreaForCurrentRotation()
+ updateDimens(newContentArea)
+
+ // If we are currently animating, we have to re-solve for the chip bounds. If we're
+ // not animating then [prepareChipAnimation] will take care of it for us
+ currentAnimatedView?.let {
+ updateChipBounds(it, newContentArea)
+ }
+ }
+ })
+ }
+
+ private fun updateDimens(contentArea: Rect) {
+ val lp = animationWindowView.layoutParams as FrameLayout.LayoutParams
+ lp.height = contentArea.height()
+
+ animationWindowView.layoutParams = lp
+ }
+
+ /**
+ * Use the current status bar content area and the current chip's measured size to update
+ * the animation rect and chipBounds. This method can be called at any time and will update
+ * the current animation values properly during e.g. a rotation.
+ */
+ private fun updateChipBounds(chip: BackgroundAnimatableView, contentArea: Rect) {
+ // decide which direction we're animating from, and then set some screen coordinates
+ val chipTop = (contentArea.bottom - chip.view.measuredHeight) / 2
+ val chipBottom = chipTop + chip.view.measuredHeight
+ val chipRight: Int
+ val chipLeft: Int
+
+ when (animationDirection) {
+ LEFT -> {
+ chipRight = contentArea.right
+ chipLeft = contentArea.right - chip.chipWidth
+ }
+ else /* RIGHT */ -> {
+ chipLeft = contentArea.left
+ chipRight = contentArea.left + chip.chipWidth
+ }
+ }
+ chipBounds = Rect(chipLeft, chipTop, chipRight, chipBottom)
+ animRect.set(chipBounds)
}
private fun layoutParamsDefault(marginEnd: Int): FrameLayout.LayoutParams =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 8902a18..278ae95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -1613,7 +1613,6 @@
// (Right now, there's a circular dependency.)
mNotificationShadeWindowController.setWindowRootView(windowRootView);
mNotificationShadeWindowViewController.setupExpandedStatusBar();
- mShadeController.setShadeViewController(mShadeSurface);
mShadeController.setNotificationShadeWindowViewController(
mNotificationShadeWindowViewController);
mBackActionInteractor.setup(mQsController, mShadeSurface);
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 cb2a78d..5c1dfbe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -51,6 +51,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.KeyguardViewController;
+import com.android.keyguard.TrustGrantFlags;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor;
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
@@ -306,6 +307,16 @@
@Nullable private TaskbarDelegate mTaskbarDelegate;
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onTrustGrantedForCurrentUser(
+ boolean dismissKeyguard,
+ boolean newlyUnlocked,
+ @NonNull TrustGrantFlags flags,
+ @Nullable String message
+ ) {
+ updateAlternateBouncerShowing(mAlternateBouncerInteractor.maybeHide());
+ }
+
@Override
public void onEmergencyCallAction() {
// Since we won't get a setOccluded call we have to reset the view manually such that
@@ -431,7 +442,6 @@
mDockManager.addListener(mDockEventListener);
mIsDocked = mDockManager.isDocked();
}
- mKeyguardStateController.addCallback(mKeyguardStateControllerCallback);
}
/** Register a callback, to be invoked by the Predictive Back system. */
@@ -1570,14 +1580,6 @@
|| 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/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index 4e52be9..7f35dfb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -34,6 +34,7 @@
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.logDiffsForTable
@@ -48,6 +49,7 @@
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import java.util.concurrent.Executor
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
@@ -60,7 +62,9 @@
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.withContext
/** Real implementation of [WifiRepository]. */
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
@@ -76,8 +80,9 @@
logger: WifiInputLogger,
@WifiTableLog wifiTableLogBuffer: TableLogBuffer,
@Main mainExecutor: Executor,
+ @Background private val bgDispatcher: CoroutineDispatcher,
@Application scope: CoroutineScope,
- wifiManager: WifiManager,
+ private val wifiManager: WifiManager,
) : RealWifiRepository {
private val wifiStateChangeEvents: Flow<Unit> =
@@ -93,20 +98,25 @@
// have changed.
override val isWifiEnabled: StateFlow<Boolean> =
merge(wifiNetworkChangeEvents, wifiStateChangeEvents)
- .mapLatest { wifiManager.isWifiEnabled }
+ .onStart { emit(Unit) }
+ .mapLatest { isWifiEnabled() }
.distinctUntilChanged()
.logDiffsForTable(
wifiTableLogBuffer,
columnPrefix = "",
columnName = "isEnabled",
- initialValue = wifiManager.isWifiEnabled,
+ initialValue = false,
)
.stateIn(
scope = scope,
- started = SharingStarted.WhileSubscribed(),
- initialValue = wifiManager.isWifiEnabled,
+ started = SharingStarted.Eagerly,
+ initialValue = false,
)
+ // [WifiManager.isWifiEnabled] is a blocking IPC call, so fetch it in the background.
+ private suspend fun isWifiEnabled(): Boolean =
+ withContext(bgDispatcher) { wifiManager.isWifiEnabled }
+
override val isWifiDefault: StateFlow<Boolean> =
connectivityRepository.defaultConnections
// TODO(b/274493701): Should wifi be considered default if it's carrier merged?
@@ -289,6 +299,7 @@
private val logger: WifiInputLogger,
@WifiTableLog private val wifiTableLogBuffer: TableLogBuffer,
@Main private val mainExecutor: Executor,
+ @Background private val bgDispatcher: CoroutineDispatcher,
@Application private val scope: CoroutineScope,
) {
fun create(wifiManager: WifiManager): WifiRepositoryImpl {
@@ -299,6 +310,7 @@
logger,
wifiTableLogBuffer,
mainExecutor,
+ bgDispatcher,
scope,
wifiManager,
)
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index 3f31ff94..8cf71a0 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -45,7 +45,7 @@
import com.android.systemui.settings.dagger.MultiUserUtilsModule;
import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
import com.android.systemui.shade.ShadeController;
-import com.android.systemui.shade.ShadeControllerImpl;
+import com.android.systemui.shade.ShadeControllerEmptyImpl;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyboardShortcutsModule;
@@ -140,7 +140,7 @@
abstract DockManager bindDockManager(DockManagerImpl dockManager);
@Binds
- abstract ShadeController provideShadeController(ShadeControllerImpl shadeController);
+ abstract ShadeController provideShadeController(ShadeControllerEmptyImpl shadeController);
@SysUISingleton
@Provides
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthStateTest.kt
index fff1b81..278a43e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthStateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptAuthStateTest.kt
@@ -18,7 +18,7 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.biometrics.domain.model.BiometricModality
+import com.android.systemui.biometrics.shared.model.BiometricModality
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
index 87c9e58..91140a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
@@ -27,11 +27,12 @@
import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor
import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractorImpl
import com.android.systemui.biometrics.domain.model.BiometricModalities
-import com.android.systemui.biometrics.domain.model.BiometricModality
import com.android.systemui.biometrics.extractAuthenticatorTypes
import com.android.systemui.biometrics.faceSensorPropertiesInternal
import com.android.systemui.biometrics.fingerprintSensorPropertiesInternal
+import com.android.systemui.biometrics.shared.model.BiometricModality
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.util.mockito.any
import com.google.common.truth.Truth.assertThat
@@ -131,20 +132,22 @@
}
@Test
- fun plays_haptic_on_authenticated() = runGenericTest {
- viewModel.showAuthenticated(testCase.authenticatedModality, 1000L)
+ fun play_haptic_on_confirm_when_confirmation_required_otherwise_on_authenticated() =
+ runGenericTest {
+ val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
- verify(vibrator).vibrateAuthSuccess(any())
- verify(vibrator, never()).vibrateAuthError(any())
- }
+ viewModel.showAuthenticated(testCase.authenticatedModality, 1_000L)
- @Test
- fun plays_no_haptic_on_confirm() = runGenericTest {
- viewModel.confirmAuthenticated()
+ verify(vibrator, if (expectConfirmation) never() else times(1))
+ .vibrateAuthSuccess(any())
- verify(vibrator, never()).vibrateAuthSuccess(any())
- verify(vibrator, never()).vibrateAuthError(any())
- }
+ if (expectConfirmation) {
+ viewModel.confirmAuthenticated()
+ }
+
+ verify(vibrator).vibrateAuthSuccess(any())
+ verify(vibrator, never()).vibrateAuthError(any())
+ }
private suspend fun TestScope.showAuthenticated(
authenticatedModality: BiometricModality,
@@ -204,7 +207,12 @@
@Test
fun plays_haptic_on_errors() = runGenericTest {
- viewModel.showTemporaryError("so sad", hapticFeedback = true)
+ viewModel.showTemporaryError(
+ "so sad",
+ messageAfterError = "",
+ authenticateAfterError = false,
+ hapticFeedback = true,
+ )
verify(vibrator).vibrateAuthError(any())
verify(vibrator, never()).vibrateAuthSuccess(any())
@@ -212,7 +220,12 @@
@Test
fun plays_haptic_on_errors_unless_skipped() = runGenericTest {
- viewModel.showTemporaryError("still sad", hapticFeedback = false)
+ viewModel.showTemporaryError(
+ "still sad",
+ messageAfterError = "",
+ authenticateAfterError = false,
+ hapticFeedback = false,
+ )
verify(vibrator, never()).vibrateAuthError(any())
verify(vibrator, never()).vibrateAuthSuccess(any())
@@ -287,7 +300,13 @@
assertThat(canTryAgain).isFalse()
}
- val errorJob = launch { viewModel.showTemporaryError("error") }
+ val errorJob = launch {
+ viewModel.showTemporaryError(
+ "error",
+ messageAfterError = "",
+ authenticateAfterError = false,
+ )
+ }
verifyNoError()
errorJob.join()
verifyNoError()
@@ -306,12 +325,66 @@
assertThat(messageIsShowing).isTrue()
}
- // @Test
- fun `suppress errors`() = runGenericTest {
- val errorMessage = "woot"
- val message by collectLastValue(viewModel.message)
+ @Test
+ fun suppress_temporary_error() = runGenericTest {
+ val messages by collectValues(viewModel.message)
- val errorJob = launch { viewModel.showTemporaryError(errorMessage) }
+ for (error in listOf("never", "see", "me")) {
+ launch {
+ viewModel.showTemporaryError(
+ error,
+ messageAfterError = "or me",
+ authenticateAfterError = false,
+ suppressIf = { _ -> true },
+ )
+ }
+ }
+
+ testScheduler.advanceUntilIdle()
+ assertThat(messages).containsExactly(PromptMessage.Empty)
+ }
+
+ @Test
+ fun suppress_temporary_error_when_already_showing_when_requested() =
+ suppress_temporary_error_when_already_showing(suppress = true)
+
+ @Test
+ fun do_not_suppress_temporary_error_when_already_showing_when_not_requested() =
+ suppress_temporary_error_when_already_showing(suppress = false)
+
+ private fun suppress_temporary_error_when_already_showing(suppress: Boolean) = runGenericTest {
+ val errors = listOf("woot", "oh yeah", "nope")
+ val afterSuffix = "(after)"
+ val expectedErrorMessage = if (suppress) errors.first() else errors.last()
+ val messages by collectValues(viewModel.message)
+
+ for (error in errors) {
+ launch {
+ viewModel.showTemporaryError(
+ error,
+ messageAfterError = "$error $afterSuffix",
+ authenticateAfterError = false,
+ suppressIf = { currentMessage -> suppress && currentMessage.isError },
+ )
+ }
+ }
+
+ testScheduler.runCurrent()
+ assertThat(messages)
+ .containsExactly(
+ PromptMessage.Empty,
+ PromptMessage.Error(expectedErrorMessage),
+ )
+ .inOrder()
+
+ testScheduler.advanceUntilIdle()
+ assertThat(messages)
+ .containsExactly(
+ PromptMessage.Empty,
+ PromptMessage.Error(expectedErrorMessage),
+ PromptMessage.Help("$expectedErrorMessage $afterSuffix"),
+ )
+ .inOrder()
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
index c2219a4..481f36e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
@@ -345,23 +345,6 @@
assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
}
- @Test
- fun switchesToGone_whenUnlocked() =
- testScope.runTest {
- utils.authenticationRepository.setUnlocked(false)
- sceneInteractor.setCurrentScene(
- SceneTestUtils.CONTAINER_1,
- SceneModel(SceneKey.Bouncer)
- )
- val currentScene by
- collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
- assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-
- utils.authenticationRepository.setUnlocked(true)
-
- assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
- }
-
private fun assertTryAgainMessage(
message: String?,
time: Int,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
index 0356036..0df0a17 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
@@ -52,7 +52,10 @@
authenticationInteractor = authenticationInteractor,
sceneInteractor = utils.sceneInteractor(),
)
- private val underTest = utils.bouncerViewModel(bouncerInteractor)
+ private val underTest =
+ utils.bouncerViewModel(
+ bouncerInteractor = bouncerInteractor,
+ )
@Test
fun authMethod_nonNullForSecureMethods_nullForNotSecureMethods() =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
index 7d6c4a1..5c6d4c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
@@ -20,7 +20,6 @@
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
-import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.shared.model.SceneKey
@@ -54,16 +53,8 @@
sceneInteractor = sceneInteractor,
)
private val bouncerViewModel =
- BouncerViewModel(
- applicationContext = context,
- applicationScope = testScope.backgroundScope,
- interactorFactory =
- object : BouncerInteractor.Factory {
- override fun create(containerName: String): BouncerInteractor {
- return bouncerInteractor
- }
- },
- containerName = SceneTestUtils.CONTAINER_1,
+ utils.bouncerViewModel(
+ bouncerInteractor = bouncerInteractor,
)
private val underTest =
PinBouncerViewModel(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractorTest.kt
index 8b36284..ca6a5b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractorTest.kt
@@ -47,7 +47,6 @@
private val underTest =
utils.lockScreenSceneInteractor(
authenticationInteractor = authenticationInteractor,
- sceneInteractor = sceneInteractor,
bouncerInteractor =
utils.bouncerInteractor(
authenticationInteractor = authenticationInteractor,
@@ -129,22 +128,6 @@
}
@Test
- fun deviceLockedInNonLockScreenScene_switchesToLockScreenScene() =
- testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
- runCurrent()
- sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.Gone))
- runCurrent()
- utils.authenticationRepository.setUnlocked(true)
- runCurrent()
- assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
-
- utils.authenticationRepository.setUnlocked(false)
-
- assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
- }
-
- @Test
fun switchFromLockScreenToGone_authMethodNotSwipe_doesNotUnlockDevice() =
testScope.runTest {
val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
index 161dd66..ba8e0f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
@@ -56,7 +56,6 @@
override fun create(containerName: String): LockscreenSceneInteractor {
return utils.lockScreenSceneInteractor(
authenticationInteractor = authenticationInteractor,
- sceneInteractor = sceneInteractor,
bouncerInteractor =
utils.bouncerInteractor(
authenticationInteractor = authenticationInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
index 4eedc99..ed7a59e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
@@ -53,7 +53,6 @@
override fun create(containerName: String): LockscreenSceneInteractor {
return utils.lockScreenSceneInteractor(
authenticationInteractor = authenticationInteractor,
- sceneInteractor = sceneInteractor,
bouncerInteractor =
utils.bouncerInteractor(
authenticationInteractor = authenticationInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartableTest.kt
index df3701e..df5e7bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartableTest.kt
@@ -14,14 +14,11 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class, ExperimentalCoroutinesApi::class)
-
package com.android.systemui.scene.domain.startable
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.shared.model.SceneContainerNames
@@ -29,11 +26,14 @@
import com.android.systemui.scene.shared.model.SceneModel
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.test.runTest
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(JUnit4::class)
class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() {
@@ -41,29 +41,47 @@
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
private val sceneInteractor = utils.sceneInteractor()
- private val featureFlags = FakeFeatureFlags()
+ private val featureFlags = utils.featureFlags
+ private val authenticationRepository = utils.authenticationRepository()
+ private val authenticationInteractor =
+ utils.authenticationInteractor(
+ repository = authenticationRepository,
+ )
private val underTest =
SystemUiDefaultSceneContainerStartable(
applicationScope = testScope.backgroundScope,
sceneInteractor = sceneInteractor,
+ authenticationInteractor = authenticationInteractor,
featureFlags = featureFlags,
)
+ @Before
+ fun setUp() {
+ prepareState()
+ }
+
@Test
- fun start_featureEnabled_keepsVisibilityUpdated() =
+ fun hydrateVisibility_featureEnabled() =
testScope.runTest {
- featureFlags.set(Flags.SCENE_CONTAINER, true)
+ val currentSceneKey by
+ collectLastValue(
+ sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
+ it.key
+ }
+ )
val isVisible by
collectLastValue(sceneInteractor.isVisible(SceneContainerNames.SYSTEM_UI_DEFAULT))
+ prepareState(
+ isFeatureEnabled = true,
+ isDeviceUnlocked = true,
+ initialSceneKey = SceneKey.Gone,
+ )
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
assertThat(isVisible).isTrue()
underTest.start()
- sceneInteractor.setCurrentScene(
- SceneContainerNames.SYSTEM_UI_DEFAULT,
- SceneModel(SceneKey.Gone)
- )
assertThat(isVisible).isFalse()
sceneInteractor.setCurrentScene(
@@ -74,14 +92,26 @@
}
@Test
- fun start_featureDisabled_doesNotUpdateVisibility() =
+ fun hydrateVisibility_featureDisabled() =
testScope.runTest {
- featureFlags.set(Flags.SCENE_CONTAINER, false)
+ val currentSceneKey by
+ collectLastValue(
+ sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
+ it.key
+ }
+ )
val isVisible by
collectLastValue(sceneInteractor.isVisible(SceneContainerNames.SYSTEM_UI_DEFAULT))
+ prepareState(
+ isFeatureEnabled = false,
+ isDeviceUnlocked = true,
+ initialSceneKey = SceneKey.Lockscreen,
+ )
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
assertThat(isVisible).isTrue()
underTest.start()
+ assertThat(isVisible).isTrue()
sceneInteractor.setCurrentScene(
SceneContainerNames.SYSTEM_UI_DEFAULT,
@@ -95,4 +125,172 @@
)
assertThat(isVisible).isTrue()
}
+
+ @Test
+ fun switchToLockscreenWhenDeviceLocks_featureEnabled() =
+ testScope.runTest {
+ val currentSceneKey by
+ collectLastValue(
+ sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
+ it.key
+ }
+ )
+ prepareState(
+ isFeatureEnabled = true,
+ isDeviceUnlocked = true,
+ initialSceneKey = SceneKey.Gone,
+ )
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
+ underTest.start()
+
+ authenticationRepository.setUnlocked(false)
+
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
+ }
+
+ @Test
+ fun switchToLockscreenWhenDeviceLocks_featureDisabled() =
+ testScope.runTest {
+ val currentSceneKey by
+ collectLastValue(
+ sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
+ it.key
+ }
+ )
+ prepareState(
+ isFeatureEnabled = false,
+ isDeviceUnlocked = false,
+ initialSceneKey = SceneKey.Gone,
+ )
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
+ underTest.start()
+
+ authenticationRepository.setUnlocked(false)
+
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
+ }
+
+ @Test
+ fun switchFromBouncerToGoneWhenDeviceUnlocked_featureEnabled() =
+ testScope.runTest {
+ val currentSceneKey by
+ collectLastValue(
+ sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
+ it.key
+ }
+ )
+ prepareState(
+ isFeatureEnabled = true,
+ isDeviceUnlocked = false,
+ initialSceneKey = SceneKey.Bouncer,
+ )
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Bouncer)
+ underTest.start()
+
+ authenticationRepository.setUnlocked(true)
+
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
+ }
+
+ @Test
+ fun switchFromBouncerToGoneWhenDeviceUnlocked_featureDisabled() =
+ testScope.runTest {
+ val currentSceneKey by
+ collectLastValue(
+ sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
+ it.key
+ }
+ )
+ prepareState(
+ isFeatureEnabled = false,
+ isDeviceUnlocked = false,
+ initialSceneKey = SceneKey.Bouncer,
+ )
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Bouncer)
+ underTest.start()
+
+ authenticationRepository.setUnlocked(true)
+
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Bouncer)
+ }
+
+ @Test
+ fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn_featureOn_bypassOn() =
+ testScope.runTest {
+ val currentSceneKey by
+ collectLastValue(
+ sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
+ it.key
+ }
+ )
+ prepareState(
+ isFeatureEnabled = true,
+ isBypassEnabled = true,
+ initialSceneKey = SceneKey.Lockscreen,
+ )
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
+ underTest.start()
+
+ authenticationRepository.setUnlocked(true)
+
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
+ }
+
+ @Test
+ fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn_featureOn_bypassOff() =
+ testScope.runTest {
+ val currentSceneKey by
+ collectLastValue(
+ sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
+ it.key
+ }
+ )
+ prepareState(
+ isFeatureEnabled = true,
+ isBypassEnabled = false,
+ initialSceneKey = SceneKey.Lockscreen,
+ )
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
+ underTest.start()
+
+ authenticationRepository.setUnlocked(true)
+
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
+ }
+
+ @Test
+ fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn_featureOff_bypassOn() =
+ testScope.runTest {
+ val currentSceneKey by
+ collectLastValue(
+ sceneInteractor.currentScene(SceneContainerNames.SYSTEM_UI_DEFAULT).map {
+ it.key
+ }
+ )
+ prepareState(
+ isFeatureEnabled = false,
+ isBypassEnabled = true,
+ initialSceneKey = SceneKey.Lockscreen,
+ )
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
+ underTest.start()
+
+ authenticationRepository.setUnlocked(true)
+
+ assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
+ }
+
+ private fun prepareState(
+ isFeatureEnabled: Boolean = true,
+ isDeviceUnlocked: Boolean = false,
+ isBypassEnabled: Boolean = false,
+ initialSceneKey: SceneKey? = null,
+ ) {
+ featureFlags.set(Flags.SCENE_CONTAINER, isFeatureEnabled)
+ authenticationRepository.setUnlocked(isDeviceUnlocked)
+ authenticationRepository.setBypassEnabled(isBypassEnabled)
+ initialSceneKey?.let {
+ sceneInteractor.setCurrentScene(SceneContainerNames.SYSTEM_UI_DEFAULT, SceneModel(it))
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt
index 16751c9..5c35913 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessDialogTest.kt
@@ -16,12 +16,14 @@
package com.android.systemui.settings.brightness
+import android.content.Intent
import android.graphics.Rect
import android.os.Handler
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.View
import android.view.ViewGroup
+import android.view.WindowManagerPolicyConstants.EXTRA_FROM_BRIGHTNESS_KEY
import androidx.test.filters.SmallTest
import androidx.test.rule.ActivityTestRule
import com.android.systemui.R
@@ -29,15 +31,20 @@
import com.android.systemui.activity.SingleActivityFactory
import com.android.systemui.settings.FakeDisplayTracker
import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper
+import com.android.systemui.util.concurrency.DelayableExecutor
+import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
-import java.util.concurrent.Executor
import org.junit.After
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.anyInt
+import org.mockito.Mockito.eq
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@@ -48,9 +55,12 @@
@Mock private lateinit var userTracker: UserTracker
@Mock private lateinit var brightnessSliderControllerFactory: BrightnessSliderController.Factory
- @Mock private lateinit var mainExecutor: Executor
@Mock private lateinit var backgroundHandler: Handler
@Mock private lateinit var brightnessSliderController: BrightnessSliderController
+ @Mock private lateinit var accessibilityMgr: AccessibilityManagerWrapper
+
+ private val clock = FakeSystemClock()
+ private val mainExecutor = FakeExecutor(clock)
private var displayTracker = FakeDisplayTracker(mContext)
@@ -64,7 +74,8 @@
displayTracker,
brightnessSliderControllerFactory,
mainExecutor,
- backgroundHandler
+ backgroundHandler,
+ accessibilityMgr
)
},
/* initialTouchMode= */ false,
@@ -77,8 +88,6 @@
`when`(brightnessSliderControllerFactory.create(any(), any()))
.thenReturn(brightnessSliderController)
`when`(brightnessSliderController.rootView).thenReturn(View(context))
-
- activityRule.launchActivity(null)
}
@After
@@ -88,6 +97,7 @@
@Test
fun testGestureExclusion() {
+ activityRule.launchActivity(Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG))
val frame = activityRule.activity.requireViewById<View>(R.id.brightness_mirror_container)
val lp = frame.layoutParams as ViewGroup.MarginLayoutParams
@@ -104,18 +114,83 @@
.isEqualTo(Rect(-horizontalMargin, 0, frame.width + horizontalMargin, frame.height))
}
+ @Test
+ fun testTimeout() {
+ `when`(
+ accessibilityMgr.getRecommendedTimeoutMillis(
+ eq(BrightnessDialog.DIALOG_TIMEOUT_MILLIS),
+ anyInt()
+ )
+ )
+ .thenReturn(BrightnessDialog.DIALOG_TIMEOUT_MILLIS)
+ val intent = Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG)
+ intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true)
+ activityRule.launchActivity(intent)
+
+ assertThat(activityRule.activity.isFinishing()).isFalse()
+
+ clock.advanceTime(BrightnessDialog.DIALOG_TIMEOUT_MILLIS.toLong())
+ assertThat(activityRule.activity.isFinishing()).isTrue()
+ }
+
+ @Test
+ fun testRestartTimeout() {
+ `when`(
+ accessibilityMgr.getRecommendedTimeoutMillis(
+ eq(BrightnessDialog.DIALOG_TIMEOUT_MILLIS),
+ anyInt()
+ )
+ )
+ .thenReturn(BrightnessDialog.DIALOG_TIMEOUT_MILLIS)
+ val intent = Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG)
+ intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true)
+ activityRule.launchActivity(intent)
+
+ assertThat(activityRule.activity.isFinishing()).isFalse()
+
+ clock.advanceTime(BrightnessDialog.DIALOG_TIMEOUT_MILLIS.toLong() / 2)
+ // Restart the timeout
+ activityRule.activity.onResume()
+
+ clock.advanceTime(BrightnessDialog.DIALOG_TIMEOUT_MILLIS.toLong() / 2)
+ // The dialog should not have disappeared yet
+ assertThat(activityRule.activity.isFinishing()).isFalse()
+
+ clock.advanceTime(BrightnessDialog.DIALOG_TIMEOUT_MILLIS.toLong() / 2)
+ assertThat(activityRule.activity.isFinishing()).isTrue()
+ }
+
+ @Test
+ fun testNoTimeoutIfNotStartedByBrightnessKey() {
+ `when`(
+ accessibilityMgr.getRecommendedTimeoutMillis(
+ eq(BrightnessDialog.DIALOG_TIMEOUT_MILLIS),
+ anyInt()
+ )
+ )
+ .thenReturn(BrightnessDialog.DIALOG_TIMEOUT_MILLIS)
+ activityRule.launchActivity(Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG))
+
+ assertThat(activityRule.activity.isFinishing()).isFalse()
+
+ clock.advanceTime(BrightnessDialog.DIALOG_TIMEOUT_MILLIS.toLong())
+ assertThat(activityRule.activity.isFinishing()).isFalse()
+ }
+
class TestDialog(
userTracker: UserTracker,
displayTracker: FakeDisplayTracker,
brightnessSliderControllerFactory: BrightnessSliderController.Factory,
- mainExecutor: Executor,
- backgroundHandler: Handler
+ mainExecutor: DelayableExecutor,
+ backgroundHandler: Handler,
+ accessibilityMgr: AccessibilityManagerWrapper
) :
BrightnessDialog(
userTracker,
displayTracker,
brightnessSliderControllerFactory,
mainExecutor,
- backgroundHandler
+ backgroundHandler,
+ accessibilityMgr
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
index 729c4a9..52e0c9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeControllerImplTest.kt
@@ -78,11 +78,11 @@
deviceProvisionedController,
notificationShadeWindowController,
windowManager,
+ Lazy { shadeViewController },
Lazy { assistManager },
Lazy { gutsManager },
)
shadeController.setNotificationShadeWindowViewController(nswvc)
- shadeController.setShadeViewController(shadeViewController)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
index 309ab05..6e9fba6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
@@ -22,7 +22,6 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.domain.interactor.LockscreenSceneInteractor
import com.android.systemui.scene.SceneTestUtils
-import com.android.systemui.scene.SceneTestUtils.Companion.CONTAINER_1
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.scene.shared.model.SceneModel
import com.google.common.truth.Truth.assertThat
@@ -54,7 +53,6 @@
override fun create(containerName: String): LockscreenSceneInteractor {
return utils.lockScreenSceneInteractor(
authenticationInteractor = authenticationInteractor,
- sceneInteractor = sceneInteractor,
bouncerInteractor =
utils.bouncerInteractor(
authenticationInteractor = authenticationInteractor,
@@ -89,7 +87,8 @@
@Test
fun onContentClicked_deviceUnlocked_switchesToGone() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
+ val currentScene by
+ collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(true)
runCurrent()
@@ -102,7 +101,8 @@
@Test
fun onContentClicked_deviceLockedSecurely_switchesToBouncer() =
testScope.runTest {
- val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1))
+ val currentScene by
+ collectLastValue(sceneInteractor.currentScene(SceneTestUtils.CONTAINER_1))
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
utils.authenticationRepository.setUnlocked(false)
runCurrent()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt
new file mode 100644
index 0000000..55b6be9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt
@@ -0,0 +1,189 @@
+/*
+ * 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.statusbar.events
+
+import android.content.Context
+import android.graphics.Rect
+import android.util.Pair
+import android.view.Gravity
+import android.view.View
+import android.widget.FrameLayout
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsChangedListener
+import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
+import com.android.systemui.statusbar.window.StatusBarWindowController
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+class SystemEventChipAnimationControllerTest : SysuiTestCase() {
+ private lateinit var controller: SystemEventChipAnimationController
+
+ @Mock private lateinit var sbWindowController: StatusBarWindowController
+ @Mock private lateinit var insetsProvider: StatusBarContentInsetsProvider
+
+ private var testView = TestView(mContext)
+ private var viewCreator: ViewCreator = { testView }
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+
+ // StatusBarWindowController is mocked. The addViewToWindow function needs to be mocked to
+ // ensure that the chip view is added to a parent view
+ whenever(sbWindowController.addViewToWindow(any(), any())).then {
+ val statusbarFake = FrameLayout(mContext)
+ statusbarFake.layout(
+ portraitArea.left,
+ portraitArea.top,
+ portraitArea.right,
+ portraitArea.bottom,
+ )
+ statusbarFake.addView(
+ it.arguments[0] as View,
+ it.arguments[1] as FrameLayout.LayoutParams
+ )
+ }
+
+ whenever(insetsProvider.getStatusBarContentInsetsForCurrentRotation())
+ .thenReturn(Pair(insets, insets))
+ whenever(insetsProvider.getStatusBarContentAreaForCurrentRotation())
+ .thenReturn(portraitArea)
+
+ controller =
+ SystemEventChipAnimationController(
+ context = mContext,
+ statusBarWindowController = sbWindowController,
+ contentInsetsProvider = insetsProvider,
+ featureFlags = FakeFeatureFlags(),
+ )
+ }
+
+ @Test
+ fun prepareChipAnimation_lazyInitializes() {
+ // Until Dagger can do our initialization, make sure that the first chip animation calls
+ // init()
+ assertFalse(controller.initialized)
+ controller.prepareChipAnimation(viewCreator)
+ assertTrue(controller.initialized)
+ }
+
+ @Test
+ fun prepareChipAnimation_positionsChip() {
+ controller.prepareChipAnimation(viewCreator)
+ val chipRect = controller.chipBounds
+
+ // SB area = 10, 0, 990, 100
+ // chip size = 0, 0, 100, 50
+ assertThat(chipRect).isEqualTo(Rect(890, 25, 990, 75))
+ }
+
+ @Test
+ fun prepareChipAnimation_rotation_repositionsChip() {
+ controller.prepareChipAnimation(viewCreator)
+
+ // Chip has been prepared, and is located at (890, 25, 990, 75)
+ // Rotation should put it into its landscape location:
+ // SB area = 10, 0, 1990, 80
+ // chip size = 0, 0, 100, 50
+
+ whenever(insetsProvider.getStatusBarContentAreaForCurrentRotation())
+ .thenReturn(landscapeArea)
+ getInsetsListener().onStatusBarContentInsetsChanged()
+
+ val chipRect = controller.chipBounds
+ assertThat(chipRect).isEqualTo(Rect(1890, 15, 1990, 65))
+ }
+
+ /** regression test for (b/289378932) */
+ @Test
+ fun fullScreenStatusBar_positionsChipAtTop_withTopGravity() {
+ // In the case of a fullscreen status bar window, the content insets area is still correct
+ // (because it uses the dimens), but the window can be full screen. This seems to happen
+ // when launching an app from the ongoing call chip.
+
+ // GIVEN layout the status bar window fullscreen portrait
+ whenever(sbWindowController.addViewToWindow(any(), any())).then {
+ val statusbarFake = FrameLayout(mContext)
+ statusbarFake.layout(
+ fullScreenSb.left,
+ fullScreenSb.top,
+ fullScreenSb.right,
+ fullScreenSb.bottom,
+ )
+
+ val lp = it.arguments[1] as FrameLayout.LayoutParams
+ assertThat(lp.gravity and Gravity.VERTICAL_GRAVITY_MASK).isEqualTo(Gravity.TOP)
+
+ statusbarFake.addView(
+ it.arguments[0] as View,
+ lp,
+ )
+ }
+
+ // GIVEN insets provider gives the correct content area
+ whenever(insetsProvider.getStatusBarContentAreaForCurrentRotation())
+ .thenReturn(portraitArea)
+
+ // WHEN the controller lays out the chip in a fullscreen window
+ controller.prepareChipAnimation(viewCreator)
+
+ // THEN it still aligns the chip to the content area provided by the insets provider
+ val chipRect = controller.chipBounds
+ assertThat(chipRect).isEqualTo(Rect(890, 25, 990, 75))
+ }
+
+ class TestView(context: Context) : View(context), BackgroundAnimatableView {
+ override val view: View
+ get() = this
+
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ setMeasuredDimension(100, 50)
+ }
+
+ override fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int) {
+ setLeftTopRightBottom(l, t, r, b)
+ }
+ }
+
+ private fun getInsetsListener(): StatusBarContentInsetsChangedListener {
+ val callbackCaptor = argumentCaptor<StatusBarContentInsetsChangedListener>()
+ verify(insetsProvider).addCallback(capture(callbackCaptor))
+ return callbackCaptor.value!!
+ }
+
+ companion object {
+ private val portraitArea = Rect(10, 0, 990, 100)
+ private val landscapeArea = Rect(10, 0, 1990, 80)
+ private val fullScreenSb = Rect(10, 0, 990, 2000)
+
+ // 10px insets on both sides
+ private const val insets = 10
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 88d8dfc..3d35233 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -447,10 +447,10 @@
mDeviceProvisionedController,
mNotificationShadeWindowController,
mContext.getSystemService(WindowManager.class),
+ () -> mNotificationPanelViewController,
() -> mAssistManager,
() -> mNotificationGutsManager
));
- mShadeController.setShadeViewController(mNotificationPanelViewController);
mShadeController.setNotificationShadeWindowViewController(
mNotificationShadeWindowViewController);
mShadeController.setNotificationPresenter(mNotificationPresenter);
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 c7143de..ed9cf3f 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
@@ -35,6 +35,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.service.trust.TrustAgentService;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.MotionEvent;
@@ -57,6 +58,8 @@
import com.android.keyguard.KeyguardMessageAreaController;
import com.android.keyguard.KeyguardSecurityModel;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.keyguard.TrustGrantFlags;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor;
@@ -84,7 +87,6 @@
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;
@@ -154,7 +156,7 @@
@Captor
private ArgumentCaptor<OnBackInvokedCallback> mBackCallbackCaptor;
@Captor
- private ArgumentCaptor<KeyguardStateController.Callback> mKeyguardStateControllerCallback;
+ private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallback;
@Before
@@ -936,18 +938,24 @@
}
@Test
- public void onDeviceUnlocked_hideAlternateBouncerAndClearMessageArea() {
+ public void onTrustChanged_hideAlternateBouncerAndClearMessageArea() {
+ // GIVEN keyguard update monitor callback is registered
+ verify(mKeyguardUpdateMonitor).registerCallback(mKeyguardUpdateMonitorCallback.capture());
+
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();
+ // WHEN the device is trusted by active unlock
+ mKeyguardUpdateMonitorCallback.getValue().onTrustGrantedForCurrentUser(
+ true,
+ true,
+ new TrustGrantFlags(TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD
+ | TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE),
+ null
+ );
// THEN the false visibility state is propagated to the keyguardUpdateMonitor
verify(mKeyguardUpdateMonitor).setAlternateBouncerShowing(eq(false));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
index 862eb00..c8b6f13d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
@@ -159,6 +159,7 @@
mock(),
mock(),
FakeExecutor(FakeSystemClock()),
+ dispatcher,
testScope.backgroundScope,
mock(),
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
index 30b95ef..5bc98e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
@@ -83,6 +83,7 @@
logger,
tableLogger,
mainExecutor,
+ testDispatcher,
testScope.backgroundScope,
wifiManager,
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
index 5ed3a5c..7007345 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
@@ -76,7 +76,8 @@
private lateinit var executor: Executor
private lateinit var connectivityRepository: ConnectivityRepository
- private val testScope = TestScope(UnconfinedTestDispatcher())
+ private val dispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(dispatcher)
@Before
fun setUp() {
@@ -1301,6 +1302,7 @@
logger,
tableLogger,
executor,
+ dispatcher,
testScope.backgroundScope,
wifiManager,
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index fec1187..d797962 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -24,6 +24,8 @@
import com.android.systemui.bouncer.data.repository.BouncerRepository
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.domain.interactor.LockscreenSceneInteractor
import com.android.systemui.scene.data.repository.SceneContainerRepository
import com.android.systemui.scene.domain.interactor.SceneInteractor
@@ -51,6 +53,7 @@
) {
val testDispatcher = StandardTestDispatcher()
val testScope = TestScope(testDispatcher)
+ val featureFlags = FakeFeatureFlags().apply { set(Flags.SCENE_CONTAINER, true) }
private val userRepository: UserRepository by lazy {
FakeUserRepository().apply {
val users = listOf(UserInfo(/* id= */ 0, "name", /* flags= */ 0))
@@ -129,6 +132,7 @@
repository = BouncerRepository(),
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
+ featureFlags = featureFlags,
containerName = CONTAINER_1,
)
}
@@ -145,13 +149,13 @@
return bouncerInteractor
}
},
+ featureFlags = featureFlags,
containerName = CONTAINER_1,
)
}
fun lockScreenSceneInteractor(
authenticationInteractor: AuthenticationInteractor,
- sceneInteractor: SceneInteractor,
bouncerInteractor: BouncerInteractor,
): LockscreenSceneInteractor {
return LockscreenSceneInteractor(
@@ -163,7 +167,6 @@
return bouncerInteractor
}
},
- sceneInteractor = sceneInteractor,
containerName = CONTAINER_1,
)
}
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 82af382..ad8f5e1 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -20,6 +20,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.ActivityManager;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
import android.app.assist.AssistStructure.WindowNode;
@@ -40,6 +42,7 @@
import android.view.WindowManager;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
+import android.widget.RemoteViews;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.ArrayUtils;
@@ -50,6 +53,8 @@
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicBoolean;
+
public final class Helper {
@@ -83,6 +88,44 @@
throw new UnsupportedOperationException("contains static members only");
}
+ private static boolean checkRemoteViewUriPermissions(
+ @UserIdInt int userId, @NonNull RemoteViews rView) {
+ final AtomicBoolean permissionsOk = new AtomicBoolean(true);
+
+ rView.visitUris(uri -> {
+ int uriOwnerId = android.content.ContentProvider.getUserIdFromUri(uri);
+ boolean allowed = uriOwnerId == userId;
+ permissionsOk.set(allowed & permissionsOk.get());
+ });
+
+ return permissionsOk.get();
+ }
+
+ /**
+ * Checks the URI permissions of the remote view,
+ * to see if the current userId is able to access it.
+ *
+ * Returns the RemoteView that is passed if user is able, null otherwise.
+ *
+ * TODO: instead of returning a null remoteview when
+ * the current userId cannot access an URI,
+ * return a new RemoteView with the URI removed.
+ */
+ public static @Nullable RemoteViews sanitizeRemoteView(RemoteViews rView) {
+ if (rView == null) return null;
+
+ int userId = ActivityManager.getCurrentUser();
+
+ boolean ok = checkRemoteViewUriPermissions(userId, rView);
+ if (!ok) {
+ Slog.w(TAG,
+ "sanitizeRemoteView() user: " + userId
+ + " tried accessing resource that does not belong to them");
+ }
+ return (ok ? rView : null);
+ }
+
+
@Nullable
static AutofillId[] toArray(@Nullable ArraySet<AutofillId> set) {
if (set == null) return null;
diff --git a/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java b/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java
index dbeb624..fa414e3 100644
--- a/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/DialogFillUi.java
@@ -53,6 +53,7 @@
import com.android.internal.R;
import com.android.server.autofill.AutofillManagerService;
+import com.android.server.autofill.Helper;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -208,7 +209,8 @@
}
private void setHeader(View decor, FillResponse response) {
- final RemoteViews presentation = response.getDialogHeader();
+ final RemoteViews presentation =
+ Helper.sanitizeRemoteView(response.getDialogHeader());
if (presentation == null) {
return;
}
@@ -243,9 +245,10 @@
}
private void initialAuthenticationLayout(View decor, FillResponse response) {
- RemoteViews presentation = response.getDialogPresentation();
+ RemoteViews presentation = Helper.sanitizeRemoteView(
+ response.getDialogPresentation());
if (presentation == null) {
- presentation = response.getPresentation();
+ presentation = Helper.sanitizeRemoteView(response.getPresentation());
}
if (presentation == null) {
throw new RuntimeException("No presentation for fill dialog authentication");
@@ -289,7 +292,8 @@
final Dataset dataset = response.getDatasets().get(i);
final int index = dataset.getFieldIds().indexOf(focusedViewId);
if (index >= 0) {
- RemoteViews presentation = dataset.getFieldDialogPresentation(index);
+ RemoteViews presentation = Helper.sanitizeRemoteView(
+ dataset.getFieldDialogPresentation(index));
if (presentation == null) {
if (sDebug) {
Slog.w(TAG, "not displaying UI on field " + focusedViewId + " because "
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 129ce72..cdfe7bb 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -148,8 +148,9 @@
final LayoutInflater inflater = LayoutInflater.from(mContext);
- final RemoteViews headerPresentation = response.getHeader();
- final RemoteViews footerPresentation = response.getFooter();
+ final RemoteViews headerPresentation = Helper.sanitizeRemoteView(response.getHeader());
+ final RemoteViews footerPresentation = Helper.sanitizeRemoteView(response.getFooter());
+
final ViewGroup decor;
if (mFullScreen) {
decor = (ViewGroup) inflater.inflate(R.layout.autofill_dataset_picker_fullscreen, null);
@@ -227,6 +228,9 @@
ViewGroup container = decor.findViewById(R.id.autofill_dataset_picker);
final View content;
try {
+ if (Helper.sanitizeRemoteView(response.getPresentation()) == null) {
+ throw new RuntimeException("Permission error accessing RemoteView");
+ }
content = response.getPresentation().applyWithTheme(
mContext, decor, interceptionHandler, mThemeId);
container.addView(content);
@@ -306,7 +310,8 @@
final Dataset dataset = response.getDatasets().get(i);
final int index = dataset.getFieldIds().indexOf(focusedViewId);
if (index >= 0) {
- final RemoteViews presentation = dataset.getFieldPresentation(index);
+ final RemoteViews presentation = Helper.sanitizeRemoteView(
+ dataset.getFieldPresentation(index));
if (presentation == null) {
Slog.w(TAG, "not displaying UI on field " + focusedViewId + " because "
+ "service didn't provide a presentation for it on " + dataset);
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 f035d07..70382f1 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -384,8 +384,7 @@
return false;
}
writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_DESCRIPTION);
-
- final RemoteViews template = customDescription.getPresentation();
+ final RemoteViews template = Helper.sanitizeRemoteView(customDescription.getPresentation());
if (template == null) {
Slog.w(TAG, "No remote view on custom description");
return false;
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 7fae31c..bca2d60 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -1827,6 +1827,9 @@
soname, soname, new String[0], true);
mSharedLibraries.put(entry.name, entry);
}
+ } catch (FileNotFoundException e) {
+ // Expected for /vendor/etc/public.libraries.txt on some devices
+ Slog.d(TAG, listFile + " does not exist");
} catch (IOException e) {
Slog.w(TAG, "Failed to read public libraries file " + listFile, e);
}
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 48de441..6baae4b 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -453,7 +453,7 @@
mInterestingJavaPids.add(Process.myPid());
// See the notes on DEFAULT_TIMEOUT.
- assert DB ||
+ assert DB || Build.IS_USERDEBUG ||
DEFAULT_TIMEOUT > ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS;
mTraceErrorLogger = new TraceErrorLogger();
@@ -527,7 +527,8 @@
*/
void updateWatchdogTimeout(long timeoutMillis) {
// See the notes on DEFAULT_TIMEOUT.
- if (!DB && timeoutMillis <= ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS) {
+ if (!DB && !Build.IS_USERDEBUG
+ && timeoutMillis <= ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS) {
timeoutMillis = ZygoteConnectionConstants.WRAPPED_PID_TIMEOUT_MILLIS + 1;
}
mWatchdogTimeoutMillis = timeoutMillis;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 359c3cd..eacc7c2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5822,12 +5822,25 @@
/**
* Allows if {@code pid} is {@link #MY_PID}, then denies if the {@code pid} has been denied
* provided non-{@code null} {@code permission} before. Otherwise calls into
- * {@link ActivityManager#checkComponentPermission(String, int, int, boolean)}.
+ * {@link ActivityManager#checkComponentPermission(String, int, int, int, boolean)}.
*/
@PackageManager.PermissionResult
@PermissionMethod
public static int checkComponentPermission(@PermissionName String permission, int pid, int uid,
int owningUid, boolean exported) {
+ return checkComponentPermission(permission, pid, uid, Context.DEVICE_ID_DEFAULT,
+ owningUid, exported);
+ }
+
+ /**
+ * Allows if {@code pid} is {@link #MY_PID}, then denies if the {@code pid} has been denied
+ * provided non-{@code null} {@code permission} before. Otherwise calls into
+ * {@link ActivityManager#checkComponentPermission(String, int, int, int, boolean)}.
+ */
+ @PackageManager.PermissionResult
+ @PermissionMethod
+ public static int checkComponentPermission(@PermissionName String permission, int pid, int uid,
+ int deviceId, int owningUid, boolean exported) {
if (pid == MY_PID) {
return PackageManager.PERMISSION_GRANTED;
}
@@ -5846,7 +5859,7 @@
}
}
}
- return ActivityManager.checkComponentPermission(permission, uid,
+ return ActivityManager.checkComponentPermission(permission, uid, deviceId,
owningUid, exported);
}
@@ -5875,10 +5888,27 @@
@PackageManager.PermissionResult
@PermissionMethod
public int checkPermission(@PermissionName String permission, int pid, int uid) {
+ return checkPermissionForDevice(permission, pid, uid, Context.DEVICE_ID_DEFAULT);
+ }
+
+ /**
+ * As the only public entry point for permissions checking, this method
+ * can enforce the semantic that requesting a check on a null global
+ * permission is automatically denied. (Internally a null permission
+ * string is used when calling {@link #checkComponentPermission} in cases
+ * when only uid-based security is needed.)
+ *
+ * This can be called with or without the global lock held.
+ */
+ @Override
+ @PackageManager.PermissionResult
+ @PermissionMethod
+ public int checkPermissionForDevice(@PermissionName String permission, int pid, int uid,
+ int deviceId) {
if (permission == null) {
return PackageManager.PERMISSION_DENIED;
}
- return checkComponentPermission(permission, pid, uid, -1, true);
+ return checkComponentPermission(permission, pid, uid, deviceId, -1, true);
}
/**
@@ -8108,8 +8138,8 @@
return killed;
}
- @Override
- public void killUid(int appId, int userId, String reason) {
+ private void killUid(int appId, int userId, int reason, int subReason,
+ String reasonAsString) {
enforceCallingPermission(Manifest.permission.KILL_UID, "killUid");
synchronized (this) {
final long identity = Binder.clearCallingIdentity();
@@ -8120,9 +8150,9 @@
true /* callerWillRestart */, true /* doit */,
true /* evenPersistent */, false /* setRemoved */,
false /* uninstalling */,
- ApplicationExitInfo.REASON_OTHER,
- ApplicationExitInfo.SUBREASON_KILL_UID,
- reason != null ? reason : "kill uid");
+ reason,
+ subReason,
+ reasonAsString != null ? reasonAsString : "kill uid");
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -8131,6 +8161,12 @@
}
@Override
+ public void killUid(int appId, int userId, String reason) {
+ killUid(appId, userId, ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_KILL_UID, reason);
+ }
+
+ @Override
public void killUidForPermissionChange(int appId, int userId, String reason) {
enforceCallingPermission(Manifest.permission.KILL_UID, "killUid");
synchronized (this) {
@@ -8645,6 +8681,8 @@
Slog.i(TAG, "Skipping kill (uid is SYSTEM)");
} else {
killUid(UserHandle.getAppId(uid), UserHandle.getUserId(uid),
+ ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
+ ApplicationExitInfo.SUBREASON_EXCESSIVE_BINDER_OBJECTS,
"Too many Binders sent to SYSTEM");
// We need to run a GC here, because killing the processes involved
// actually isn't guaranteed to free up the proxies; in fact, if the
@@ -8658,7 +8696,7 @@
// cleaning up the old proxies.
VMRuntime.getRuntime().requestConcurrentGC();
}
- }, mHandler);
+ }, BackgroundThread.getHandler());
t.traceEnd(); // setBinderProxies
t.traceEnd(); // ActivityManagerStartApps
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 81bcd2a..1bc681a 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7005,7 +7005,7 @@
*/
private boolean canBeNonDismissible(ApplicationInfo ai, Notification notification) {
return notification.isMediaNotification() || isEnterpriseExempted(ai)
- || isCallNotification(ai.packageName, ai.uid, notification)
+ || notification.isStyle(Notification.CallStyle.class)
|| isDefaultSearchSelectorPackage(ai.packageName);
}
diff --git a/services/core/java/com/android/server/notification/PermissionHelper.java b/services/core/java/com/android/server/notification/PermissionHelper.java
index 93c83e1..85c140c 100644
--- a/services/core/java/com/android/server/notification/PermissionHelper.java
+++ b/services/core/java/com/android/server/notification/PermissionHelper.java
@@ -196,19 +196,20 @@
int uid = mPackageManager.getPackageUid(packageName, 0, userId);
boolean currentlyGranted = hasPermission(uid);
if (grant && !currentlyGranted) {
- mPermManager.grantRuntimePermission(packageName, NOTIFICATION_PERMISSION, userId);
+ mPermManager.grantRuntimePermission(packageName, NOTIFICATION_PERMISSION,
+ Context.DEVICE_ID_DEFAULT, userId);
} else if (!grant && currentlyGranted) {
mPermManager.revokeRuntimePermission(packageName, NOTIFICATION_PERMISSION,
- userId, TAG);
+ Context.DEVICE_ID_DEFAULT, userId, TAG);
}
int flagMask = FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED;
flagMask = userSet || !grant ? flagMask | FLAG_PERMISSION_GRANTED_BY_DEFAULT : flagMask;
if (userSet) {
- mPermManager.updatePermissionFlags(packageName, NOTIFICATION_PERMISSION,
- flagMask, FLAG_PERMISSION_USER_SET, true, userId);
+ mPermManager.updatePermissionFlags(packageName, NOTIFICATION_PERMISSION, flagMask,
+ FLAG_PERMISSION_USER_SET, true, Context.DEVICE_ID_DEFAULT, userId);
} else {
mPermManager.updatePermissionFlags(packageName, NOTIFICATION_PERMISSION,
- flagMask, 0, true, userId);
+ flagMask, 0, true, Context.DEVICE_ID_DEFAULT, userId);
}
} catch (RemoteException e) {
Slog.e(TAG, "Could not reach system server", e);
@@ -236,7 +237,7 @@
try {
try {
int flags = mPermManager.getPermissionFlags(packageName, NOTIFICATION_PERMISSION,
- userId);
+ Context.DEVICE_ID_DEFAULT, userId);
return (flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0
|| (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0;
} catch (RemoteException e) {
@@ -253,7 +254,7 @@
try {
try {
int flags = mPermManager.getPermissionFlags(packageName, NOTIFICATION_PERMISSION,
- userId);
+ Context.DEVICE_ID_DEFAULT, userId);
return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
| PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
} catch (RemoteException e) {
@@ -270,7 +271,7 @@
try {
try {
int flags = mPermManager.getPermissionFlags(packageName, NOTIFICATION_PERMISSION,
- userId);
+ Context.DEVICE_ID_DEFAULT, userId);
return (flags & (PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT
| PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE)) != 0;
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
index 1b34c70..7f0aadc 100644
--- a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
+++ b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java
@@ -234,7 +234,7 @@
// the installers without INSTALL_PACKAGES perm can't perform
// the installation in background. So we can just filter out them.
if (mPermissionManager.checkPermission(installerPackageName,
- android.Manifest.permission.INSTALL_PACKAGES,
+ android.Manifest.permission.INSTALL_PACKAGES, Context.DEVICE_ID_DEFAULT,
userId) != PackageManager.PERMISSION_GRANTED) {
return;
}
@@ -433,7 +433,7 @@
return true;
}
return mPermissionManager.checkPermission(pkgName,
- android.Manifest.permission.INSTALL_PACKAGES,
+ android.Manifest.permission.INSTALL_PACKAGES, Context.DEVICE_ID_DEFAULT,
userId) == PackageManager.PERMISSION_GRANTED;
}
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 7aa5c65..1b52725 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -2583,7 +2583,7 @@
// NOTE: Can't remove without a major refactor. Keep around for now.
public final int checkUidPermission(String permName, int uid) {
- return mPermissionManager.checkUidPermission(uid, permName);
+ return mPermissionManager.checkUidPermission(uid, permName, Context.DEVICE_ID_DEFAULT);
}
public int getPackageUidInternal(String packageName,
@@ -4528,8 +4528,8 @@
int numMatch = 0;
for (int i=0; i<permissions.length; i++) {
final String permission = permissions[i];
- if (mPermissionManager.checkPermission(ps.getPackageName(), permission, userId)
- == PERMISSION_GRANTED) {
+ if (mPermissionManager.checkPermission(ps.getPackageName(), permission,
+ Context.DEVICE_ID_DEFAULT, userId) == PERMISSION_GRANTED) {
tmp[i] = true;
numMatch++;
} else {
diff --git a/services/core/java/com/android/server/pm/DefaultAppProvider.java b/services/core/java/com/android/server/pm/DefaultAppProvider.java
index c18d0e9..fc61451 100644
--- a/services/core/java/com/android/server/pm/DefaultAppProvider.java
+++ b/services/core/java/com/android/server/pm/DefaultAppProvider.java
@@ -24,14 +24,10 @@
import android.os.UserHandle;
import android.util.Slog;
-import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.CollectionUtils;
import com.android.server.FgThread;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -70,27 +66,19 @@
* Set the package name of the default browser.
*
* @param packageName package name of the default browser, or {@code null} to unset
- * @param async whether the operation should be asynchronous
* @param userId the user ID
- * @return whether the default browser was successfully set.
*/
- public boolean setDefaultBrowser(@Nullable String packageName, boolean async,
- @UserIdInt int userId) {
- if (userId == UserHandle.USER_ALL) {
- return false;
- }
+ public void setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId) {
final RoleManager roleManager = mRoleManagerSupplier.get();
if (roleManager == null) {
- return false;
+ return;
}
final UserHandle user = UserHandle.of(userId);
final Executor executor = FgThread.getExecutor();
- final AndroidFuture<Void> future = new AndroidFuture<>();
final Consumer<Boolean> callback = successful -> {
- if (successful) {
- future.complete(null);
- } else {
- future.completeExceptionally(new RuntimeException());
+ if (!successful) {
+ Slog.e(PackageManagerService.TAG, "Failed to set default browser to "
+ + packageName);
}
};
final long identity = Binder.clearCallingIdentity();
@@ -102,19 +90,9 @@
roleManager.clearRoleHoldersAsUser(RoleManager.ROLE_BROWSER, 0, user, executor,
callback);
}
- if (!async) {
- try {
- future.get(5, TimeUnit.SECONDS);
- } catch (InterruptedException | ExecutionException | TimeoutException e) {
- Slog.e(PackageManagerService.TAG, "Exception while setting default browser: "
- + packageName, e);
- return false;
- }
- }
} finally {
Binder.restoreCallingIdentity(identity);
}
- return true;
}
/**
diff --git a/services/core/java/com/android/server/pm/DumpHelper.java b/services/core/java/com/android/server/pm/DumpHelper.java
index b5647d0..f3ea42e 100644
--- a/services/core/java/com/android/server/pm/DumpHelper.java
+++ b/services/core/java/com/android/server/pm/DumpHelper.java
@@ -23,6 +23,7 @@
import android.annotation.NonNull;
import android.content.ComponentName;
+import android.content.Context;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
import android.os.Binder;
@@ -160,7 +161,8 @@
pkg = snapshot.resolveInternalPackageName(pkg,
PackageManager.VERSION_CODE_HIGHEST);
- pw.println(mPermissionManager.checkPermission(perm, pkg, user));
+ pw.println(mPermissionManager.checkPermission(
+ pkg, perm, Context.DEVICE_ID_DEFAULT, user));
return;
} else if ("l".equals(cmd) || "libraries".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_LIBS);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5a81a1a..d271adc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2825,7 +2825,8 @@
// NOTE: Can't remove due to unsupported app usage
public int checkPermission(String permName, String pkgName, int userId) {
- return mPermissionManager.checkPermission(pkgName, permName, userId);
+ return mPermissionManager.checkPermission(pkgName, permName, Context.DEVICE_ID_DEFAULT,
+ userId);
}
public String getSdkSandboxPackageName() {
@@ -3425,6 +3426,18 @@
// within these users.
mPermissionManager.restoreDelayedRuntimePermissions(packageName, userId);
+ // Restore default browser setting if it is now installed.
+ String defaultBrowser;
+ synchronized (mLock) {
+ defaultBrowser = mSettings.getPendingDefaultBrowserLPr(userId);
+ }
+ if (Objects.equals(packageName, defaultBrowser)) {
+ mDefaultAppProvider.setDefaultBrowser(packageName, userId);
+ synchronized (mLock) {
+ mSettings.removePendingDefaultBrowserLPw(userId);
+ }
+ }
+
// Persistent preferred activity might have came into effect due to this
// install.
mPreferredActivityHelper.updateDefaultHomeNotLocked(snapshotComputer(), userId);
@@ -6647,7 +6660,7 @@
@Override
public String removeLegacyDefaultBrowserPackageName(int userId) {
synchronized (mLock) {
- return mSettings.removeDefaultBrowserPackageNameLPw(userId);
+ return mSettings.removePendingDefaultBrowserLPw(userId);
}
}
@@ -7523,8 +7536,8 @@
return mDefaultAppProvider.getDefaultBrowser(userId);
}
- void setDefaultBrowser(@Nullable String packageName, boolean async, @UserIdInt int userId) {
- mDefaultAppProvider.setDefaultBrowser(packageName, async, userId);
+ void setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId) {
+ mDefaultAppProvider.setDefaultBrowser(packageName, userId);
}
PackageUsage getPackageUsage() {
diff --git a/services/core/java/com/android/server/pm/PreferredActivityHelper.java b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
index 6e273cf..571aab4 100644
--- a/services/core/java/com/android/server/pm/PreferredActivityHelper.java
+++ b/services/core/java/com/android/server/pm/PreferredActivityHelper.java
@@ -585,7 +585,17 @@
(parser1, userId1) -> {
final String defaultBrowser = Settings.readDefaultApps(parser1);
if (defaultBrowser != null) {
- mPm.setDefaultBrowser(defaultBrowser, false, userId1);
+ final PackageStateInternal packageState = mPm.snapshotComputer()
+ .getPackageStateInternal(defaultBrowser);
+ if (packageState != null
+ && packageState.getUserStateOrDefault(userId1).isInstalled()) {
+ mPm.setDefaultBrowser(defaultBrowser, userId1);
+ } else {
+ synchronized (mPm.mLock) {
+ mPm.mSettings.setPendingDefaultBrowserLPw(defaultBrowser,
+ userId1);
+ }
+ }
}
});
} catch (Exception e) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 87f9126..60c5852 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -518,9 +518,11 @@
private final WatchedArrayMap<String, String> mRenamedPackages =
new WatchedArrayMap<String, String>();
- // For every user, it is used to find the package name of the default Browser App.
+ // For every user, it is used to find the package name of the default browser app pending to be
+ // applied, either on first boot after upgrade, or after backup & restore but before app is
+ // installed.
@Watched
- final WatchedSparseArray<String> mDefaultBrowserApp = new WatchedSparseArray<String>();
+ final WatchedSparseArray<String> mPendingDefaultBrowser = new WatchedSparseArray<>();
// TODO(b/161161364): This seems unused, and is probably not relevant in the new API, but should
// verify.
@@ -593,7 +595,7 @@
mAppIds.registerObserver(mObserver);
mRenamedPackages.registerObserver(mObserver);
mNextAppLinkGeneration.registerObserver(mObserver);
- mDefaultBrowserApp.registerObserver(mObserver);
+ mPendingDefaultBrowser.registerObserver(mObserver);
mPendingPackages.registerObserver(mObserver);
mPastSignatures.registerObserver(mObserver);
mKeySetRefs.registerObserver(mObserver);
@@ -788,7 +790,7 @@
mRenamedPackages.snapshot(r.mRenamedPackages);
mNextAppLinkGeneration.snapshot(r.mNextAppLinkGeneration);
- mDefaultBrowserApp.snapshot(r.mDefaultBrowserApp);
+ mPendingDefaultBrowser.snapshot(r.mPendingDefaultBrowser);
// mReadMessages
mPendingPackages = r.mPendingPackagesSnapshot.snapshot();
mPendingPackagesSnapshot = new SnapshotCache.Sealed<>();
@@ -1509,8 +1511,16 @@
return cpir;
}
- String removeDefaultBrowserPackageNameLPw(int userId) {
- return (userId == UserHandle.USER_ALL) ? null : mDefaultBrowserApp.removeReturnOld(userId);
+ String getPendingDefaultBrowserLPr(int userId) {
+ return mPendingDefaultBrowser.get(userId);
+ }
+
+ void setPendingDefaultBrowserLPw(String defaultBrowser, int userId) {
+ mPendingDefaultBrowser.put(userId, defaultBrowser);
+ }
+
+ String removePendingDefaultBrowserLPw(int userId) {
+ return mPendingDefaultBrowser.removeReturnOld(userId);
}
private File getUserSystemDirectory(int userId) {
@@ -1695,7 +1705,7 @@
throws XmlPullParserException, IOException {
String defaultBrowser = readDefaultApps(parser);
if (defaultBrowser != null) {
- mDefaultBrowserApp.put(userId, defaultBrowser);
+ mPendingDefaultBrowser.put(userId, defaultBrowser);
}
}
@@ -2105,7 +2115,7 @@
void writeDefaultAppsLPr(XmlSerializer serializer, int userId)
throws IllegalArgumentException, IllegalStateException, IOException {
- String defaultBrowser = mDefaultBrowserApp.get(userId);
+ String defaultBrowser = mPendingDefaultBrowser.get(userId);
writeDefaultApps(serializer, defaultBrowser);
}
diff --git a/services/core/java/com/android/server/pm/VerifyingSession.java b/services/core/java/com/android/server/pm/VerifyingSession.java
index 7198de2..3a1fd7c 100644
--- a/services/core/java/com/android/server/pm/VerifyingSession.java
+++ b/services/core/java/com/android/server/pm/VerifyingSession.java
@@ -589,27 +589,14 @@
final PackageVerificationResponse response = new PackageVerificationResponse(
verificationCodeAtTimeout, requiredUid);
- if (streaming) {
- // For streaming installations, count verification timeout from the broadcast.
- startVerificationTimeoutCountdown(verificationId, streaming, response,
- verificationTimeout);
- }
+ startVerificationTimeoutCountdown(verificationId, streaming, response,
+ verificationTimeout);
// Send the intent to the required verification agent, but only start the
// verification timeout after the target BroadcastReceivers have run.
mPm.mContext.sendOrderedBroadcastAsUser(requiredIntent, verifierUser,
receiverPermission, AppOpsManager.OP_NONE, options.toBundle(),
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!streaming) {
- // For NON-streaming installations, count verification timeout from
- // the broadcast was processed by all receivers.
- startVerificationTimeoutCountdown(verificationId, streaming,
- response, verificationTimeout);
- }
- }
- }, null, 0, null, null);
+ null, null, 0, null, null);
}
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index dbe2d54..7609073 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -218,9 +218,12 @@
}
}
- private int checkPermission(String pkgName, String permName, @UserIdInt int userId) {
+ @Override
+ @PackageManager.PermissionResult
+ public int checkPermission(String packageName, String permissionName, int deviceId,
+ @UserIdInt int userId) {
// Not using Objects.requireNonNull() here for compatibility reasons.
- if (pkgName == null || permName == null) {
+ if (packageName == null || permissionName == null) {
return PackageManager.PERMISSION_DENIED;
}
@@ -230,15 +233,18 @@
}
if (checkPermissionDelegate == null) {
- return mPermissionManagerServiceImpl.checkPermission(pkgName, permName, userId);
+ return mPermissionManagerServiceImpl.checkPermission(
+ packageName, permissionName, userId);
}
- return checkPermissionDelegate.checkPermission(pkgName, permName, userId,
+ return checkPermissionDelegate.checkPermission(packageName, permissionName, userId,
mPermissionManagerServiceImpl::checkPermission);
}
- private int checkUidPermission(int uid, String permName) {
+ @Override
+ @PackageManager.PermissionResult
+ public int checkUidPermission(int uid, String permissionName, int deviceId) {
// Not using Objects.requireNonNull() here for compatibility reasons.
- if (permName == null) {
+ if (permissionName == null) {
return PackageManager.PERMISSION_DENIED;
}
@@ -248,9 +254,9 @@
}
if (checkPermissionDelegate == null) {
- return mPermissionManagerServiceImpl.checkUidPermission(uid, permName);
+ return mPermissionManagerServiceImpl.checkUidPermission(uid, permissionName);
}
- return checkPermissionDelegate.checkUidPermission(uid, permName,
+ return checkPermissionDelegate.checkUidPermission(uid, permissionName,
mPermissionManagerServiceImpl::checkUidPermission);
}
@@ -502,14 +508,15 @@
}
@Override
- public int getPermissionFlags(String packageName, String permissionName, int userId) {
+ public int getPermissionFlags(String packageName, String permissionName, int deviceId,
+ int userId) {
return mPermissionManagerServiceImpl
.getPermissionFlags(packageName, permissionName, userId);
}
@Override
public void updatePermissionFlags(String packageName, String permissionName, int flagMask,
- int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
+ int flagValues, boolean checkAdjustPolicyFlagPermission, int deviceId, int userId) {
mPermissionManagerServiceImpl.updatePermissionFlags(packageName, permissionName, flagMask,
flagValues, checkAdjustPolicyFlagPermission, userId);
}
@@ -551,15 +558,16 @@
}
@Override
- public void grantRuntimePermission(String packageName, String permissionName, int userId) {
+ public void grantRuntimePermission(String packageName, String permissionName, int deviceId,
+ int userId) {
mPermissionManagerServiceImpl.grantRuntimePermission(packageName, permissionName, userId);
}
@Override
- public void revokeRuntimePermission(String packageName, String permissionName, int userId,
- String reason) {
- mPermissionManagerServiceImpl.revokeRuntimePermission(packageName, permissionName, userId,
- reason);
+ public void revokeRuntimePermission(String packageName, String permissionName, int deviceId,
+ int userId, String reason) {
+ mPermissionManagerServiceImpl.revokeRuntimePermission(packageName, permissionName,
+ userId, reason);
}
@Override
@@ -570,14 +578,14 @@
@Override
public boolean shouldShowRequestPermissionRationale(String packageName, String permissionName,
- int userId) {
+ int deviceId, int userId) {
return mPermissionManagerServiceImpl.shouldShowRequestPermissionRationale(packageName,
permissionName, userId);
}
@Override
public boolean isPermissionRevokedByPolicy(String packageName, String permissionName,
- int userId) {
+ int deviceId, int userId) {
return mPermissionManagerServiceImpl
.isPermissionRevokedByPolicy(packageName, permissionName, userId);
}
@@ -592,14 +600,14 @@
private class PermissionManagerServiceInternalImpl implements PermissionManagerServiceInternal {
@Override
public int checkPermission(@NonNull String packageName, @NonNull String permissionName,
- @UserIdInt int userId) {
+ int deviceId, @UserIdInt int userId) {
return PermissionManagerService.this.checkPermission(packageName, permissionName,
- userId);
+ deviceId, userId);
}
@Override
- public int checkUidPermission(int uid, @NonNull String permissionName) {
- return PermissionManagerService.this.checkUidPermission(uid, permissionName);
+ public int checkUidPermission(int uid, @NonNull String permissionName, int deviceId) {
+ return PermissionManagerService.this.checkUidPermission(uid, permissionName, deviceId);
}
@Override
@@ -805,6 +813,7 @@
public void resetRuntimePermissions(@NonNull AndroidPackage pkg, @UserIdInt int userId) {
mPermissionManagerServiceImpl.resetRuntimePermissions(pkg, userId);
}
+
@Override
public void resetRuntimePermissionsForUser(@UserIdInt int userId) {
mPermissionManagerServiceImpl.resetRuntimePermissionsForUser(userId);
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index cf2b69c..98adeb6 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -46,12 +46,13 @@
*
* @param packageName the name of the package you are checking against
* @param permissionName the name of the permission you are checking for
+ * @param deviceId the device ID
* @param userId the user ID
* @return {@code PERMISSION_GRANTED} if the permission is granted, or {@code PERMISSION_DENIED}
* otherwise
*/
//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
- int checkPermission(@NonNull String packageName, @NonNull String permissionName,
+ int checkPermission(@NonNull String packageName, @NonNull String permissionName, int deviceId,
@UserIdInt int userId);
/**
@@ -59,11 +60,12 @@
*
* @param uid the UID
* @param permissionName the name of the permission you are checking for
+ * @param deviceId the device for which you are checking the permission
* @return {@code PERMISSION_GRANTED} if the permission is granted, or {@code PERMISSION_DENIED}
* otherwise
*/
//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
- int checkUidPermission(int uid, @NonNull String permissionName);
+ int checkUidPermission(int uid, @NonNull String permissionName, int deviceId);
/**
* Get whether permission review is required for a package.
@@ -73,8 +75,7 @@
* @return whether permission review is required
*/
//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
- boolean isPermissionsReviewRequired(@NonNull String packageName,
- @UserIdInt int userId);
+ boolean isPermissionsReviewRequired(@NonNull String packageName, @UserIdInt int userId);
/**
* Reset the runtime permission state changes for a package.
@@ -85,8 +86,7 @@
* @param userId the user ID
*/
//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
- void resetRuntimePermissions(@NonNull AndroidPackage pkg,
- @UserIdInt int userId);
+ void resetRuntimePermissions(@NonNull AndroidPackage pkg, @UserIdInt int userId);
/**
* Reset the runtime permission state changes for all packages in a user.
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 2679fce..d6e35e8 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -1421,8 +1421,8 @@
}
boolean hasCreatedNotificationChannels = mNotificationManager
.getNumNotificationChannelsForPackage(pkgName, uid, true) > 0;
- boolean granted = mPermissionManagerInternal.checkUidPermission(uid, POST_NOTIFICATIONS)
- == PackageManager.PERMISSION_GRANTED;
+ boolean granted = mPermissionManagerInternal.checkUidPermission(uid, POST_NOTIFICATIONS,
+ Context.DEVICE_ID_DEFAULT) == PackageManager.PERMISSION_GRANTED;
int flags = mPackageManager.getPermissionFlags(POST_NOTIFICATIONS, pkgName, user);
boolean explicitlySet = (flags & PermissionManager.EXPLICIT_SET_FLAGS) != 0;
return !granted && hasCreatedNotificationChannels && !explicitlySet;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 6f5125c..402bb59 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3304,8 +3304,10 @@
minLinearBrightness, maxLinearBrightness);
mDisplayManager.setBrightness(screenDisplayId, adjustedLinearBrightness);
- startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
- UserHandle.CURRENT_OR_SELF);
+ Intent intent = new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION);
+ intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true);
+ startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
}
return true;
case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN:
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index a1199d9..6747cea 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -91,8 +91,6 @@
CredentialManagerService, CredentialManagerServiceImpl> {
private static final String TAG = "CredManSysService";
- private static final String DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API =
- "enable_credential_description_api";
private static final String PERMISSION_DENIED_ERROR = "permission_denied";
private static final String PERMISSION_DENIED_WRITE_SECURE_SETTINGS_ERROR =
"Caller is missing WRITE_SECURE_SETTINGS permission";
@@ -311,14 +309,7 @@
}
public static boolean isCredentialDescriptionApiEnabled() {
- final long origId = Binder.clearCallingIdentity();
- try {
- return DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API,
- false);
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
+ return true;
}
@SuppressWarnings("GuardedBy") // ErrorProne requires initiateProviderSessionForRequestLocked
diff --git a/services/permission/TEST_MAPPING b/services/permission/TEST_MAPPING
new file mode 100644
index 0000000..579d4e3
--- /dev/null
+++ b/services/permission/TEST_MAPPING
@@ -0,0 +1,71 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsPermissionTestCases",
+ "options": [
+ {
+ "include-filter": "android.permission.cts.BackgroundPermissionsTest"
+ },
+ {
+ "include-filter": "android.permission.cts.SplitPermissionTest"
+ },
+ {
+ "include-filter": "android.permission.cts.PermissionFlagsTest"
+ },
+ {
+ "include-filter": "android.permission.cts.SharedUidPermissionsTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsAppSecurityHostTestCases",
+ "options": [
+ {
+ "include-filter": "android.appsecurity.cts.AppSecurityTests#rebootWithDuplicatePermission"
+ }
+ ]
+ },
+ {
+ "name": "CtsPermissionPolicyTestCases",
+ "options": [
+ {
+ "include-filter": "android.permissionpolicy.cts.RestrictedPermissionsTest"
+ },
+ {
+ "include-filter": "android.permission.cts.PermissionMaxSdkVersionTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsStatsdHostTestCases",
+ "options": [
+ {
+ "include-filter": "android.cts.statsd.atom.UidAtomTests#testDangerousPermissionState"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsAppSecurityHostTestCases",
+ "options": [
+ {
+ "include-filter": "android.appsecurity.cts.AppSecurityTests#testPermissionDiffCert"
+ }
+ ]
+ },
+ {
+ "name": "CtsPermissionTestCases",
+ "options": [
+ {
+ "include-filter": "android.permission.cts.PermissionUpdateListenerTest"
+ }
+ ]
+ }
+ ],
+ "imports": [
+ {
+ "path": "vendor/xts/gts-tests/tests/permission"
+ }
+ ]
+}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
index 0ed863e..ffd7332 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -126,6 +126,7 @@
protected InputMethodManagerService mInputMethodManagerService;
protected ServiceThread mServiceThread;
protected boolean mIsLargeScreen;
+ private InputManagerGlobal.TestSession mInputManagerGlobalSession;
@BeforeClass
public static void setupClass() {
@@ -186,7 +187,7 @@
// Injecting and mocked InputMethodBindingController and InputMethod.
mMockInputMethodInvoker = IInputMethodInvoker.create(mMockInputMethod);
- InputManagerGlobal.resetInstance(mMockIInputManager);
+ mInputManagerGlobalSession = InputManagerGlobal.createTestSession(mMockIInputManager);
synchronized (ImfLock.class) {
when(mMockInputMethodBindingController.getCurMethod())
.thenReturn(mMockInputMethodInvoker);
@@ -262,6 +263,10 @@
if (mMockingSession != null) {
mMockingSession.finishMocking();
}
+
+ if (mInputManagerGlobalSession != null) {
+ mInputManagerGlobalSession.close();
+ }
LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
index fe23eee..bb91939 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
@@ -2435,10 +2435,11 @@
private void setPermissionState(String packageName, int uid, String perm, boolean granted) {
doReturn(granted ? PERMISSION_GRANTED : PERMISSION_DENIED)
.when(mPermissionManagerServiceInternal)
- .checkUidPermission(uid, perm);
+ .checkUidPermission(uid, perm, Context.DEVICE_ID_DEFAULT);
doReturn(granted ? PERMISSION_GRANTED : PERMISSION_DENIED)
.when(mPermissionManagerServiceInternal)
- .checkPermission(packageName, perm, UserHandle.getUserId(uid));
+ .checkPermission(
+ packageName, perm, Context.DEVICE_ID_DEFAULT, UserHandle.getUserId(uid));
try {
doReturn(granted ? PERMISSION_GRANTED : PERMISSION_DENIED)
.when(mIActivityManager)
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java
index 6f2cca5..4c633a1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageMonitorCallbackHelperTest.java
@@ -221,6 +221,19 @@
assertThat(pkgNames[0]).isEqualTo(FAKE_PACKAGE_NAME);
}
+ @Test
+ public void testPackageMonitorCallback_onUserRemoved_callbackNotCalled() throws Exception {
+ IRemoteCallback callback = createMockPackageMonitorCallback();
+ mPackageMonitorCallbackHelper.registerPackageMonitorCallback(callback, 10 /* userId */);
+
+ mPackageMonitorCallbackHelper.onUserRemoved(10);
+ mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_ADDED,
+ FAKE_PACKAGE_NAME, createFakeBundle(), new int[]{10} /* userIds */,
+ null /* instantUserIds */);
+
+ verify(callback, after(WAIT_CALLBACK_CALLED_IN_MS).never()).sendResult(any());
+ }
+
private IRemoteCallback createMockPackageMonitorCallback() {
return spy(new IRemoteCallback.Stub() {
@Override
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
index 6c6b608..7e6883b 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
@@ -44,6 +44,7 @@
import com.android.server.LocalServices;
import com.android.server.input.InputManagerInternal;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -93,6 +94,11 @@
threadVerifier);
}
+ @After
+ public void tearDown() {
+ mInputManagerMockHelper.tearDown();
+ }
+
@Test
public void registerInputDevice_deviceCreation_hasDeviceId() {
final IBinder device1Token = new Binder("device1");
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java b/services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java
index 5cadc0a..3722247 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java
@@ -46,6 +46,7 @@
private final TestableLooper mTestableLooper;
private final InputController.NativeWrapper mNativeWrapperMock;
private final IInputManager mIInputManagerMock;
+ private final InputManagerGlobal.TestSession mInputManagerGlobalSession;
private final List<InputDevice> mDevices = new ArrayList<>();
private IInputDevicesChangedListener mDevicesChangedListener;
@@ -77,7 +78,13 @@
// Set a new instance of InputManager for testing that uses the IInputManager mock as the
// interface to the server.
- InputManagerGlobal.resetInstance(mIInputManagerMock);
+ mInputManagerGlobalSession = InputManagerGlobal.createTestSession(mIInputManagerMock);
+ }
+
+ public void tearDown() {
+ if (mInputManagerGlobalSession != null) {
+ mInputManagerGlobalSession.close();
+ }
}
private long handleNativeOpenInputDevice(InvocationOnMock inv) {
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index 4b801bc..d76d615 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -376,6 +376,7 @@
@After
public void tearDown() {
mDeviceImpl.close();
+ mInputManagerMockHelper.tearDown();
}
@Test
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 ad1c60e..7478778 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -46,7 +46,6 @@
import static android.app.admin.DevicePolicyManager.WIFI_SECURITY_OPEN;
import static android.app.admin.DevicePolicyManager.WIFI_SECURITY_PERSONAL;
import static android.app.admin.DevicePolicyManager.WIPE_EUICC;
-import static android.app.admin.PasswordMetrics.computeForPasswordOrPin;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
import static android.location.LocationManager.FUSED_PROVIDER;
import static android.location.LocationManager.GPS_PROVIDER;
@@ -5479,8 +5478,7 @@
reset(mContext.spiedContext);
- PasswordMetrics passwordMetricsNoSymbols = computeForPasswordOrPin(
- "abcdXYZ5".getBytes(), /* isPin */ false);
+ PasswordMetrics passwordMetricsNoSymbols = metricsForPassword("abcdXYZ5");
setActivePasswordState(passwordMetricsNoSymbols);
assertThat(dpm.isActivePasswordSufficient()).isTrue();
@@ -5507,8 +5505,7 @@
reset(mContext.spiedContext);
assertThat(dpm.isActivePasswordSufficient()).isFalse();
- PasswordMetrics passwordMetricsWithSymbols = computeForPasswordOrPin(
- "abcd.XY5".getBytes(), /* isPin */ false);
+ PasswordMetrics passwordMetricsWithSymbols = metricsForPassword("abcd.XY5");
setActivePasswordState(passwordMetricsWithSymbols);
assertThat(dpm.isActivePasswordSufficient()).isTrue();
@@ -5564,7 +5561,7 @@
parentDpm.setRequiredPasswordComplexity(PASSWORD_COMPLEXITY_MEDIUM);
when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
- .thenReturn(computeForPasswordOrPin("184342".getBytes(), /* isPin */ true));
+ .thenReturn(metricsForPin("184342"));
// Numeric password is compliant with current requirement (QUALITY_NUMERIC set explicitly
// on the parent admin)
@@ -5685,7 +5682,7 @@
// Set a work challenge and verify profile.isActivePasswordSufficient is now true
when(getServices().lockSettingsInternal.getUserPasswordMetrics(managedProfileUserId))
- .thenReturn(computeForPasswordOrPin("abcdXYZ5".getBytes(), /* isPin */ false));
+ .thenReturn(metricsForPassword("abcdXYZ5"));
assertThat(dpm.isActivePasswordSufficient()).isTrue();
assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
}
@@ -5710,7 +5707,7 @@
// Set a work challenge and verify profile.isActivePasswordSufficient is now true
when(getServices().lockSettingsInternal.getUserPasswordMetrics(managedProfileUserId))
- .thenReturn(computeForPasswordOrPin("5156".getBytes(), /* isPin */ true));
+ .thenReturn(metricsForPin("5156"));
assertThat(dpm.isActivePasswordSufficient()).isTrue();
assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
}
@@ -5735,7 +5732,7 @@
// Set a device lockscreen and verify parent.isActivePasswordSufficient is now true
when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
- .thenReturn(computeForPasswordOrPin("acbdXYZ5".getBytes(), /* isPin */ false));
+ .thenReturn(metricsForPassword("acbdXYZ5"));
assertThat(dpm.isActivePasswordSufficient()).isTrue();
assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
}
@@ -5758,7 +5755,7 @@
// Set a device lockscreen and verify parent.isActivePasswordSufficient is now true
when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
- .thenReturn(computeForPasswordOrPin("1234".getBytes(), /* isPin */ true));
+ .thenReturn(metricsForPin("1234"));
assertThat(dpm.isActivePasswordSufficient()).isTrue();
assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
}
@@ -5783,7 +5780,7 @@
// Set a device lockscreen and verify {profile, parent}.isActivePasswordSufficient is true
when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
- .thenReturn(computeForPasswordOrPin("abcdXYZ5".getBytes(), /* isPin */ false));
+ .thenReturn(metricsForPassword("abcdXYZ5"));
assertThat(dpm.isActivePasswordSufficient()).isTrue();
assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
}
@@ -5806,7 +5803,7 @@
// Set a device lockscreen and verify {profile, parent}.isActivePasswordSufficient is true
when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
- .thenReturn(computeForPasswordOrPin("51567548".getBytes(), /* isPin */ true));
+ .thenReturn(metricsForPin("51567548"));
assertThat(dpm.isActivePasswordSufficient()).isTrue();
assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
}
@@ -5831,7 +5828,7 @@
// Set a device lockscreen and verify {profile, parent}.isActivePasswordSufficient is true
when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
- .thenReturn(computeForPasswordOrPin("abcdXYZ5".getBytes(), /* isPin */ false));
+ .thenReturn(metricsForPassword("abcdXYZ5"));
assertThat(dpm.isActivePasswordSufficient()).isTrue();
assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
}
@@ -5854,7 +5851,7 @@
// Set a device lockscreen and verify {profile, parent}.isActivePasswordSufficient is true
when(getServices().lockSettingsInternal.getUserPasswordMetrics(UserHandle.USER_SYSTEM))
- .thenReturn(computeForPasswordOrPin("5156".getBytes(), /* isPin */ true));
+ .thenReturn(metricsForPin("5156"));
assertThat(dpm.isActivePasswordSufficient()).isTrue();
assertThat(parentDpm.isActivePasswordSufficient()).isTrue();
}
@@ -6909,7 +6906,7 @@
.thenReturn(CALLER_USER_HANDLE);
when(getServices().lockSettingsInternal
.getUserPasswordMetrics(CALLER_USER_HANDLE))
- .thenReturn(computeForPasswordOrPin("asdf".getBytes(), /* isPin */ false));
+ .thenReturn(metricsForPassword("asdf"));
assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_MEDIUM);
}
@@ -6929,10 +6926,10 @@
when(getServices().lockSettingsInternal
.getUserPasswordMetrics(CALLER_USER_HANDLE))
- .thenReturn(computeForPasswordOrPin("asdf".getBytes(), /* isPin */ false));
+ .thenReturn(metricsForPassword("asdf"));
when(getServices().lockSettingsInternal
.getUserPasswordMetrics(parentUser.id))
- .thenReturn(computeForPasswordOrPin("parentUser".getBytes(), /* isPin */ false));
+ .thenReturn(metricsForPassword("parentUser"));
assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_HIGH);
}
@@ -7654,15 +7651,13 @@
assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_NONE);
reset(mContext.spiedContext);
- PasswordMetrics passwordMetricsNoSymbols = computeForPasswordOrPin(
- "1234".getBytes(), /* isPin */ true);
+ PasswordMetrics passwordMetricsNoSymbols = metricsForPin("1234");
setActivePasswordState(passwordMetricsNoSymbols);
assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_LOW);
assertThat(dpm.isActivePasswordSufficient()).isFalse();
reset(mContext.spiedContext);
- passwordMetricsNoSymbols = computeForPasswordOrPin(
- "84125312943a".getBytes(), /* isPin */ false);
+ passwordMetricsNoSymbols = metricsForPassword("84125312943a");
setActivePasswordState(passwordMetricsNoSymbols);
assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_HIGH);
// using isActivePasswordSufficient
@@ -8837,4 +8832,12 @@
assumeTrue("device doesn't support deprecated password APIs",
isDeprecatedPasswordApisSupported());
}
+
+ private static PasswordMetrics metricsForPassword(String password) {
+ return PasswordMetrics.computeForCredential(LockscreenCredential.createPassword(password));
+ }
+
+ private static PasswordMetrics metricsForPin(String pin) {
+ return PasswordMetrics.computeForCredential(LockscreenCredential.createPin(pin));
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/input/OWNERS b/services/tests/servicestests/src/com/android/server/input/OWNERS
deleted file mode 100644
index 6e9aa1d..0000000
--- a/services/tests/servicestests/src/com/android/server/input/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-include /services/core/java/com/android/server/input/OWNERS
-
diff --git a/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java
index ba91647..daf18ed 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java
@@ -402,7 +402,7 @@
assertEquals(0,
mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
doReturn(PackageManager.PERMISSION_DENIED).when(mPermissionManager).checkPermission(
- anyString(), anyString(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt());
generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED,
USER_ID_1, INSTALLER_NAME_1, 0);
mTestLooper.dispatchAll();
@@ -415,7 +415,7 @@
assertEquals(0,
mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission(
- anyString(), anyString(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt());
generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED,
USER_ID_1, INSTALLER_NAME_1, 0);
mTestLooper.dispatchAll();
@@ -428,7 +428,7 @@
assertEquals(0,
mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission(
- anyString(), anyString(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt());
generateUsageEvent(UsageEvents.Event.USER_INTERACTION,
USER_ID_1, INSTALLER_NAME_1, 0);
mTestLooper.dispatchAll();
@@ -441,7 +441,7 @@
assertEquals(0,
mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission(
- anyString(), anyString(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt());
generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED,
USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1);
mTestLooper.dispatchAll();
@@ -464,7 +464,7 @@
assertEquals(0,
mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission(
- anyString(), anyString(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt());
generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED,
USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1);
generateUsageEvent(Event.ACTIVITY_STOPPED,
@@ -489,7 +489,7 @@
assertEquals(0,
mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission(
- anyString(), anyString(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt());
generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED,
USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1);
generateUsageEvent(Event.ACTIVITY_STOPPED,
@@ -520,7 +520,7 @@
assertEquals(0,
mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps());
doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission(
- anyString(), anyString(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt());
generateUsageEvent(Event.ACTIVITY_STOPPED,
USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1);
mTestLooper.dispatchAll();
@@ -605,7 +605,7 @@
// So it's not a background install. Thus, it's null for the return of
// mBackgroundInstallControlService.getBackgroundInstalledPackages()
doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission(
- anyString(), anyString(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt());
generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED,
USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1);
generateUsageEvent(Event.ACTIVITY_STOPPED,
@@ -651,7 +651,7 @@
// it's a background install. Thus, it's not null for the return of
// mBackgroundInstallControlService.getBackgroundInstalledPackages()
doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission(
- anyString(), anyString(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt());
generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED,
USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2);
generateUsageEvent(Event.ACTIVITY_STOPPED,
@@ -701,7 +701,7 @@
// it's a background install. Thus, it's not null for the return of
// mBackgroundInstallControlService.getBackgroundInstalledPackages()
doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission(
- anyString(), anyString(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt());
generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED,
USER_ID_2, INSTALLER_NAME_2, USAGE_EVENT_TIMESTAMP_2);
generateUsageEvent(Event.ACTIVITY_STOPPED,
@@ -752,7 +752,7 @@
// as a background install. Since we do not want to treat side-loaded apps as background
// install getBackgroundInstalledPackages() is expected to return null
doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission(
- anyString(), anyString(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt());
generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED,
USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2);
generateUsageEvent(Event.ACTIVITY_STOPPED,
@@ -801,7 +801,7 @@
// as a background install. Since we do not want to treat side-loaded apps as background
// install getBackgroundInstalledPackages() is expected to return null
doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission(
- anyString(), anyString(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt());
generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED,
USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2);
generateUsageEvent(Event.ACTIVITY_STOPPED,
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
index 2ab79fc..f3c17a8 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
@@ -77,6 +77,7 @@
private TestLooper mTestLooper;
private ContextWrapper mContextSpy;
+ private InputManagerGlobal.TestSession mInputManagerGlobalSession;
private InputManager mInputManager;
private InputDeviceDelegate mInputDeviceDelegate;
private IInputDevicesChangedListener mIInputDevicesChangedListener;
@@ -84,7 +85,7 @@
@Before
public void setUp() throws Exception {
mTestLooper = new TestLooper();
- InputManagerGlobal.resetInstance(mIInputManagerMock);
+ mInputManagerGlobalSession = InputManagerGlobal.createTestSession(mIInputManagerMock);
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
mInputManager = new InputManager(mContextSpy);
@@ -100,7 +101,9 @@
@After
public void tearDown() throws Exception {
- InputManagerGlobal.clearInstance();
+ if (mInputManagerGlobalSession != null) {
+ mInputManagerGlobalSession.close();
+ }
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index c805fc5..9a911f4 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -186,14 +186,14 @@
private VirtualDeviceManagerInternal.VirtualDisplayListener mRegisteredVirtualDisplayListener;
private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener
mRegisteredAppsOnVirtualDeviceListener;
-
+ private InputManagerGlobal.TestSession mInputManagerGlobalSession;
private InputManager mInputManager;
@Before
public void setUp() throws Exception {
mTestLooper = new TestLooper();
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
- InputManagerGlobal.resetInstance(mIInputManagerMock);
+ mInputManagerGlobalSession = InputManagerGlobal.createTestSession(mIInputManagerMock);
mVibrationConfig = new VibrationConfig(mContextSpy.getResources());
ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
@@ -268,7 +268,9 @@
LocalServices.removeServiceForTest(PowerManagerInternal.class);
// Ignore potential exceptions about the looper having never dispatched any messages.
mTestLooper.stopAutoDispatchAndIgnoreExceptions();
- InputManagerGlobal.clearInstance();
+ if (mInputManagerGlobalSession != null) {
+ mInputManagerGlobalSession.close();
+ }
}
private VibratorManagerService createSystemReadyService() {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 30180e8..7e81ef2 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -11269,7 +11269,6 @@
// Given: a call notification has the flag FLAG_ONGOING_EVENT set
// feature flag: ALLOW_DISMISS_ONGOING is on
mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
- when(mTelecomManager.isInManagedCall()).thenReturn(true);
Person person = new Person.Builder()
.setName("caller")
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
index 539f329..318f932 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
@@ -246,10 +246,10 @@
mPermissionHelper.setNotificationPermission("pkg", 10, true, true);
verify(mPermManager).grantRuntimePermission(
- "pkg", Manifest.permission.POST_NOTIFICATIONS, 10);
+ "pkg", Manifest.permission.POST_NOTIFICATIONS, Context.DEVICE_ID_DEFAULT, 10);
verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS,
USER_FLAG_MASK | FLAG_PERMISSION_GRANTED_BY_DEFAULT,
- FLAG_PERMISSION_USER_SET, true, 10);
+ FLAG_PERMISSION_USER_SET, true, Context.DEVICE_ID_DEFAULT, 10);
}
@Test
@@ -259,16 +259,16 @@
.thenReturn(PERMISSION_DENIED);
when(mPermManager.getPermissionFlags(anyString(),
eq(Manifest.permission.POST_NOTIFICATIONS),
- anyInt())).thenReturn(FLAG_PERMISSION_GRANTED_BY_DEFAULT);
+ anyInt(), anyInt())).thenReturn(FLAG_PERMISSION_GRANTED_BY_DEFAULT);
PermissionHelper.PackagePermission pkgPerm = new PermissionHelper.PackagePermission(
"pkg", 10, true, false);
mPermissionHelper.setNotificationPermission(pkgPerm);
verify(mPermManager).grantRuntimePermission(
- "pkg", Manifest.permission.POST_NOTIFICATIONS, 10);
+ "pkg", Manifest.permission.POST_NOTIFICATIONS, Context.DEVICE_ID_DEFAULT, 10);
verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS,
USER_FLAG_MASK | FLAG_PERMISSION_GRANTED_BY_DEFAULT,
- FLAG_PERMISSION_USER_SET, true, 10);
+ FLAG_PERMISSION_USER_SET, true, Context.DEVICE_ID_DEFAULT, 10);
}
@Test
@@ -279,10 +279,11 @@
mPermissionHelper.setNotificationPermission("pkg", 10, false, true);
verify(mPermManager).revokeRuntimePermission(
- eq("pkg"), eq(Manifest.permission.POST_NOTIFICATIONS), eq(10), anyString());
+ eq("pkg"), eq(Manifest.permission.POST_NOTIFICATIONS),
+ eq(Context.DEVICE_ID_DEFAULT), eq(10), anyString());
verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS,
USER_FLAG_MASK | FLAG_PERMISSION_GRANTED_BY_DEFAULT,
- FLAG_PERMISSION_USER_SET, true, 10);
+ FLAG_PERMISSION_USER_SET, true, Context.DEVICE_ID_DEFAULT, 10);
}
@Test
@@ -293,9 +294,9 @@
mPermissionHelper.setNotificationPermission("pkg", 10, true, false);
verify(mPermManager).grantRuntimePermission(
- "pkg", Manifest.permission.POST_NOTIFICATIONS, 10);
+ "pkg", Manifest.permission.POST_NOTIFICATIONS, Context.DEVICE_ID_DEFAULT, 10);
verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS,
- USER_FLAG_MASK, 0, true, 10);
+ USER_FLAG_MASK, 0, true, Context.DEVICE_ID_DEFAULT, 10);
}
@Test
@@ -306,36 +307,37 @@
mPermissionHelper.setNotificationPermission("pkg", 10, false, false);
verify(mPermManager).revokeRuntimePermission(
- eq("pkg"), eq(Manifest.permission.POST_NOTIFICATIONS), eq(10), anyString());
+ eq("pkg"), eq(Manifest.permission.POST_NOTIFICATIONS),
+ eq(Context.DEVICE_ID_DEFAULT), eq(10), anyString());
verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS,
USER_FLAG_MASK | FLAG_PERMISSION_GRANTED_BY_DEFAULT, 0,
- true, 10);
+ true, Context.DEVICE_ID_DEFAULT, 10);
}
@Test
public void testSetNotificationPermission_SystemFixedPermNotSet() throws Exception {
when(mPermManager.getPermissionFlags(anyString(),
eq(Manifest.permission.POST_NOTIFICATIONS),
- anyInt())).thenReturn(FLAG_PERMISSION_SYSTEM_FIXED);
+ anyInt(), anyInt())).thenReturn(FLAG_PERMISSION_SYSTEM_FIXED);
mPermissionHelper.setNotificationPermission("pkg", 10, false, true);
verify(mPermManager, never()).revokeRuntimePermission(
- anyString(), anyString(), anyInt(), anyString());
+ anyString(), anyString(), anyInt(), anyInt(), anyString());
verify(mPermManager, never()).updatePermissionFlags(
- anyString(), anyString(), anyInt(), anyInt(), anyBoolean(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt(), anyBoolean(), anyInt(), anyInt());
}
@Test
public void testSetNotificationPermission_PolicyFixedPermNotSet() throws Exception {
when(mPermManager.getPermissionFlags(anyString(),
eq(Manifest.permission.POST_NOTIFICATIONS),
- anyInt())).thenReturn(FLAG_PERMISSION_POLICY_FIXED);
+ anyInt(), anyInt())).thenReturn(FLAG_PERMISSION_POLICY_FIXED);
mPermissionHelper.setNotificationPermission("pkg", 10, false, true);
verify(mPermManager, never()).revokeRuntimePermission(
- anyString(), anyString(), anyInt(), anyString());
+ anyString(), anyString(), anyInt(), anyInt(), anyString());
verify(mPermManager, never()).updatePermissionFlags(
- anyString(), anyString(), anyInt(), anyInt(), anyBoolean(), anyInt());
+ anyString(), anyString(), anyInt(), anyInt(), anyBoolean(), anyInt(), anyInt());
}
@Test
@@ -345,7 +347,7 @@
mPermissionHelper.setNotificationPermission("pkg", 10, true, false);
verify(mPermManager, never()).grantRuntimePermission(
- "pkg", Manifest.permission.POST_NOTIFICATIONS, 10);
+ "pkg", Manifest.permission.POST_NOTIFICATIONS, Context.DEVICE_ID_DEFAULT, 10);
}
@Test
@@ -355,7 +357,8 @@
mPermissionHelper.setNotificationPermission("pkg", 10, false, false);
verify(mPermManager, never()).revokeRuntimePermission(
- eq("pkg"), eq(Manifest.permission.POST_NOTIFICATIONS), eq(10), anyString());
+ eq("pkg"), eq(Manifest.permission.POST_NOTIFICATIONS),
+ eq(Context.DEVICE_ID_DEFAULT), eq(10), anyString());
}
@Test
@@ -374,26 +377,27 @@
verify(mContext, never()).checkPermission(
eq(Manifest.permission.POST_NOTIFICATIONS), eq(-1), eq(testUid));
verify(mPermManager, never()).revokeRuntimePermission(
- eq("pkg"), eq(Manifest.permission.POST_NOTIFICATIONS), eq(10), anyString());
+ eq("pkg"), eq(Manifest.permission.POST_NOTIFICATIONS),
+ eq(Context.DEVICE_ID_DEFAULT), eq(10), anyString());
}
@Test
public void testIsPermissionFixed() throws Exception {
when(mPermManager.getPermissionFlags(anyString(),
eq(Manifest.permission.POST_NOTIFICATIONS),
- anyInt())).thenReturn(FLAG_PERMISSION_USER_SET);
+ anyInt(), anyInt())).thenReturn(FLAG_PERMISSION_USER_SET);
assertThat(mPermissionHelper.isPermissionFixed("pkg", 0)).isFalse();
when(mPermManager.getPermissionFlags(anyString(),
- eq(Manifest.permission.POST_NOTIFICATIONS),
+ eq(Manifest.permission.POST_NOTIFICATIONS), anyInt(),
anyInt())).thenReturn(FLAG_PERMISSION_USER_SET|FLAG_PERMISSION_POLICY_FIXED);
assertThat(mPermissionHelper.isPermissionFixed("pkg", 0)).isTrue();
when(mPermManager.getPermissionFlags(anyString(),
eq(Manifest.permission.POST_NOTIFICATIONS),
- anyInt())).thenReturn(FLAG_PERMISSION_SYSTEM_FIXED);
+ anyInt(), anyInt())).thenReturn(FLAG_PERMISSION_SYSTEM_FIXED);
assertThat(mPermissionHelper.isPermissionFixed("pkg", 0)).isTrue();
}
@@ -434,13 +438,14 @@
.thenReturn(requesting);
// 2 and 3 are user-set permissions
- when(mPermManager.getPermissionFlags(
- "first", Manifest.permission.POST_NOTIFICATIONS, userId)).thenReturn(0);
- when(mPermManager.getPermissionFlags(
- "second", Manifest.permission.POST_NOTIFICATIONS, userId))
+ when(mPermManager.getPermissionFlags("first", Manifest.permission.POST_NOTIFICATIONS,
+ Context.DEVICE_ID_DEFAULT, userId))
+ .thenReturn(0);
+ when(mPermManager.getPermissionFlags("second", Manifest.permission.POST_NOTIFICATIONS,
+ Context.DEVICE_ID_DEFAULT, userId))
.thenReturn(FLAG_PERMISSION_USER_SET);
- when(mPermManager.getPermissionFlags(
- "third", Manifest.permission.POST_NOTIFICATIONS, userId))
+ when(mPermManager.getPermissionFlags("third", Manifest.permission.POST_NOTIFICATIONS,
+ Context.DEVICE_ID_DEFAULT, userId))
.thenReturn(FLAG_PERMISSION_USER_SET);
Map<Pair<Integer, String>, Pair<Boolean, Boolean>> expected =
diff --git a/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java b/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
index 48d050c..bb0d30a 100644
--- a/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
+++ b/tests/ChoreographerTests/src/main/java/android/view/choreographertests/AttachedChoreographerTest.java
@@ -22,9 +22,9 @@
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import android.Manifest;
-import android.app.compat.CompatChanges;
import android.hardware.display.DisplayManager;
import android.os.Looper;
import android.support.test.uiautomator.UiDevice;
@@ -34,6 +34,7 @@
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
+import android.view.WindowManager;
import androidx.lifecycle.Lifecycle;
import androidx.test.core.app.ActivityScenario;
@@ -52,7 +53,7 @@
public class AttachedChoreographerTest {
private static final String TAG = "AttachedChoreographerTest";
private static final long DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID = 170503758;
- private static final long THRESHOLD_MS = 10;
+ private static final long THRESHOLD_MS = 4;
private static final int FRAME_ITERATIONS = 21;
private static final int CALLBACK_MISSED_THRESHOLD = 2;
@@ -66,7 +67,7 @@
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private Choreographer mChoreographer;
- private boolean mIsFirstCallback = true;
+ private long mExpectedPresentTime;
private int mCallbackMissedCounter = 0;
@Before
@@ -74,6 +75,13 @@
mScenario = ActivityScenario.launch(GraphicsActivity.class);
mScenario.moveToState(Lifecycle.State.CREATED);
mScenario.onActivity(activity -> {
+ // Lock the display frame rate. This will not allow SurfaceFlinger to use the frame rate
+ // override feature that throttles down the global choreographer for this test.
+ float refreshRate = activity.getDisplay().getMode().getRefreshRate();
+ WindowManager.LayoutParams attrs = activity.getWindow().getAttributes();
+ attrs.preferredRefreshRate = refreshRate;
+ activity.getWindow().setAttributes(attrs);
+
mSurfaceView = activity.findViewById(R.id.surface);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@@ -95,6 +103,12 @@
});
UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+ // TODO(b/290634611): clean this up once SF new front end is enabled by default
+ boolean sfNewFeEnabled = uiDevice.executeShellCommand("dumpsys SurfaceFlinger")
+ .indexOf("SurfaceFlinger New Frontend Enabled:true") != -1;
+ assumeTrue(sfNewFeEnabled);
+
uiDevice.wakeUp();
uiDevice.executeShellCommand("wm dismiss-keyguard");
mScenario.moveToState(Lifecycle.State.RESUMED);
@@ -112,18 +126,16 @@
mDisplayManager.setRefreshRateSwitchingType(
DisplayManager.SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY);
mDisplayManager.setShouldAlwaysRespectAppRequestedMode(true);
- boolean changeIsEnabled =
- CompatChanges.isChangeEnabled(
- DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID);
- Log.i(TAG, "DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGE_ID is "
- + (changeIsEnabled ? "enabled" : "disabled"));
});
}
@After
public void tearDown() {
- mDisplayManager.setRefreshRateSwitchingType(mInitialMatchContentFrameRate);
- mDisplayManager.setShouldAlwaysRespectAppRequestedMode(false);
+ if (mDisplayManager != null) {
+ mDisplayManager.setRefreshRateSwitchingType(mInitialMatchContentFrameRate);
+ mDisplayManager.setShouldAlwaysRespectAppRequestedMode(false);
+ }
+
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.dropShellPermissionIdentity();
}
@@ -407,18 +419,141 @@
}
}
+ @Test
+ public void testChoreographerAttachedAfterSetFrameRate() {
+ Log.i(TAG, "adyabr: starting testChoreographerAttachedAfterSetFrameRate");
+
+ class TransactionGenerator implements SurfaceControl.TransactionCommittedListener {
+ private SurfaceControl mSc;
+ private int mFrame;
+ private static final int NUM_FRAMES = 50;
+ private final CountDownLatch mCompleteLatch = new CountDownLatch(1);
+
+ TransactionGenerator(SurfaceControl sc) {
+ mSc = sc;
+
+ }
+
+ @Override
+ public void onTransactionCommitted() {
+ mFrame++;
+ if (mFrame >= NUM_FRAMES) {
+ mCompleteLatch.countDown();
+ return;
+ }
+
+ SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+ transaction.setAlpha(mSc, 1.0f / mFrame)
+ .addTransactionCommittedListener(Runnable::run, this)
+ .apply();
+
+ }
+
+ public void startAndWaitForCompletion() {
+ onTransactionCommitted();
+ if (waitForCountDown(mCompleteLatch, /* timeoutInSeconds */ 10L)) {
+ fail("failed to send new transactions");
+ }
+ }
+ }
+
+
+ for (int divisor : new int[]{2, 3}) {
+ CountDownLatch choreographerLatch = new CountDownLatch(1);
+ mScenario.onActivity(activity -> {
+ if (waitForCountDown(mSurfaceCreationCountDown, /* timeoutInSeconds */ 1L)) {
+ fail("Unable to create surface within 1 Second");
+ }
+
+ SurfaceControl sc = mSurfaceView.getSurfaceControl();
+ SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+ float displayRefreshRate = activity.getDisplay().getMode().getRefreshRate();
+ float fps = displayRefreshRate / divisor;
+ long callbackDurationMs = Math.round(1000 / fps);
+ mCallbackMissedCounter = 0;
+ transaction.setFrameRate(sc, fps, Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE)
+ .apply();
+
+
+ new TransactionGenerator(sc).startAndWaitForCompletion();
+
+ Choreographer choreographer = sc.getChoreographer();
+ verifyVsyncCallbacks(choreographer, callbackDurationMs,
+ choreographerLatch, FRAME_ITERATIONS);
+ });
+ // wait for the previous callbacks to finish before moving to the next divisor
+ if (waitForCountDown(choreographerLatch, /* timeoutInSeconds */ 5L)) {
+ fail("Test not finished in 5 Seconds");
+ }
+ }
+ }
+
+ @Test
+ public void testChoreographerNonDivisorFixedSourceRefreshRate() {
+ CountDownLatch continueLatch = new CountDownLatch(1);
+ mScenario.onActivity(activity -> {
+ if (waitForCountDown(mSurfaceCreationCountDown, /* timeoutInSeconds */ 1L)) {
+ fail("Unable to create surface within 1 Second");
+ }
+ SurfaceControl sc = mSurfaceView.getSurfaceControl();
+ Choreographer choreographer = sc.getChoreographer();
+ SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+ float displayRefreshRate = activity.getDisplay().getMode().getRefreshRate();
+ float fps = 61.7f; // hopefully not a divisor
+ long callbackDurationMs = Math.round(1000 / displayRefreshRate);
+ mCallbackMissedCounter = 0;
+ transaction.setFrameRate(sc, fps, Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE)
+ .addTransactionCommittedListener(Runnable::run,
+ () -> verifyVsyncCallbacks(choreographer,
+ callbackDurationMs, continueLatch, FRAME_ITERATIONS))
+ .apply();
+ });
+ // wait for the previous callbacks to finish before moving to the next divisor
+ if (waitForCountDown(continueLatch, /* timeoutInSeconds */ 5L)) {
+ fail("Test not finished in 5 Seconds");
+ }
+ }
+
+ @Test
+ public void testChoreographerNonDivisorRefreshRate() {
+ CountDownLatch continueLatch = new CountDownLatch(1);
+ mScenario.onActivity(activity -> {
+ if (waitForCountDown(mSurfaceCreationCountDown, /* timeoutInSeconds */ 1L)) {
+ fail("Unable to create surface within 1 Second");
+ }
+ SurfaceControl sc = mSurfaceView.getSurfaceControl();
+ Choreographer choreographer = sc.getChoreographer();
+ SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+ float displayRefreshRate = activity.getDisplay().getMode().getRefreshRate();
+ float fps = 61.7f; // hopefully not a divisor
+ float expectedFps = displayRefreshRate / Math.round(displayRefreshRate / fps);
+ long callbackDurationMs = Math.round(1000 / expectedFps);
+ mCallbackMissedCounter = 0;
+ transaction.setFrameRate(sc, fps, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT)
+ .addTransactionCommittedListener(Runnable::run,
+ () -> verifyVsyncCallbacks(choreographer,
+ callbackDurationMs, continueLatch, FRAME_ITERATIONS))
+ .apply();
+ });
+ // wait for the previous callbacks to finish before moving to the next divisor
+ if (waitForCountDown(continueLatch, /* timeoutInSeconds */ 5L)) {
+ fail("Test not finished in 5 Seconds");
+ }
+ }
+
private void verifyVsyncCallbacks(Choreographer choreographer, long callbackDurationMs,
CountDownLatch continueLatch, int frameCount) {
- long callbackRequestedTimeNs = System.nanoTime();
choreographer.postVsyncCallback(frameData -> {
+ long expectedPresentTime =
+ frameData.getPreferredFrameTimeline().getExpectedPresentationTimeNanos();
if (frameCount > 0) {
- if (!mIsFirstCallback) {
- // Skip the first callback as it takes 1 frame
- // to reflect the new refresh rate
- long callbackDurationDiffMs = getCallbackDurationDiffInMs(
- frameData.getFrameTimeNanos(),
- callbackRequestedTimeNs, callbackDurationMs);
- if (callbackDurationDiffMs < 0 || callbackDurationDiffMs > THRESHOLD_MS) {
+ if (mExpectedPresentTime > 0) {
+ long callbackDurationDiffMs =
+ TimeUnit.NANOSECONDS.toMillis(
+ expectedPresentTime - mExpectedPresentTime);
+ if (callbackDurationDiffMs < 0
+ || Math.abs(callbackDurationMs - callbackDurationDiffMs)
+ > THRESHOLD_MS) {
mCallbackMissedCounter++;
Log.e(TAG, "Frame #" + Math.abs(frameCount - FRAME_ITERATIONS)
+ " vsync callback failed, expected callback in "
@@ -427,25 +562,19 @@
+ " but actual duration difference is " + callbackDurationDiffMs);
}
}
- mIsFirstCallback = false;
+ mExpectedPresentTime = expectedPresentTime;
verifyVsyncCallbacks(choreographer, callbackDurationMs,
continueLatch, frameCount - 1);
} else {
- assertTrue("Missed timeline for " + mCallbackMissedCounter + " callbacks, while "
- + CALLBACK_MISSED_THRESHOLD + " missed callbacks are allowed",
+ assertTrue("Missed timeline for " + mCallbackMissedCounter
+ + " callbacks, while " + CALLBACK_MISSED_THRESHOLD
+ + " missed callbacks are allowed",
mCallbackMissedCounter <= CALLBACK_MISSED_THRESHOLD);
continueLatch.countDown();
}
});
}
- private long getCallbackDurationDiffInMs(long callbackTimeNs, long requestedTimeNs,
- long expectedCallbackMs) {
- long actualTimeMs = TimeUnit.NANOSECONDS.toMillis(callbackTimeNs)
- - TimeUnit.NANOSECONDS.toMillis(requestedTimeNs);
- return Math.abs(expectedCallbackMs - actualTimeMs);
- }
-
private boolean waitForCountDown(CountDownLatch countDownLatch, long timeoutInSeconds) {
try {
return !countDownLatch.await(timeoutInSeconds, TimeUnit.SECONDS);
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index 4fa6fbe..96b685d 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -19,13 +19,26 @@
platform_apis: true,
certificate: "platform",
static_libs: [
+ "androidx.test.core",
"androidx.test.ext.junit",
+ "androidx.test.ext.truth",
"androidx.test.rules",
+ "androidx.test.runner",
+ "androidx.test.uiautomator_uiautomator",
+ "servicestests-utils",
+ "frameworks-base-testutils",
+ "hamcrest-library",
+ "kotlin-test",
"mockito-target-minus-junit4",
+ "platform-test-annotations",
"services.core.unboosted",
"testables",
+ "testng",
"truth-prebuilt",
- "androidx.test.uiautomator_uiautomator",
+ ],
+ libs: [
+ "android.test.mock",
+ "android.test.base",
],
test_suites: ["device-tests"],
}
diff --git a/tests/Input/AndroidManifest.xml b/tests/Input/AndroidManifest.xml
index 20f564e..3b723dd 100644
--- a/tests/Input/AndroidManifest.xml
+++ b/tests/Input/AndroidManifest.xml
@@ -16,11 +16,14 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.test.input">
- <uses-permission android:name="android.permission.MONITOR_INPUT"/>
- <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
- <uses-permission android:name="android.permission.INJECT_EVENTS"/>
- <application android:label="InputTest">
+ <uses-permission android:name="android.permission.INJECT_EVENTS"/>
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
+ <uses-permission android:name="android.permission.MONITOR_INPUT"/>
+ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG"/>
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
+
+ <application android:label="InputTest" android:debuggable="true">
<activity android:name=".UnresponsiveGestureMonitorActivity"
android:label="Unresponsive gesture monitor"
diff --git a/tests/Input/OWNERS b/tests/Input/OWNERS
index d701f23..3cffce9 100644
--- a/tests/Input/OWNERS
+++ b/tests/Input/OWNERS
@@ -1 +1,2 @@
+# Bug component: 136048
include /core/java/android/hardware/input/OWNERS
diff --git a/services/tests/servicestests/res/raw/dummy_keyboard_layout.kcm b/tests/Input/res/raw/dummy_keyboard_layout.kcm
similarity index 100%
rename from services/tests/servicestests/res/raw/dummy_keyboard_layout.kcm
rename to tests/Input/res/raw/dummy_keyboard_layout.kcm
diff --git a/services/tests/servicestests/res/raw/input_port_associations.xml b/tests/Input/res/raw/input_port_associations.xml
similarity index 100%
rename from services/tests/servicestests/res/raw/input_port_associations.xml
rename to tests/Input/res/raw/input_port_associations.xml
diff --git a/services/tests/servicestests/res/raw/input_port_associations_bad_displayport.xml b/tests/Input/res/raw/input_port_associations_bad_displayport.xml
similarity index 100%
rename from services/tests/servicestests/res/raw/input_port_associations_bad_displayport.xml
rename to tests/Input/res/raw/input_port_associations_bad_displayport.xml
diff --git a/services/tests/servicestests/res/raw/input_port_associations_bad_xml.xml b/tests/Input/res/raw/input_port_associations_bad_xml.xml
similarity index 100%
rename from services/tests/servicestests/res/raw/input_port_associations_bad_xml.xml
rename to tests/Input/res/raw/input_port_associations_bad_xml.xml
diff --git a/services/tests/servicestests/res/xml/keyboard_layouts.xml b/tests/Input/res/xml/keyboard_layouts.xml
similarity index 100%
rename from services/tests/servicestests/res/xml/keyboard_layouts.xml
rename to tests/Input/res/xml/keyboard_layouts.xml
diff --git a/core/tests/coretests/src/android/hardware/input/InputDeviceBatteryListenerTest.kt b/tests/Input/src/android/hardware/input/InputDeviceBatteryListenerTest.kt
similarity index 96%
rename from core/tests/coretests/src/android/hardware/input/InputDeviceBatteryListenerTest.kt
rename to tests/Input/src/android/hardware/input/InputDeviceBatteryListenerTest.kt
index fdcc7c9..90dff47 100644
--- a/core/tests/coretests/src/android/hardware/input/InputDeviceBatteryListenerTest.kt
+++ b/tests/Input/src/android/hardware/input/InputDeviceBatteryListenerTest.kt
@@ -46,7 +46,7 @@
* Tests for [InputManager.InputDeviceBatteryListener].
*
* Build/Install/Run:
- * atest FrameworksCoreTests:InputDeviceBatteryListenerTest
+ * atest InputTests:InputDeviceBatteryListenerTest
*/
@Presubmit
@RunWith(MockitoJUnitRunner::class)
@@ -63,6 +63,7 @@
@Mock
private lateinit var iInputManagerMock: IInputManager
+ private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
@Before
fun setUp() {
@@ -71,7 +72,7 @@
executor = HandlerExecutor(Handler(testLooper.looper))
registeredListener = null
monitoredDevices.clear()
- InputManagerGlobal.resetInstance(iInputManagerMock)
+ inputManagerGlobalSession = InputManagerGlobal.createTestSession(iInputManagerMock)
inputManager = InputManager(context)
`when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE)))
.thenReturn(inputManager)
@@ -112,7 +113,9 @@
@After
fun tearDown() {
- InputManagerGlobal.clearInstance()
+ if (this::inputManagerGlobalSession.isInitialized) {
+ inputManagerGlobalSession.close()
+ }
}
private fun notifyBatteryStateChanged(
diff --git a/core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java b/tests/Input/src/android/hardware/input/InputDeviceLightsManagerTest.java
similarity index 95%
rename from core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java
rename to tests/Input/src/android/hardware/input/InputDeviceLightsManagerTest.java
index 1e505ab..080186e 100644
--- a/core/tests/coretests/src/android/hardware/input/InputDeviceLightsManagerTest.java
+++ b/tests/Input/src/android/hardware/input/InputDeviceLightsManagerTest.java
@@ -43,7 +43,7 @@
import android.util.ArrayMap;
import android.view.InputDevice;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
@@ -63,7 +63,7 @@
* Tests for {@link InputDeviceLightsManager}.
*
* Build/Install/Run:
- * atest FrameworksCoreTests:InputDeviceLightsManagerTest
+ * atest InputTests:InputDeviceLightsManagerTest
*/
@Presubmit
@RunWith(MockitoJUnitRunner.class)
@@ -78,16 +78,18 @@
private InputManager mInputManager;
@Mock private IInputManager mIInputManagerMock;
+ private InputManagerGlobal.TestSession mInputManagerGlobalSession;
@Before
public void setUp() throws Exception {
- final Context context = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
+ final Context context = spy(
+ new ContextWrapper(InstrumentationRegistry.getInstrumentation().getContext()));
when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID});
when(mIInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn(
createInputDevice(DEVICE_ID));
- InputManagerGlobal.resetInstance(mIInputManagerMock);
+ mInputManagerGlobalSession = InputManagerGlobal.createTestSession(mIInputManagerMock);
mInputManager = new InputManager(context);
when(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(mInputManager);
@@ -114,7 +116,9 @@
@After
public void tearDown() {
- InputManagerGlobal.clearInstance();
+ if (mInputManagerGlobalSession != null) {
+ mInputManagerGlobalSession.close();
+ }
}
private InputDevice createInputDevice(int id) {
diff --git a/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java b/tests/Input/src/android/hardware/input/InputDeviceSensorManagerTest.java
similarity index 94%
rename from core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
rename to tests/Input/src/android/hardware/input/InputDeviceSensorManagerTest.java
index b33cfdd..0e3c200 100644
--- a/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
+++ b/tests/Input/src/android/hardware/input/InputDeviceSensorManagerTest.java
@@ -38,7 +38,7 @@
import android.platform.test.annotations.Presubmit;
import android.view.InputDevice;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.annotations.GuardedBy;
@@ -61,7 +61,7 @@
* Tests for {@link InputDeviceSensorManager}.
*
* Build/Install/Run:
- * atest FrameworksCoreTests:InputDeviceSensorManagerTest
+ * atest InputTests:InputDeviceSensorManagerTest
*/
@Presubmit
@RunWith(MockitoJUnitRunner.class)
@@ -77,11 +77,13 @@
private final Object mLock = new Object();
@Mock private IInputManager mIInputManagerMock;
+ private InputManagerGlobal.TestSession mInputManagerGlobalSession;
@Before
public void setUp() throws Exception {
- final Context context = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
- InputManagerGlobal.resetInstance(mIInputManagerMock);
+ final Context context = spy(
+ new ContextWrapper(InstrumentationRegistry.getInstrumentation().getContext()));
+ mInputManagerGlobalSession = InputManagerGlobal.createTestSession(mIInputManagerMock);
mInputManager = new InputManager(context);
when(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(mInputManager);
@@ -102,7 +104,9 @@
@After
public void tearDown() {
- InputManagerGlobal.clearInstance();
+ if (mInputManagerGlobalSession != null) {
+ mInputManagerGlobalSession.close();
+ }
}
private class InputTestSensorEventListener implements SensorEventListener {
diff --git a/core/tests/coretests/src/android/hardware/input/InputManagerTest.kt b/tests/Input/src/android/hardware/input/InputManagerTest.kt
similarity index 93%
rename from core/tests/coretests/src/android/hardware/input/InputManagerTest.kt
rename to tests/Input/src/android/hardware/input/InputManagerTest.kt
index 2ebe362..152dde9 100644
--- a/core/tests/coretests/src/android/hardware/input/InputManagerTest.kt
+++ b/tests/Input/src/android/hardware/input/InputManagerTest.kt
@@ -41,7 +41,7 @@
* Tests for [InputManager].
*
* Build/Install/Run:
- * atest FrameworksCoreTests:InputManagerTest
+ * atest InputTests:InputManagerTest
*/
@Presubmit
@RunWith(MockitoJUnitRunner::class)
@@ -63,11 +63,12 @@
@Mock
private lateinit var iInputManager: IInputManager
+ private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
@Before
fun setUp() {
context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
- InputManagerGlobal.resetInstance(iInputManager)
+ inputManagerGlobalSession = InputManagerGlobal.createTestSession(iInputManager)
inputManager = InputManager(context)
`when`(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager)
`when`(iInputManager.inputDeviceIds).then {
@@ -77,7 +78,9 @@
@After
fun tearDown() {
- InputManagerGlobal.clearInstance()
+ if (this::inputManagerGlobalSession.isInitialized) {
+ inputManagerGlobalSession.close()
+ }
}
private fun notifyDeviceChanged(
diff --git a/core/tests/coretests/src/android/hardware/input/KeyboardBacklightListenerTest.kt b/tests/Input/src/android/hardware/input/KeyboardBacklightListenerTest.kt
similarity index 94%
rename from core/tests/coretests/src/android/hardware/input/KeyboardBacklightListenerTest.kt
rename to tests/Input/src/android/hardware/input/KeyboardBacklightListenerTest.kt
index ce816ab..23135b2 100644
--- a/core/tests/coretests/src/android/hardware/input/KeyboardBacklightListenerTest.kt
+++ b/tests/Input/src/android/hardware/input/KeyboardBacklightListenerTest.kt
@@ -45,7 +45,7 @@
* Tests for [InputManager.KeyboardBacklightListener].
*
* Build/Install/Run:
- * atest FrameworksCoreTests:KeyboardBacklightListenerTest
+ * atest InputTests:KeyboardBacklightListenerTest
*/
@Presubmit
@RunWith(MockitoJUnitRunner::class)
@@ -58,6 +58,7 @@
private lateinit var executor: Executor
private lateinit var context: Context
private lateinit var inputManager: InputManager
+ private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
@Mock
private lateinit var iInputManagerMock: IInputManager
@@ -65,7 +66,7 @@
@Before
fun setUp() {
context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
- InputManagerGlobal.resetInstance(iInputManagerMock)
+ inputManagerGlobalSession = InputManagerGlobal.createTestSession(iInputManagerMock)
testLooper = TestLooper()
executor = HandlerExecutor(Handler(testLooper.looper))
registeredListener = null
@@ -99,7 +100,9 @@
@After
fun tearDown() {
- InputManagerGlobal.clearInstance()
+ if (this::inputManagerGlobalSession.isInitialized) {
+ inputManagerGlobalSession.close()
+ }
}
private fun notifyKeyboardBacklightChanged(
diff --git a/core/tests/coretests/src/android/hardware/input/VirtualKeyEventTest.java b/tests/Input/src/android/hardware/input/VirtualKeyEventTest.java
similarity index 100%
rename from core/tests/coretests/src/android/hardware/input/VirtualKeyEventTest.java
rename to tests/Input/src/android/hardware/input/VirtualKeyEventTest.java
diff --git a/core/tests/coretests/src/android/hardware/input/VirtualMouseButtonEventTest.java b/tests/Input/src/android/hardware/input/VirtualMouseButtonEventTest.java
similarity index 100%
rename from core/tests/coretests/src/android/hardware/input/VirtualMouseButtonEventTest.java
rename to tests/Input/src/android/hardware/input/VirtualMouseButtonEventTest.java
diff --git a/core/tests/coretests/src/android/hardware/input/VirtualMouseRelativeEventTest.java b/tests/Input/src/android/hardware/input/VirtualMouseRelativeEventTest.java
similarity index 100%
rename from core/tests/coretests/src/android/hardware/input/VirtualMouseRelativeEventTest.java
rename to tests/Input/src/android/hardware/input/VirtualMouseRelativeEventTest.java
diff --git a/core/tests/coretests/src/android/hardware/input/VirtualMouseScrollEventTest.java b/tests/Input/src/android/hardware/input/VirtualMouseScrollEventTest.java
similarity index 100%
rename from core/tests/coretests/src/android/hardware/input/VirtualMouseScrollEventTest.java
rename to tests/Input/src/android/hardware/input/VirtualMouseScrollEventTest.java
diff --git a/core/tests/coretests/src/android/hardware/input/VirtualTouchEventTest.java b/tests/Input/src/android/hardware/input/VirtualTouchEventTest.java
similarity index 100%
rename from core/tests/coretests/src/android/hardware/input/VirtualTouchEventTest.java
rename to tests/Input/src/android/hardware/input/VirtualTouchEventTest.java
diff --git a/services/tests/servicestests/src/com/android/server/input/AmbientKeyboardBacklightControllerTests.kt b/tests/Input/src/com/android/server/input/AmbientKeyboardBacklightControllerTests.kt
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/input/AmbientKeyboardBacklightControllerTests.kt
rename to tests/Input/src/com/android/server/input/AmbientKeyboardBacklightControllerTests.kt
index 98b4628..ad481df 100644
--- a/services/tests/servicestests/src/com/android/server/input/AmbientKeyboardBacklightControllerTests.kt
+++ b/tests/Input/src/com/android/server/input/AmbientKeyboardBacklightControllerTests.kt
@@ -55,7 +55,7 @@
* Tests for {@link AmbientKeyboardBacklightController}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:AmbientKeyboardBacklightControllerTests
+ * atest InputTests:AmbientKeyboardBacklightControllerTests
*/
@Presubmit
class AmbientKeyboardBacklightControllerTests {
diff --git a/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt b/tests/Input/src/com/android/server/input/BatteryControllerTests.kt
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt
rename to tests/Input/src/com/android/server/input/BatteryControllerTests.kt
index c36122b..f2724e6 100644
--- a/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt
+++ b/tests/Input/src/com/android/server/input/BatteryControllerTests.kt
@@ -167,7 +167,7 @@
* Tests for {@link InputDeviceBatteryController}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:InputDeviceBatteryControllerTests
+ * atest InputTests:InputDeviceBatteryControllerTests
*/
@Presubmit
class BatteryControllerTests {
@@ -198,13 +198,14 @@
private lateinit var context: TestableContext
private lateinit var testLooper: TestLooper
private lateinit var devicesChangedListener: IInputDevicesChangedListener
+ private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
private val deviceGenerationMap = mutableMapOf<Int /*deviceId*/, Int /*generation*/>()
@Before
fun setup() {
context = TestableContext(ApplicationProvider.getApplicationContext())
testLooper = TestLooper()
- InputManagerGlobal.resetInstance(iInputManager)
+ inputManagerGlobalSession = InputManagerGlobal.createTestSession(iInputManager)
val inputManager = InputManager(context)
context.addMockSystemService(InputManager::class.java, inputManager)
`when`(iInputManager.inputDeviceIds).then {
@@ -222,6 +223,13 @@
testLooper.dispatchAll()
}
+ @After
+ fun tearDown() {
+ if (this::inputManagerGlobalSession.isInitialized) {
+ inputManagerGlobalSession.close()
+ }
+ }
+
private fun notifyDeviceChanged(
deviceId: Int,
hasBattery: Boolean = true,
@@ -253,11 +261,6 @@
.adapter.getRemoteDevice(address)
}
- @After
- fun tearDown() {
- InputManagerGlobal.clearInstance()
- }
-
@Test
fun testRegisterAndUnregisterBinderLifecycle() {
val listener = createMockListener()
diff --git a/services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java b/tests/Input/src/com/android/server/input/ConfigurationProcessorTest.java
similarity index 87%
rename from services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java
rename to tests/Input/src/com/android/server/input/ConfigurationProcessorTest.java
index 2bd4a3a..9a49d91 100644
--- a/services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java
+++ b/tests/Input/src/com/android/server/input/ConfigurationProcessorTest.java
@@ -22,7 +22,7 @@
import android.content.Context;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
@@ -43,12 +43,12 @@
@Before
public void setUp() throws Exception {
- mContext = InstrumentationRegistry.getContext();
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
}
@Test
public void testGetInputPortAssociations() {
- final int res = com.android.frameworks.servicestests.R.raw.input_port_associations;
+ final int res = com.android.test.input.R.raw.input_port_associations;
InputStream xml = mContext.getResources().openRawResource(res);
Map<String, Integer> associations = null;
try {
@@ -65,7 +65,7 @@
@Test
public void testGetInputPortAssociationsBadDisplayport() {
final int res =
- com.android.frameworks.servicestests.R.raw.input_port_associations_bad_displayport;
+ com.android.test.input.R.raw.input_port_associations_bad_displayport;
InputStream xml = mContext.getResources().openRawResource(res);
Map<String, Integer> associations = null;
try {
@@ -79,7 +79,7 @@
@Test
public void testGetInputPortAssociationsEmptyConfig() {
- final int res = com.android.frameworks.servicestests.R.raw.input_port_associations_bad_xml;
+ final int res = com.android.test.input.R.raw.input_port_associations_bad_xml;
InputStream xml = mContext.getResources().openRawResource(res);
try {
ConfigurationProcessor.processInputPortAssociations(xml);
diff --git a/services/tests/servicestests/src/com/android/server/input/InputManagerServiceTests.kt b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
similarity index 94%
rename from services/tests/servicestests/src/com/android/server/input/InputManagerServiceTests.kt
rename to tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
index 498776d..93a5582 100644
--- a/services/tests/servicestests/src/com/android/server/input/InputManagerServiceTests.kt
+++ b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
@@ -20,6 +20,8 @@
import android.content.Context
import android.content.ContextWrapper
import android.hardware.display.DisplayViewport
+import android.hardware.input.InputManager
+import android.hardware.input.InputManagerGlobal
import android.os.IInputConstants
import android.os.test.TestLooper
import android.platform.test.annotations.Presubmit
@@ -27,9 +29,10 @@
import android.test.mock.MockContentResolver
import android.view.Display
import android.view.PointerIcon
-import androidx.test.InstrumentationRegistry
+import androidx.test.platform.app.InstrumentationRegistry
import com.android.internal.util.test.FakeSettingsProvider
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
@@ -59,7 +62,7 @@
* Tests for {@link InputManagerService}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:InputManagerServiceTests
+ * atest InputTests:InputManagerServiceTests
*/
@Presubmit
class InputManagerServiceTests {
@@ -84,10 +87,11 @@
private lateinit var context: Context
private lateinit var testLooper: TestLooper
private lateinit var contentResolver: MockContentResolver
+ private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
@Before
fun setup() {
- context = spy(ContextWrapper(InstrumentationRegistry.getContext()))
+ context = spy(ContextWrapper(InstrumentationRegistry.getInstrumentation().getContext()))
contentResolver = MockContentResolver(context)
contentResolver.addProvider(Settings.AUTHORITY, FakeSettingsProvider())
whenever(context.contentResolver).thenReturn(contentResolver)
@@ -105,10 +109,22 @@
localService = service!!
}
})
+ inputManagerGlobalSession = InputManagerGlobal.createTestSession(service)
+ val inputManager = InputManager(context)
+ whenever(context.getSystemService(InputManager::class.java)).thenReturn(inputManager)
+ whenever(context.getSystemService(Context.INPUT_SERVICE)).thenReturn(inputManager)
+
assertTrue("Local service must be registered", this::localService.isInitialized)
service.setWindowManagerCallbacks(wmCallbacks)
}
+ @After
+ fun tearDown() {
+ if (this::inputManagerGlobalSession.isInitialized) {
+ inputManagerGlobalSession.close()
+ }
+ }
+
@Test
fun testStart() {
verifyZeroInteractions(native)
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyRemapperTests.kt b/tests/Input/src/com/android/server/input/KeyRemapperTests.kt
similarity index 94%
rename from services/tests/servicestests/src/com/android/server/input/KeyRemapperTests.kt
rename to tests/Input/src/com/android/server/input/KeyRemapperTests.kt
index c10f651..f74fd72 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyRemapperTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyRemapperTests.kt
@@ -54,7 +54,7 @@
* Tests for {@link KeyRemapper}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:KeyRemapperTests
+ * atest InputTests:KeyRemapperTests
*/
@Presubmit
class KeyRemapperTests {
@@ -81,6 +81,7 @@
private lateinit var context: Context
private lateinit var dataStore: PersistentDataStore
private lateinit var testLooper: TestLooper
+ private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
@Before
fun setup() {
@@ -103,7 +104,7 @@
dataStore,
testLooper.looper
)
- InputManagerGlobal.resetInstance(iInputManager)
+ inputManagerGlobalSession = InputManagerGlobal.createTestSession(iInputManager)
val inputManager = InputManager(context)
Mockito.`when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE)))
.thenReturn(inputManager)
@@ -112,7 +113,9 @@
@After
fun tearDown() {
- InputManagerGlobal.clearInstance()
+ if (this::inputManagerGlobalSession.isInitialized) {
+ inputManagerGlobalSession.close()
+ }
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt b/tests/Input/src/com/android/server/input/KeyboardBacklightControllerTests.kt
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
rename to tests/Input/src/com/android/server/input/KeyboardBacklightControllerTests.kt
index 3f4a4fb..59aa96c 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardBacklightControllerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyboardBacklightControllerTests.kt
@@ -87,7 +87,7 @@
* Tests for {@link KeyboardBacklightController}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:KeyboardBacklightControllerTests
+ * atest InputTests:KeyboardBacklightControllerTests
*/
@Presubmit
class KeyboardBacklightControllerTests {
@@ -111,6 +111,7 @@
private lateinit var context: Context
private lateinit var dataStore: PersistentDataStore
private lateinit var testLooper: TestLooper
+ private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
private var lightColorMap: HashMap<Int, Int> = HashMap()
private var lastBacklightState: KeyboardBacklightState? = null
private var sysfsNodeChanges = 0
@@ -133,7 +134,7 @@
testLooper = TestLooper()
keyboardBacklightController = KeyboardBacklightController(context, native, dataStore,
testLooper.looper, FakeAnimatorFactory(), uEventManager)
- InputManagerGlobal.resetInstance(iInputManager)
+ inputManagerGlobalSession = InputManagerGlobal.createTestSession(iInputManager)
val inputManager = InputManager(context)
`when`(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager)
`when`(iInputManager.inputDeviceIds).thenReturn(intArrayOf(DEVICE_ID))
@@ -153,7 +154,9 @@
@After
fun tearDown() {
- InputManagerGlobal.clearInstance()
+ if (this::inputManagerGlobalSession.isInitialized) {
+ inputManagerGlobalSession.close()
+ }
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt b/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
rename to tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
index 55c45df..b6477510 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardLayoutManagerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyboardLayoutManagerTests.kt
@@ -37,6 +37,7 @@
import android.view.inputmethod.InputMethodSubtype
import androidx.test.core.R
import androidx.test.core.app.ApplicationProvider
+import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertNull
@@ -77,7 +78,7 @@
* Tests for {@link Default UI} and {@link New UI}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:KeyboardLayoutManagerTests
+ * atest InputTests:KeyboardLayoutManagerTests
*/
@Presubmit
class KeyboardLayoutManagerTests {
@@ -120,6 +121,7 @@
private lateinit var context: Context
private lateinit var dataStore: PersistentDataStore
private lateinit var testLooper: TestLooper
+ private lateinit var inputManagerGlobalSession: InputManagerGlobal.TestSession
// Devices
private lateinit var keyboardDevice: InputDevice
@@ -130,6 +132,7 @@
@Before
fun setup() {
context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
+ inputManagerGlobalSession = InputManagerGlobal.createTestSession(iInputManager)
dataStore = PersistentDataStore(object : PersistentDataStore.Injector() {
override fun openRead(): InputStream? {
throw FileNotFoundException()
@@ -148,8 +151,14 @@
setupIme()
}
+ @After
+ fun tearDown() {
+ if (this::inputManagerGlobalSession.isInitialized) {
+ inputManagerGlobalSession.close()
+ }
+ }
+
private fun setupInputDevices() {
- InputManagerGlobal.resetInstance(iInputManager)
val inputManager = InputManager(context)
Mockito.`when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE)))
.thenReturn(inputManager)
diff --git a/services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt b/tests/Input/src/com/android/server/input/KeyboardMetricsCollectorTests.kt
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt
rename to tests/Input/src/com/android/server/input/KeyboardMetricsCollectorTests.kt
index c9724a3..e2dc131 100644
--- a/services/tests/servicestests/src/com/android/server/input/KeyboardMetricsCollectorTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyboardMetricsCollectorTests.kt
@@ -58,7 +58,7 @@
* Tests for {@link KeyboardMetricsCollector}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:KeyboardMetricsCollectorTests
+ * atest InputTests:KeyboardMetricsCollectorTests
*/
@Presubmit
class KeyboardMetricsCollectorTests {