Merge "Add ANR/Watchdog subject to trace."
diff --git a/core/api/current.txt b/core/api/current.txt
index 20f318d..9d74a8c 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -27638,6 +27638,7 @@
field public static final String CATEGORY_PAYMENT = "payment";
field public static final String EXTRA_CATEGORY = "category";
field public static final String EXTRA_SERVICE_COMPONENT = "component";
+ field public static final String EXTRA_USERID = "android.nfc.cardemulation.extra.USERID";
field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1
field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2
field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 2891735..6d342db 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -961,20 +961,20 @@
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public boolean getBluetoothContactSharingDisabled(@NonNull android.os.UserHandle);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwner();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public android.content.ComponentName getDeviceOwnerComponentOnAnyUser();
- method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwnerNameOnAnyUser();
+ method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public String getDeviceOwnerNameOnAnyUser();
method @Nullable public CharSequence getDeviceOwnerOrganizationName();
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getDeviceOwnerUser();
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<java.lang.String> getPermittedAccessibilityServices(int);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<java.lang.String> getPermittedInputMethodsForCurrentUser();
method @Nullable public android.content.ComponentName getProfileOwner() throws java.lang.IllegalArgumentException;
- method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getProfileOwnerNameAsUser(int) throws java.lang.IllegalArgumentException;
- method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserProvisioningState();
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public String getProfileOwnerNameAsUser(int) throws java.lang.IllegalArgumentException;
+ method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public int getUserProvisioningState();
method public boolean isDeviceManaged();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isDeviceProvisioned();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isDeviceProvisioningConfigApplied();
- method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isManagedKiosk();
+ method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public boolean isManagedKiosk();
method public boolean isSecondaryLockscreenEnabled(@NonNull android.os.UserHandle);
- method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isUnattendedManagedKiosk();
+ method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public boolean isUnattendedManagedKiosk();
method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long);
method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long, boolean);
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean packageHasActiveAdmins(String);
@@ -8681,7 +8681,11 @@
}
public final class NewUserRequest {
+ method @Nullable public String getAccountName();
+ method @Nullable public android.os.PersistableBundle getAccountOptions();
+ method @Nullable public String getAccountType();
method @Nullable public String getName();
+ method @Nullable public android.graphics.Bitmap getUserIcon();
method @NonNull public String getUserType();
method public boolean isAdmin();
method public boolean isEphemeral();
@@ -8690,9 +8694,13 @@
public static final class NewUserRequest.Builder {
ctor public NewUserRequest.Builder();
method @NonNull public android.os.NewUserRequest build();
+ method @NonNull public android.os.NewUserRequest.Builder setAccountName(@Nullable String);
+ method @NonNull public android.os.NewUserRequest.Builder setAccountOptions(@Nullable android.os.PersistableBundle);
+ method @NonNull public android.os.NewUserRequest.Builder setAccountType(@Nullable String);
method @NonNull public android.os.NewUserRequest.Builder setAdmin();
method @NonNull public android.os.NewUserRequest.Builder setEphemeral();
method @NonNull public android.os.NewUserRequest.Builder setName(@Nullable String);
+ method @NonNull public android.os.NewUserRequest.Builder setUserIcon(@Nullable android.graphics.Bitmap);
method @NonNull public android.os.NewUserRequest.Builder setUserType(@NonNull String);
}
@@ -8970,6 +8978,7 @@
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean removeUser(@NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(@NonNull android.graphics.Bitmap) throws android.os.UserManager.UserOperationException;
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserName(@Nullable String);
+ method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean someUserHasAccount(@NonNull String, @NonNull String);
field public static final String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
field @Deprecated public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
field public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
@@ -8981,6 +8990,7 @@
field public static final int SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED = 4; // 0x4
field public static final int SWITCHABILITY_STATUS_USER_IN_CALL = 1; // 0x1
field public static final int SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED = 2; // 0x2
+ field public static final int USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS = 7; // 0x7
field public static final String USER_TYPE_FULL_GUEST = "android.os.usertype.full.GUEST";
field public static final String USER_TYPE_FULL_SECONDARY = "android.os.usertype.full.SECONDARY";
field public static final String USER_TYPE_FULL_SYSTEM = "android.os.usertype.full.SYSTEM";
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 311a60d..57b3196 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -7867,7 +7867,7 @@
@SystemApi
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
- android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS,
+ android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
})
public ComponentName getDeviceOwnerComponentOnAnyUser() {
return getDeviceOwnerComponentInner(/* callingUserOnly =*/ false);
@@ -7980,8 +7980,8 @@
* Called by the system to find out whether the device is managed by a Device Owner.
*
* @return whether the device is managed by a Device Owner.
- * @throws SecurityException if the caller is not the device owner, does not hold the
- * MANAGE_USERS permission and is not the system.
+ * @throws SecurityException if the caller is not the device owner, does not hold
+ * MANAGE_USERS or MANAGE_PROFILE_AND_DEVICE_OWNERS permissions and is not the system.
*
* @hide
*/
@@ -8002,7 +8002,10 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
+ })
public String getDeviceOwnerNameOnAnyUser() {
throwIfParentInstance("getDeviceOwnerNameOnAnyUser");
if (mService != null) {
@@ -8392,7 +8395,10 @@
* @throws IllegalArgumentException if the userId is invalid.
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
+ })
public @Nullable String getProfileOwnerNameAsUser(int userId) throws IllegalArgumentException {
throwIfParentInstance("getProfileOwnerNameAsUser");
if (mService != null) {
@@ -11930,7 +11936,10 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
+ })
@UserProvisioningState
public int getUserProvisioningState() {
throwIfParentInstance("getUserProvisioningState");
@@ -13439,7 +13448,10 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
+ })
public boolean isManagedKiosk() {
throwIfParentInstance("isManagedKiosk");
if (mService != null) {
@@ -13468,7 +13480,10 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
+ })
public boolean isUnattendedManagedKiosk() {
throwIfParentInstance("isUnattendedManagedKiosk");
if (mService != null) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a5a75a4..25d1d53 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -6544,30 +6544,24 @@
@NonNull Configuration overrideConfiguration);
/**
- * Return a new Context object for the current Context but whose resources
- * are adjusted to match the metrics of the given Display. Each call to this method
- * returns a new instance of a Context object; Context objects are not
- * shared, however common state (ClassLoader, other Resources for the
- * same configuration) may be so the Context itself can be fairly lightweight.
- *
- * To obtain an instance of a {@link WindowManager} (see {@link #getSystemService(String)}) that
- * is configured to show windows on the given display call
- * {@link #createWindowContext(int, Bundle)} on the returned display Context or use an
- * {@link android.app.Activity}.
- *
+ * Returns a new <code>Context</code> object from the current context but with resources
+ * adjusted to match the metrics of <code>display</code>. Each call to this method
+ * returns a new instance of a context object. Context objects are not shared; however,
+ * common state (such as the {@link ClassLoader} and other resources for the same
+ * configuration) can be shared, so the <code>Context</code> itself is lightweight.
* <p>
- * Note that invoking #createDisplayContext(Display) from an UI context is not regarded
- * as an UI context. In other words, it is not suggested to access UI components (such as
- * obtain a {@link WindowManager} by {@link #getSystemService(String)})
- * from the context created from #createDisplayContext(Display).
- * </p>
+ * To obtain an instance of {@link WindowManager} configured to show windows on the given
+ * display, call {@link #createWindowContext(int, Bundle)} on the returned display context,
+ * then call {@link #getSystemService(String)} or {@link #getSystemService(Class)} on the
+ * returned window context.
+ * <p>
+ * <b>Note:</b> The context returned by <code>createDisplayContext(Display)</code> is not a UI
+ * context. Do not access UI components or obtain a {@link WindowManager} from the context
+ * created by <code>createDisplayContext(Display)</code>.
*
- * @param display A {@link Display} object specifying the display for whose metrics the
- * Context's resources should be tailored.
+ * @param display The display to which the current context's resources are adjusted.
*
- * @return A {@link Context} for the display.
- *
- * @see #getSystemService(String)
+ * @return A context for the display.
*/
@DisplayContext
public abstract Context createDisplayContext(@NonNull Display display);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a3efbd7..2b8681a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -5522,8 +5522,8 @@
/**
* A boolean extra, when used with {@link #ACTION_VIEW_PERMISSION_USAGE_FOR_PERIOD},
- * that specifies whether the system displayed attribution information in the
- * permission usage system UI for the chosen entry.
+ * that specifies whether the permission usage system UI is showing attribution information
+ * for the chosen entry.
*
* <p> The extra can only be true if application has specified attributionsAreUserVisible
* in its manifest. </p>
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 96a18dc..3c8b6e9 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1323,7 +1323,7 @@
* <p>Maximum flashlight brightness level.</p>
* <p>If this value is greater than 1, then the device supports controlling the
* flashlight brightness level via
- * {android.hardware.camera2.CameraManager#setTorchStrengthLevel}.
+ * {android.hardware.camera2.CameraManager#turnOnTorchWithStrengthLevel}.
* If this value is equal to 1, flashlight brightness control is not supported.
* The value for this key will be null for devices with no flash unit.</p>
* <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -1335,7 +1335,7 @@
/**
* <p>Default flashlight brightness level to be set via
- * {android.hardware.camera2.CameraManager#setTorchStrengthLevel}.</p>
+ * {android.hardware.camera2.CameraManager#turnOnTorchWithStrengthLevel}.</p>
* <p>If flash unit is available this will be greater than or equal to 1 and less
* or equal to <code>{@link CameraCharacteristics#FLASH_INFO_STRENGTH_MAXIMUM_LEVEL android.flash.info.strengthMaximumLevel}</code>.</p>
* <p>Setting flashlight brightness above the default level
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 0af322e..0954013 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -528,6 +528,7 @@
public String toString() {
StringBuilder out = new StringBuilder("ApduService: ");
out.append(getComponent());
+ out.append(", UID: " + mUid);
out.append(", description: " + mDescription);
out.append(", Static AID Groups: ");
for (AidGroup aidGroup : mStaticAidGroups.values()) {
@@ -546,7 +547,8 @@
if (!(o instanceof ApduServiceInfo)) return false;
ApduServiceInfo thatService = (ApduServiceInfo) o;
- return thatService.getComponent().equals(this.getComponent());
+ return thatService.getComponent().equals(this.getComponent())
+ && thatService.getUid() == this.getUid();
}
@Override
@@ -619,8 +621,9 @@
};
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println(" " + getComponent() +
- " (Description: " + getDescription() + ")");
+ pw.println(" " + getComponent()
+ + " (Description: " + getDescription() + ")"
+ + " (UID: " + getUid() + ")");
if (mOnHost) {
pw.println(" On Host Service");
} else {
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index d498535..0a9fe90 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -30,6 +30,7 @@
import android.nfc.INfcCardEmulation;
import android.nfc.NfcAdapter;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;
@@ -83,6 +84,13 @@
public static final String EXTRA_SERVICE_COMPONENT = "component";
/**
+ * The caller userId extra for {@link #ACTION_CHANGE_DEFAULT}.
+ *
+ * @see #ACTION_CHANGE_DEFAULT
+ */
+ public static final String EXTRA_USERID = "android.nfc.cardemulation.extra.USERID";
+
+ /**
* Category used for NFC payment services.
*/
public static final String CATEGORY_PAYMENT = "payment";
@@ -269,8 +277,8 @@
if (CATEGORY_PAYMENT.equals(category)) {
boolean preferForeground = false;
try {
- preferForeground = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.NFC_PAYMENT_FOREGROUND) != 0;
+ preferForeground = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.NFC_PAYMENT_FOREGROUND, UserHandle.myUserId()) != 0;
} catch (SettingNotFoundException e) {
}
return preferForeground;
@@ -829,6 +837,28 @@
/**
* @hide
*/
+ public boolean setDefaultForNextTap(int userId, ComponentName service) {
+ try {
+ return sService.setDefaultForNextTap(userId, service);
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
+ try {
+ return sService.setDefaultForNextTap(userId, service);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return false;
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
public List<ApduServiceInfo> getServices(String category) {
try {
return sService.getServices(mContext.getUserId(), category);
@@ -849,6 +879,28 @@
}
/**
+ * @hide
+ */
+ public List<ApduServiceInfo> getServices(String category, int userId) {
+ try {
+ return sService.getServices(userId, category);
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return null;
+ }
+ try {
+ return sService.getServices(userId, category);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return null;
+ }
+ }
+ }
+
+ /**
* A valid AID according to ISO/IEC 7816-4:
* <ul>
* <li>Has >= 5 bytes and <=16 bytes (>=10 hex chars and <= 32 hex chars)
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index b839706..50ca9ff 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -20,6 +20,7 @@
import android.os.Bundle;
import android.os.IUserRestrictionsListener;
import android.os.PersistableBundle;
+import android.os.UserHandle;
import android.os.UserManager;
import android.content.pm.UserInfo;
import android.content.IntentSender;
@@ -91,6 +92,9 @@
boolean markGuestForDeletion(int userId);
UserInfo findCurrentGuestUser();
boolean isQuietModeEnabled(int userId);
+ UserHandle createUserWithAttributes(in String userName, in String userType, int flags,
+ in Bitmap userIcon,
+ in String accountName, in String accountType, in PersistableBundle accountOptions);
void setSeedAccountData(int userId, in String accountName,
in String accountType, in PersistableBundle accountOptions, boolean persist);
String getSeedAccountName(int userId);
@@ -98,6 +102,7 @@
PersistableBundle getSeedAccountOptions(int userId);
void clearSeedAccountData(int userId);
boolean someUserHasSeedAccount(in String accountName, in String accountType);
+ boolean someUserHasAccount(in String accountName, in String accountType);
boolean isProfile(int userId);
boolean isManagedProfile(int userId);
boolean isCloneProfile(int userId);
diff --git a/core/java/android/os/NewUserRequest.java b/core/java/android/os/NewUserRequest.java
index 2ebc01f..b0e1f91 100644
--- a/core/java/android/os/NewUserRequest.java
+++ b/core/java/android/os/NewUserRequest.java
@@ -17,7 +17,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.text.TextUtils;
/**
* Contains necessary information to create user using
@@ -26,6 +30,7 @@
* @hide
*/
@SystemApi
+@SuppressLint("PackageLayering")
public final class NewUserRequest {
@Nullable
private final String mName;
@@ -33,16 +38,24 @@
private final boolean mEphemeral;
@NonNull
private final String mUserType;
+ private final Bitmap mUserIcon;
+ private final String mAccountName;
+ private final String mAccountType;
+ private final PersistableBundle mAccountOptions;
private NewUserRequest(Builder builder) {
mName = builder.mName;
mAdmin = builder.mAdmin;
mEphemeral = builder.mEphemeral;
mUserType = builder.mUserType;
+ mUserIcon = builder.mUserIcon;
+ mAccountName = builder.mAccountName;
+ mAccountType = builder.mAccountType;
+ mAccountOptions = builder.mAccountOptions;
}
/**
- * Gets the user name.
+ * Returns the name of the user.
*/
@Nullable
public String getName() {
@@ -50,7 +63,7 @@
}
/**
- * Is user Ephemenral?
+ * Returns whether the user is ephemeral.
*
* <p> Ephemeral user will be removed after leaving the foreground.
*/
@@ -59,7 +72,7 @@
}
/**
- * Is user Admin?
+ * Returns whether the user is an admin.
*
* <p> Admin user is with administrative privileges and such user can create and
* delete users.
@@ -69,7 +82,17 @@
}
/**
- * Gets user type.
+ * Returns the calculated flags for user creation.
+ */
+ int getFlags() {
+ int flags = 0;
+ if (isAdmin()) flags |= UserInfo.FLAG_ADMIN;
+ if (isEphemeral()) flags |= UserInfo.FLAG_EPHEMERAL;
+ return flags;
+ }
+
+ /**
+ * Returns the user type.
*
* <p> Supported types are {@link UserManager.USER_TYPE_FULL_SECONDARY} and
* {@link USER_TYPE_FULL_GUEST}
@@ -79,25 +102,71 @@
return mUserType;
}
+ /**
+ * Returns the user icon.
+ */
+ @Nullable
+ public Bitmap getUserIcon() {
+ return mUserIcon;
+ }
+
+ /**
+ * Returns the account name.
+ */
+ @Nullable
+ public String getAccountName() {
+ return mAccountName;
+ }
+
+ /**
+ * Returns the account type.
+ */
+ @Nullable
+ public String getAccountType() {
+ return mAccountType;
+ }
+
+ /**
+ * Returns the account options.
+ */
+ @SuppressLint("NullableCollection")
+ @Nullable
+ public PersistableBundle getAccountOptions() {
+ return mAccountOptions;
+ }
+
@Override
public String toString() {
- return String.format(
- "NewUserRequest- UserName:%s, userType:%s, IsAdmin:%s, IsEphemeral:%s.", mName,
- mUserType, mAdmin, mEphemeral);
+ return "NewUserRequest{"
+ + "mName='" + mName + '\''
+ + ", mAdmin=" + mAdmin
+ + ", mEphemeral=" + mEphemeral
+ + ", mUserType='" + mUserType + '\''
+ + ", mAccountName='" + mAccountName + '\''
+ + ", mAccountType='" + mAccountType + '\''
+ + ", mAccountOptions=" + mAccountOptions
+ + '}';
}
/**
* Builder for building {@link NewUserRequest}
*/
+ @SuppressLint("PackageLayering")
public static final class Builder {
private String mName;
private boolean mAdmin;
private boolean mEphemeral;
private String mUserType = UserManager.USER_TYPE_FULL_SECONDARY;
+ private Bitmap mUserIcon;
+ private String mAccountName;
+ private String mAccountType;
+ private PersistableBundle mAccountOptions;
/**
* Sets user name.
+ *
+ * @return This object for method chaining.
*/
@NonNull
public Builder setName(@Nullable String name) {
@@ -110,6 +179,8 @@
*
* <p> Admin user is with administrative privileges and such user can create
* and delete users.
+ *
+ * @return This object for method chaining.
*/
@NonNull
public Builder setAdmin() {
@@ -121,6 +192,8 @@
* Sets user as ephemeral.
*
* <p> Ephemeral user will be removed after leaving the foreground.
+ *
+ * @return This object for method chaining.
*/
@NonNull
public Builder setEphemeral() {
@@ -134,6 +207,8 @@
* Supported types are {@link UserManager.USER_TYPE_FULL_SECONDARY} and
* {@link UserManager.USER_TYPE_FULL_GUEST}. Default value is
* {@link UserManager.USER_TYPE_FULL_SECONDARY}.
+ *
+ * @return This object for method chaining.
*/
@NonNull
public Builder setUserType(@NonNull String type) {
@@ -142,6 +217,54 @@
}
/**
+ * Sets user icon.
+ *
+ * @return This object for method chaining.
+ */
+ @NonNull
+ public Builder setUserIcon(@Nullable Bitmap userIcon) {
+ mUserIcon = userIcon;
+ return this;
+ }
+
+ /**
+ * Sets account name that will be used by the setup wizard to initialize the user.
+ *
+ * @see android.accounts.Account
+ * @return This object for method chaining.
+ */
+ @NonNull
+ public Builder setAccountName(@Nullable String accountName) {
+ mAccountName = accountName;
+ return this;
+ }
+
+ /**
+ * Sets account type for the account to be created. This is required if the account name
+ * is not null. This will be used by the setup wizard to initialize the user.
+ *
+ * @see android.accounts.Account
+ * @return This object for method chaining.
+ */
+ @NonNull
+ public Builder setAccountType(@Nullable String accountType) {
+ mAccountType = accountType;
+ return this;
+ }
+
+ /**
+ * Sets account options that can contain account-specific extra information
+ * to be used by setup wizard to initialize the account for the user.
+ *
+ * @return This object for method chaining.
+ */
+ @NonNull
+ public Builder setAccountOptions(@Nullable PersistableBundle accountOptions) {
+ mAccountOptions = accountOptions;
+ return this;
+ }
+
+ /**
* Builds {@link NewUserRequest}
*
* @throws IllegalStateException if builder is configured with incompatible properties and
@@ -165,6 +288,11 @@
&& mUserType != UserManager.USER_TYPE_FULL_GUEST) {
throw new IllegalStateException("Unsupported user type: " + mUserType);
}
+
+ if (TextUtils.isEmpty(mAccountName) != TextUtils.isEmpty(mAccountType)) {
+ throw new IllegalStateException(
+ "Account name and account type should be provided together.");
+ }
}
}
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 94375c0..cf4ce9b 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -70,6 +70,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
/**
@@ -1661,6 +1662,14 @@
public static final int USER_OPERATION_ERROR_MAX_USERS = 6;
/**
+ * Indicates user operation failed because a user with that account already exists.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS = 7;
+
+ /**
* Result returned from various user operations.
*
* @hide
@@ -1673,7 +1682,8 @@
USER_OPERATION_ERROR_MAX_RUNNING_USERS,
USER_OPERATION_ERROR_CURRENT_USER,
USER_OPERATION_ERROR_LOW_STORAGE,
- USER_OPERATION_ERROR_MAX_USERS
+ USER_OPERATION_ERROR_MAX_USERS,
+ USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS
})
public @interface UserOperationResult {}
@@ -3159,26 +3169,24 @@
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
public @NonNull NewUserResponse createUser(@NonNull NewUserRequest newUserRequest) {
- UserInfo user = null;
- int operationResult = USER_OPERATION_ERROR_UNKNOWN;
try {
- user = createUser(newUserRequest.getName(), newUserRequest.getUserType(),
- determineFlagsForUserCreation(newUserRequest));
- } catch (UserOperationException e) {
- Log.w(TAG, "Exception while creating user " + newUserRequest, e);
- operationResult = e.getUserOperationResult();
- }
- if (user == null) {
- return new NewUserResponse(null, operationResult);
- }
- return new NewUserResponse(user.getUserHandle(), USER_OPERATION_SUCCESS);
- }
+ final UserHandle userHandle = mService.createUserWithAttributes(
+ newUserRequest.getName(),
+ newUserRequest.getUserType(),
+ newUserRequest.getFlags(),
+ newUserRequest.getUserIcon(),
+ newUserRequest.getAccountName(),
+ newUserRequest.getAccountType(),
+ newUserRequest.getAccountOptions());
- private int determineFlagsForUserCreation(NewUserRequest newUserRequest) {
- int flags = 0;
- if (newUserRequest.isAdmin()) flags |= UserInfo.FLAG_ADMIN;
- if (newUserRequest.isEphemeral()) flags |= UserInfo.FLAG_EPHEMERAL;
- return flags;
+ return new NewUserResponse(userHandle, USER_OPERATION_SUCCESS);
+
+ } catch (ServiceSpecificException e) {
+ Log.w(TAG, "Exception while creating user " + newUserRequest, e);
+ return new NewUserResponse(null, e.errorCode);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
}
/**
@@ -4913,12 +4921,12 @@
}
/**
- * @hide
* Checks if any uninitialized user has the specific seed account name and type.
*
* @param accountName The account name to check for
* @param accountType The account type of the account to check for
* @return whether the seed account was found
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public boolean someUserHasSeedAccount(String accountName, String accountType) {
@@ -4930,6 +4938,29 @@
}
/**
+ * Checks if any initialized or uninitialized user has the specific account name and type.
+ *
+ * @param accountName The account name to check for
+ * @param accountType The account type of the account to check for
+ * @return whether the account was found
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
+ Manifest.permission.CREATE_USERS})
+ public boolean someUserHasAccount(
+ @NonNull String accountName, @NonNull String accountType) {
+ Objects.requireNonNull(accountName, "accountName must not be null");
+ Objects.requireNonNull(accountType, "accountType must not be null");
+
+ try {
+ return mService.someUserHasAccount(accountName, accountType);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* @hide
* User that enforces a restriction.
*
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ae09b45..cc95c1f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4537,6 +4537,25 @@
"haptic_feedback_intensity";
/**
+ * The intensity of haptic feedback vibrations for interaction with hardware components from
+ * the device, like buttons and sensors, if configurable.
+ *
+ * Not all devices are capable of changing their feedback intensity; on these devices
+ * there will likely be no difference between the various vibration intensities except for
+ * intensity 0 (off) and the rest.
+ *
+ * <b>Values:</b><br/>
+ * 0 - Vibration is disabled<br/>
+ * 1 - Weak vibrations<br/>
+ * 2 - Medium vibrations<br/>
+ * 3 - Strong vibrations
+ * @hide
+ */
+ @Readable
+ public static final String HARDWARE_HAPTIC_FEEDBACK_INTENSITY =
+ "hardware_haptic_feedback_intensity";
+
+ /**
* Ringer volume. This is used internally, changing this value will not
* change the volume. See AudioManager.
*
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 1b38f59..5d84af0 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -3584,6 +3584,23 @@
"content://telephony/carriers/enforce_managed");
/**
+ * The {@code content://} style URL for the perferred APN used for internet.
+ *
+ * @hide
+ */
+ public static final Uri PREFERRED_APN_URI = Uri.parse(
+ "content://telephony/carriers/preferapn/subId/");
+
+ /**
+ * The {@code content://} style URL for the perferred APN set id.
+ *
+ * @hide
+ */
+ public static final Uri PREFERRED_APN_SET_URI = Uri.parse(
+ "content://telephony/carriers/preferapnset/subId/");
+
+
+ /**
* The column name for ENFORCE_MANAGED_URI, indicates whether DPC-owned APNs are enforced.
* @hide
*/
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index ec613ed..c5bc99d 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -153,11 +153,20 @@
/**
* Invocation of the voice assistant via hardware button.
+ * This is a private constant. Feel free to renumber as desired.
* @hide
*/
public static final int ASSISTANT_BUTTON = 10002;
/**
+ * The user has performed a long press on the power button hardware that is resulting
+ * in an action being performed.
+ * This is a private constant. Feel free to renumber as desired.
+ * @hide
+ */
+ public static final int LONG_PRESS_POWER_BUTTON = 10003;
+
+ /**
* Flag for {@link View#performHapticFeedback(int, int)
* View.performHapticFeedback(int, int)}: Ignore the setting in the
* view for whether to perform haptic feedback, do it always.
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 1460cb2..c3a638c 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -295,7 +295,8 @@
/** Key code constant: Fast Forward media key. */
public static final int KEYCODE_MEDIA_FAST_FORWARD = 90;
/** Key code constant: Mute key.
- * Mutes the microphone, unlike {@link #KEYCODE_VOLUME_MUTE}. */
+ * Mute key for the microphone (unlike {@link #KEYCODE_VOLUME_MUTE}, which is the speaker mute
+ * key). */
public static final int KEYCODE_MUTE = 91;
/** Key code constant: Page Up key. */
public static final int KEYCODE_PAGE_UP = 92;
@@ -482,9 +483,10 @@
/** Key code constant: Numeric keypad ')' key. */
public static final int KEYCODE_NUMPAD_RIGHT_PAREN = 163;
/** Key code constant: Volume Mute key.
- * Mutes the speaker, unlike {@link #KEYCODE_MUTE}.
- * This key should normally be implemented as a toggle such that the first press
- * mutes the speaker and the second press restores the original volume. */
+ * Mute key for speaker (unlike {@link #KEYCODE_MUTE}, which is the mute key for the
+ * microphone). This key should normally be implemented as a toggle such that the first press
+ * mutes the speaker and the second press restores the original volume.
+ */
public static final int KEYCODE_VOLUME_MUTE = 164;
/** Key code constant: Info key.
* Common on TV remotes to show additional information related to what is
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 3b4fcc0..7fe810a 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -129,17 +129,15 @@
/**
* The interface that apps use to talk to the window manager.
- * </p><p>
- * Each window manager instance is bound to a particular {@link Display}.
- * To obtain a {@link WindowManager} for a different display, use
- * {@link Context#createDisplayContext} to obtain a {@link Context} for that
- * display, then use <code>Context.getSystemService(Context.WINDOW_SERVICE)</code>
- * to get the WindowManager.
- * </p><p>
- * The simplest way to show a window on another display is to create a
- * {@link Presentation}. The presentation will automatically obtain a
- * {@link WindowManager} and {@link Context} for that display.
- * </p>
+ * <p>
+ * Each window manager instance is bound to a {@link Display}. To obtain the
+ * <code>WindowManager</code> associated with a display,
+ * call {@link Context#createWindowContext(Display, int, Bundle)} to get the display's UI context,
+ * then call {@link Context#getSystemService(String)} or {@link Context#getSystemService(Class)} on
+ * the UI context.
+ * <p>
+ * The simplest way to show a window on a particular display is to create a {@link Presentation},
+ * which automatically obtains a <code>WindowManager</code> and context for the display.
*/
@SystemService(Context.WINDOW_SERVICE)
public interface WindowManager extends ViewManager {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d3ee98a..601280a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -6395,6 +6395,10 @@
android:permission="android.permission.BIND_JOB_SERVICE">
</service>
+ <service android:name="com.android.server.compos.IsolatedCompilationJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE">
+ </service>
+
<service android:name="com.android.server.PruneInstantAppsJobService"
android:permission="android.permission.BIND_JOB_SERVICE" >
</service>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index d239e56..287d0fb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -244,15 +244,24 @@
// Fullscreen
//
+ // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+ @BindsOptionalOf
+ @DynamicOverride
+ abstract FullscreenTaskListener optionalFullscreenTaskListener();
+
@WMSingleton
@Provides
static FullscreenTaskListener provideFullscreenTaskListener(
+ @DynamicOverride Optional<FullscreenTaskListener> fullscreenTaskListener,
SyncTransactionQueue syncQueue,
Optional<FullscreenUnfoldController> optionalFullscreenUnfoldController,
- Optional<RecentTasksController> recentTasksOptional
- ) {
- return new FullscreenTaskListener(syncQueue, optionalFullscreenUnfoldController,
- recentTasksOptional);
+ Optional<RecentTasksController> recentTasksOptional) {
+ if (fullscreenTaskListener.isPresent()) {
+ return fullscreenTaskListener.get();
+ } else {
+ return new FullscreenTaskListener(syncQueue, optionalFullscreenUnfoldController,
+ recentTasksOptional);
+ }
}
//
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 8f04cfb..f43586f 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -17,24 +17,29 @@
#define LOG_TAG "PointerController"
//#define LOG_NDEBUG 0
-// Log debug messages about pointer updates
-#define DEBUG_POINTER_UPDATES 0
-
#include "PointerController.h"
-#include "MouseCursorController.h"
#include "PointerControllerContext.h"
-#include "TouchSpotController.h"
-#include <log/log.h>
-
-#include <SkBitmap.h>
#include <SkBlendMode.h>
#include <SkCanvas.h>
#include <SkColor.h>
-#include <SkPaint.h>
namespace android {
+namespace {
+
+const ui::Transform kIdentityTransform;
+
+} // namespace
+
+// --- PointerController::DisplayInfoListener ---
+
+void PointerController::DisplayInfoListener::onWindowInfosChanged(
+ const std::vector<android::gui::WindowInfo>&,
+ const std::vector<android::gui::DisplayInfo>& displayInfo) {
+ mPointerController.onDisplayInfosChanged(displayInfo);
+}
+
// --- PointerController ---
std::shared_ptr<PointerController> PointerController::create(
@@ -63,9 +68,16 @@
PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
const sp<Looper>& looper,
const sp<SpriteController>& spriteController)
- : mContext(policy, looper, spriteController, *this), mCursorController(mContext) {
+ : mContext(policy, looper, spriteController, *this),
+ mCursorController(mContext),
+ mDisplayInfoListener(new DisplayInfoListener(*this)) {
std::scoped_lock lock(mLock);
mLocked.presentation = Presentation::SPOT;
+ SurfaceComposerClient::getDefault()->addWindowInfosListener(mDisplayInfoListener);
+}
+
+PointerController::~PointerController() {
+ SurfaceComposerClient::getDefault()->removeWindowInfosListener(mDisplayInfoListener);
}
bool PointerController::getBounds(float* outMinX, float* outMinY, float* outMaxX,
@@ -74,7 +86,14 @@
}
void PointerController::move(float deltaX, float deltaY) {
- mCursorController.move(deltaX, deltaY);
+ const int32_t displayId = mCursorController.getDisplayId();
+ vec2 transformed;
+ {
+ std::scoped_lock lock(mLock);
+ const auto& transform = getTransformForDisplayLocked(displayId);
+ transformed = transformWithoutTranslation(transform, {deltaX, deltaY});
+ }
+ mCursorController.move(transformed.x, transformed.y);
}
void PointerController::setButtonState(int32_t buttonState) {
@@ -86,12 +105,26 @@
}
void PointerController::setPosition(float x, float y) {
- std::scoped_lock lock(mLock);
- mCursorController.setPosition(x, y);
+ const int32_t displayId = mCursorController.getDisplayId();
+ vec2 transformed;
+ {
+ std::scoped_lock lock(mLock);
+ const auto& transform = getTransformForDisplayLocked(displayId);
+ transformed = transform.transform(x, y);
+ }
+ mCursorController.setPosition(transformed.x, transformed.y);
}
void PointerController::getPosition(float* outX, float* outY) const {
+ const int32_t displayId = mCursorController.getDisplayId();
mCursorController.getPosition(outX, outY);
+ {
+ std::scoped_lock lock(mLock);
+ const auto& transform = getTransformForDisplayLocked(displayId);
+ const auto xy = transform.inverse().transform(*outX, *outY);
+ *outX = xy.x;
+ *outY = xy.y;
+ }
}
int32_t PointerController::getDisplayId() const {
@@ -130,11 +163,25 @@
void PointerController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
BitSet32 spotIdBits, int32_t displayId) {
std::scoped_lock lock(mLock);
+ std::array<PointerCoords, MAX_POINTERS> outSpotCoords{};
+ const ui::Transform& transform = getTransformForDisplayLocked(displayId);
+
+ for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) {
+ const uint32_t index = spotIdToIndex[idBits.clearFirstMarkedBit()];
+
+ const vec2 xy = transform.transform(spotCoords[index].getXYValue());
+ outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_X, xy.x);
+ outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y);
+
+ float pressure = spotCoords[index].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
+ outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
+ }
+
auto it = mLocked.spotControllers.find(displayId);
if (it == mLocked.spotControllers.end()) {
mLocked.spotControllers.try_emplace(displayId, displayId, mContext);
}
- mLocked.spotControllers.at(displayId).setSpots(spotCoords, spotIdToIndex, spotIdBits);
+ mLocked.spotControllers.at(displayId).setSpots(outSpotCoords.data(), spotIdToIndex, spotIdBits);
}
void PointerController::clearSpots() {
@@ -194,7 +241,7 @@
void PointerController::onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports) {
std::unordered_set<int32_t> displayIdSet;
- for (DisplayViewport viewport : viewports) {
+ for (const DisplayViewport& viewport : viewports) {
displayIdSet.insert(viewport.displayId);
}
@@ -214,4 +261,17 @@
}
}
+void PointerController::onDisplayInfosChanged(const std::vector<gui::DisplayInfo>& displayInfo) {
+ std::scoped_lock lock(mLock);
+ mLocked.mDisplayInfos = displayInfo;
+}
+
+const ui::Transform& PointerController::getTransformForDisplayLocked(int displayId) const {
+ const auto& di = mLocked.mDisplayInfos;
+ auto it = std::find_if(di.begin(), di.end(), [displayId](const gui::DisplayInfo& info) {
+ return info.displayId == displayId;
+ });
+ return it != di.end() ? it->transform : kIdentityTransform;
+}
+
} // namespace android
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 97567ba..796077f 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -47,7 +47,7 @@
const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
const sp<SpriteController>& spriteController);
- virtual ~PointerController() = default;
+ ~PointerController() override;
virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
virtual void move(float deltaX, float deltaY);
@@ -72,6 +72,8 @@
void reloadPointerResources();
void onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports);
+ void onDisplayInfosChanged(const std::vector<gui::DisplayInfo>& displayInfos);
+
private:
friend PointerControllerContext::LooperCallback;
friend PointerControllerContext::MessageHandler;
@@ -85,9 +87,23 @@
struct Locked {
Presentation presentation;
+ std::vector<gui::DisplayInfo> mDisplayInfos;
std::unordered_map<int32_t /* displayId */, TouchSpotController> spotControllers;
} mLocked GUARDED_BY(mLock);
+ class DisplayInfoListener : public gui::WindowInfosListener {
+ public:
+ explicit DisplayInfoListener(PointerController& pc) : mPointerController(pc){};
+ void onWindowInfosChanged(const std::vector<android::gui::WindowInfo>&,
+ const std::vector<android::gui::DisplayInfo>&) override;
+
+ private:
+ PointerController& mPointerController;
+ };
+ sp<DisplayInfoListener> mDisplayInfoListener;
+
+ const ui::Transform& getTransformForDisplayLocked(int displayId) const REQUIRES(mLock);
+
PointerController(const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
const sp<SpriteController>& spriteController);
void clearSpotsLocked();
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 58d2185..1df1bce 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -160,10 +160,12 @@
private void registerIntentReceiver(BroadcastReceiver receiver, IntentFilter filter) {
if (mUserHandle == null) {
// If userHandle has not been provided, simply call registerReceiver.
- mContext.registerReceiver(receiver, filter, null, mReceiverHandler);
+ mContext.registerReceiver(receiver, filter, null, mReceiverHandler,
+ Context.RECEIVER_EXPORTED);
} else {
// userHandle was explicitly specified, so need to call multi-user aware API.
- mContext.registerReceiverAsUser(receiver, mUserHandle, filter, null, mReceiverHandler);
+ mContext.registerReceiverAsUser(receiver, mUserHandle, filter, null, mReceiverHandler,
+ Context.RECEIVER_EXPORTED);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
index a210e90..8b17be1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
@@ -19,7 +19,6 @@
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.AlertDialog;
-import android.app.Dialog;
import android.app.NotificationManager;
import android.content.Context;
import android.content.DialogInterface;
@@ -85,6 +84,7 @@
@VisibleForTesting
protected Context mContext;
+ private final int mThemeResId;
@VisibleForTesting
protected TextView mZenAlarmWarning;
@VisibleForTesting
@@ -97,10 +97,15 @@
protected LayoutInflater mLayoutInflater;
public EnableZenModeDialog(Context context) {
- mContext = context;
+ this(context, 0);
}
- public Dialog createDialog() {
+ public EnableZenModeDialog(Context context, int themeResId) {
+ mContext = context;
+ mThemeResId = themeResId;
+ }
+
+ public AlertDialog createDialog() {
mNotificationManager = (NotificationManager) mContext.
getSystemService(Context.NOTIFICATION_SERVICE);
mForeverId = Condition.newId(mContext).appendPath("forever").build();
@@ -108,7 +113,7 @@
mUserId = mContext.getUserId();
mAttached = false;
- final AlertDialog.Builder builder = new AlertDialog.Builder(mContext)
+ final AlertDialog.Builder builder = new AlertDialog.Builder(mContext, mThemeResId)
.setTitle(R.string.zen_mode_settings_turn_on_dialog_title)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.zen_mode_enable_dialog_turn_on,
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
index 0fe4efe..a944bf5 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
@@ -80,6 +80,7 @@
Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
Settings.System.RING_VIBRATION_INTENSITY,
Settings.System.HAPTIC_FEEDBACK_INTENSITY,
+ Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY,
Settings.System.DISPLAY_COLOR_MODE_VENDOR_HINT, // must precede DISPLAY_COLOR_MODE
Settings.System.DISPLAY_COLOR_MODE,
Settings.System.ALARM_ALERT,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 462c3a5..63acffb 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -120,6 +120,7 @@
VALIDATORS.put(System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
VALIDATORS.put(System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
VALIDATORS.put(System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
+ VALIDATORS.put(System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
VALIDATORS.put(System.RINGTONE, URI_VALIDATOR);
VALIDATORS.put(System.NOTIFICATION_SOUND, URI_VALIDATOR);
VALIDATORS.put(System.ALARM_ALERT, URI_VALIDATOR);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index e24f07c..b56d189 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -801,13 +801,16 @@
mHandler.postDelayed(mRetryFingerprintAuthentication, HAL_ERROR_RETRY_TIMEOUT);
}
+ boolean lockedOutStateChanged = false;
if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
+ lockedOutStateChanged |= !mFingerprintLockedOutPermanent;
mFingerprintLockedOutPermanent = true;
requireStrongAuthIfAllLockedOut();
}
if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT
|| msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
+ lockedOutStateChanged |= !mFingerprintLockedOut;
mFingerprintLockedOut = true;
if (isUdfpsEnrolled()) {
updateFingerprintListeningState();
@@ -820,9 +823,14 @@
cb.onBiometricError(msgId, errString, BiometricSourceType.FINGERPRINT);
}
}
+
+ if (lockedOutStateChanged) {
+ notifyLockedOutStateChanged(BiometricSourceType.FINGERPRINT);
+ }
}
private void handleFingerprintLockoutReset() {
+ boolean changed = mFingerprintLockedOut || mFingerprintLockedOutPermanent;
mFingerprintLockedOut = false;
mFingerprintLockedOutPermanent = false;
@@ -837,6 +845,10 @@
} else {
updateFingerprintListeningState();
}
+
+ if (changed) {
+ notifyLockedOutStateChanged(BiometricSourceType.FINGERPRINT);
+ }
}
private void setFingerprintRunningState(int fingerprintRunningState) {
@@ -999,7 +1011,9 @@
}
}
+ boolean lockedOutStateChanged = false;
if (msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT) {
+ lockedOutStateChanged = !mFaceLockedOutPermanent;
mFaceLockedOutPermanent = true;
requireStrongAuthIfAllLockedOut();
}
@@ -1011,11 +1025,21 @@
BiometricSourceType.FACE);
}
}
+
+ if (lockedOutStateChanged) {
+ notifyLockedOutStateChanged(BiometricSourceType.FACE);
+ }
}
private void handleFaceLockoutReset() {
+ boolean changed = mFaceLockedOutPermanent;
mFaceLockedOutPermanent = false;
+
updateFaceListeningState();
+
+ if (changed) {
+ notifyLockedOutStateChanged(BiometricSourceType.FACE);
+ }
}
private void setFaceRunningState(int faceRunningState) {
@@ -1237,6 +1261,16 @@
}
}
+ private void notifyLockedOutStateChanged(BiometricSourceType type) {
+ Assert.isMainThread();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+ if (cb != null) {
+ cb.onLockedOutStateChanged(type);
+ }
+ }
+ }
+
public boolean isScreenOn() {
return mScreenOn;
}
@@ -2454,6 +2488,10 @@
}
}
+ public boolean isFingerprintLockedOut() {
+ return mFingerprintLockedOut || mFingerprintLockedOutPermanent;
+ }
+
/**
* If biometrics hardware is available, not disabled, and user has enrolled templates.
* This does NOT check if the device is encrypted or in lockdown.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 12431984..8170a81 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -292,6 +292,11 @@
public void onStrongAuthStateChanged(int userId) { }
/**
+ * When the current user's locked out state changed.
+ */
+ public void onLockedOutStateChanged(BiometricSourceType biometricSourceType) { }
+
+ /**
* Called when the dream's window state is changed.
* @param dreaming true if the dream's window has been created and is visible
*/
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 223eb78..8f4d6f6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -255,7 +255,6 @@
private void maybeShowInputBouncer() {
if (mShowingUdfpsBouncer && hasUdfpsBouncerShownWithMinTime()) {
mKeyguardViewManager.showBouncer(true);
- mKeyguardViewManager.resetAlternateAuth(false);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index e97e762..fb7ab60 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -793,7 +793,8 @@
return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
} else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) {
return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
- } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) {
+ } else if (any && ((strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0
+ || mUpdateMonitor.isFingerprintLockedOut())) {
return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
} else if (any && (strongAuth & STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE) != 0) {
return KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
index 98b9146..fce0c0c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
@@ -17,8 +17,10 @@
package com.android.systemui.qs
import android.content.Intent
+import android.os.Handler
import android.os.UserManager
import android.provider.Settings
+import android.provider.Settings.Global.USER_SWITCHER_ENABLED
import android.view.View
import android.widget.Toast
import androidx.annotation.VisibleForTesting
@@ -35,6 +37,7 @@
import com.android.systemui.qs.FooterActionsController.ExpansionState.COLLAPSED
import com.android.systemui.qs.FooterActionsController.ExpansionState.EXPANDED
import com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED
+import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.phone.MultiUserSwitchController
import com.android.systemui.statusbar.phone.SettingsButton
import com.android.systemui.statusbar.policy.DeviceProvisionedController
@@ -42,6 +45,7 @@
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener
import com.android.systemui.tuner.TunerService
import com.android.systemui.util.ViewController
+import com.android.systemui.util.settings.GlobalSettings
import javax.inject.Inject
import javax.inject.Named
@@ -55,6 +59,7 @@
private val qsPanelController: QSPanelController,
private val activityStarter: ActivityStarter,
private val userManager: UserManager,
+ private val userTracker: UserTracker,
private val userInfoController: UserInfoController,
private val multiUserSwitchController: MultiUserSwitchController,
private val deviceProvisionedController: DeviceProvisionedController,
@@ -64,7 +69,9 @@
private val globalActionsDialog: GlobalActionsDialogLite,
private val uiEventLogger: UiEventLogger,
@Named(PM_LITE_ENABLED) private val showPMLiteButton: Boolean,
- private val buttonsVisibleState: ExpansionState
+ private val buttonsVisibleState: ExpansionState,
+ private val globalSetting: GlobalSettings,
+ private val handler: Handler
) : ViewController<FooterActionsView>(view) {
enum class ExpansionState { COLLAPSED, EXPANDED }
@@ -83,6 +90,16 @@
mView.onUserInfoChanged(picture, isGuestUser)
}
+ private val multiUserSetting =
+ object : SettingObserver(
+ globalSetting, handler, USER_SWITCHER_ENABLED, userTracker.userId) {
+ override fun handleValueChanged(value: Int, observedChange: Boolean) {
+ if (observedChange) {
+ updateView()
+ }
+ }
+ }
+
private val onClickListener = View.OnClickListener { v ->
// Don't do anything until views are unhidden. Don't do anything if the tap looks
// suspicious.
@@ -182,6 +199,7 @@
return
}
this.listening = listening
+ multiUserSetting.isListening = listening
if (this.listening) {
userInfoController.addCallback(onUserInfoChangedListener)
updateView()
@@ -215,4 +233,4 @@
}
private fun isTunerEnabled() = tunerService.isTunerEnabled
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt
index f6c89a9..dd4dc87 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt
@@ -16,18 +16,22 @@
package com.android.systemui.qs
+import android.os.Handler
import android.os.UserManager
import com.android.internal.logging.MetricsLogger
import com.android.internal.logging.UiEventLogger
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.globalactions.GlobalActionsDialogLite
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.qs.FooterActionsController.ExpansionState
import com.android.systemui.qs.dagger.QSFlagsModule
+import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.phone.MultiUserSwitchController
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.statusbar.policy.UserInfoController
import com.android.systemui.tuner.TunerService
+import com.android.systemui.util.settings.GlobalSettings
import javax.inject.Inject
import javax.inject.Named
@@ -35,6 +39,7 @@
private val qsPanelController: QSPanelController,
private val activityStarter: ActivityStarter,
private val userManager: UserManager,
+ private val userTracker: UserTracker,
private val userInfoController: UserInfoController,
private val multiUserSwitchControllerFactory: MultiUserSwitchController.Factory,
private val deviceProvisionedController: DeviceProvisionedController,
@@ -43,7 +48,9 @@
private val tunerService: TunerService,
private val globalActionsDialog: GlobalActionsDialogLite,
private val uiEventLogger: UiEventLogger,
- @Named(QSFlagsModule.PM_LITE_ENABLED) private val showPMLiteButton: Boolean
+ @Named(QSFlagsModule.PM_LITE_ENABLED) private val showPMLiteButton: Boolean,
+ private val globalSettings: GlobalSettings,
+ @Main private val handler: Handler
) {
private lateinit var view: FooterActionsView
private lateinit var buttonsVisibleState: ExpansionState
@@ -60,8 +67,9 @@
fun build(): FooterActionsController {
return FooterActionsController(view, qsPanelController, activityStarter, userManager,
- userInfoController, multiUserSwitchControllerFactory.create(view),
+ userTracker, userInfoController, multiUserSwitchControllerFactory.create(view),
deviceProvisionedController, falsingManager, metricsLogger, tunerService,
- globalActionsDialog, uiEventLogger, showPMLiteButton, buttonsVisibleState)
+ globalActionsDialog, uiEventLogger, showPMLiteButton, buttonsVisibleState,
+ globalSettings, handler)
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 99cb700..18b401f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -19,6 +19,7 @@
import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
import static android.provider.Settings.Global.ZEN_MODE_OFF;
+import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
@@ -41,7 +42,6 @@
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
-import android.view.WindowManager;
import android.widget.Switch;
import android.widget.Toast;
@@ -53,6 +53,7 @@
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SysUIToast;
+import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -84,6 +85,7 @@
private final DndDetailAdapter mDetailAdapter;
private final SharedPreferences mSharedPreferences;
private final SettingObserver mSettingZenDuration;
+ private final DialogLaunchAnimator mDialogLaunchAnimator;
private boolean mListening;
private boolean mShowingDetail;
@@ -100,7 +102,8 @@
QSLogger qsLogger,
ZenModeController zenModeController,
@Main SharedPreferences sharedPreferences,
- SecureSettings secureSettings
+ SecureSettings secureSettings,
+ DialogLaunchAnimator dialogLaunchAnimator
) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
@@ -108,6 +111,7 @@
mSharedPreferences = sharedPreferences;
mDetailAdapter = new DndDetailAdapter();
mController.observe(getLifecycle(), mZenCallback);
+ mDialogLaunchAnimator = dialogLaunchAnimator;
mSettingZenDuration = new SettingObserver(secureSettings, mUiHandler,
Settings.Secure.ZEN_DURATION, getHost().getUserId()) {
@Override
@@ -117,8 +121,6 @@
};
}
-
-
public static void setVisible(Context context, boolean visible) {
Prefs.putBoolean(context, Prefs.Key.DND_TILE_VISIBLE, visible);
}
@@ -187,14 +189,17 @@
switch (zenDuration) {
case Settings.Secure.ZEN_DURATION_PROMPT:
mUiHandler.post(() -> {
- Dialog mDialog = new EnableZenModeDialog(mContext).createDialog();
- mDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- SystemUIDialog.setShowForAllUsers(mDialog, true);
- SystemUIDialog.registerDismissListener(mDialog);
- SystemUIDialog.setWindowOnTop(mDialog);
- mUiHandler.post(() -> mDialog.show());
- mHost.collapsePanels();
+ Dialog dialog = makeZenModeDialog();
+ if (view != null) {
+ final Dialog hostDialog =
+ mDialogLaunchAnimator.showFromView(dialog, view, false);
+ setDialogListeners(dialog, hostDialog);
+ } else {
+ // If we are not launching with animator, register default
+ // dismiss listener
+ SystemUIDialog.registerDismissListener(dialog);
+ dialog.show();
+ }
});
break;
case Settings.Secure.ZEN_DURATION_FOREVER:
@@ -209,6 +214,20 @@
}
}
+ private Dialog makeZenModeDialog() {
+ AlertDialog dialog = new EnableZenModeDialog(mContext, R.style.Theme_SystemUI_Dialog)
+ .createDialog();
+ SystemUIDialog.applyFlags(dialog);
+ SystemUIDialog.setShowForAllUsers(dialog, true);
+ return dialog;
+ }
+
+ private void setDialogListeners(Dialog zenModeDialog, Dialog hostDialog) {
+ // Zen mode dialog is never hidden.
+ SystemUIDialog.registerDismissListener(zenModeDialog, hostDialog::dismiss);
+ zenModeDialog.setOnCancelListener(dialog -> hostDialog.cancel());
+ }
+
@Override
protected void handleSecondaryClick(@Nullable View view) {
if (mController.isVolumeRestricted()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 75b3592..3cecbb7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -533,9 +533,13 @@
* @param animate {@code true} to show animations.
*/
public void recomputeDisableFlags(int displayId, boolean animate) {
- int disabled1 = getDisabled1(displayId);
- int disabled2 = getDisabled2(displayId);
- disable(displayId, disabled1, disabled2, animate);
+ // This must update holding the lock otherwise it can clobber the disabled flags set on the
+ // binder thread from the disable() call
+ synchronized (mLock) {
+ int disabled1 = getDisabled1(displayId);
+ int disabled2 = getDisabled2(displayId);
+ disable(displayId, disabled1, disabled2, animate);
+ }
}
private void setDisabled(int displayId, int disabled1, int disabled2) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 67f51cb..aa3b3e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.hardware.biometrics.BiometricSourceType;
+import android.hardware.fingerprint.FingerprintManager;
import android.metrics.LogMaker;
import android.os.Handler;
import android.os.PowerManager;
@@ -46,9 +47,11 @@
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.FileDescriptor;
@@ -71,6 +74,7 @@
private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl();
+ private static final int FP_ATTEMPTS_BEFORE_SHOW_BOUNCER = 3;
@IntDef(prefix = { "MODE_" }, value = {
MODE_NONE,
@@ -167,6 +171,10 @@
private final MetricsLogger mMetricsLogger;
private final AuthController mAuthController;
+ private final StatusBarStateController mStatusBarStateController;
+
+ private long mLastFpFailureUptimeMillis;
+ private int mNumConsecutiveFpFailures;
private static final class PendingAuthenticated {
public final int userId;
@@ -209,7 +217,10 @@
BIOMETRIC_IRIS_FAILURE(403),
@UiEvent(doc = "A biometric event of type iris errored.")
- BIOMETRIC_IRIS_ERROR(404);
+ BIOMETRIC_IRIS_ERROR(404),
+
+ @UiEvent(doc = "Bouncer was shown as a result of consecutive failed UDFPS attempts.")
+ BIOMETRIC_BOUNCER_SHOWN(916);
private final int mId;
@@ -257,7 +268,8 @@
NotificationMediaManager notificationMediaManager,
WakefulnessLifecycle wakefulnessLifecycle,
ScreenLifecycle screenLifecycle,
- AuthController authController) {
+ AuthController authController,
+ StatusBarStateController statusBarStateController) {
mContext = context;
mPowerManager = powerManager;
mShadeController = shadeController;
@@ -279,6 +291,7 @@
mKeyguardBypassController.setUnlockController(this);
mMetricsLogger = metricsLogger;
mAuthController = authController;
+ mStatusBarStateController = statusBarStateController;
dumpManager.registerDumpable(getClass().getName(), this);
}
@@ -620,6 +633,22 @@
.setType(MetricsEvent.TYPE_FAILURE).setSubtype(toSubtype(biometricSourceType)));
Optional.ofNullable(BiometricUiEvent.FAILURE_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
.ifPresent(UI_EVENT_LOGGER::log);
+
+ long currUptimeMillis = SystemClock.uptimeMillis();
+ if (currUptimeMillis - mLastFpFailureUptimeMillis < 2000) { // attempt within 2 seconds
+ mNumConsecutiveFpFailures += 1;
+ } else {
+ mNumConsecutiveFpFailures = 1;
+ }
+ mLastFpFailureUptimeMillis = currUptimeMillis;
+
+ if (biometricSourceType.equals(BiometricSourceType.FINGERPRINT)
+ && mUpdateMonitor.isUdfpsSupported()
+ && mNumConsecutiveFpFailures >= FP_ATTEMPTS_BEFORE_SHOW_BOUNCER) {
+ mKeyguardViewController.showBouncer(true);
+ UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN);
+ mNumConsecutiveFpFailures = 0;
+ }
cleanup();
}
@@ -631,6 +660,16 @@
.addTaggedData(MetricsEvent.FIELD_BIOMETRIC_AUTH_ERROR, msgId));
Optional.ofNullable(BiometricUiEvent.ERROR_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
.ifPresent(UI_EVENT_LOGGER::log);
+
+ // if we're on the shade and we're locked out, immediately show the bouncer
+ if (biometricSourceType == BiometricSourceType.FINGERPRINT
+ && (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT
+ || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT)
+ && mUpdateMonitor.isUdfpsSupported()
+ && (mStatusBarStateController.getState() == StatusBarState.SHADE
+ || mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED)) {
+ mKeyguardViewController.showBouncer(true);
+ }
cleanup();
}
@@ -664,6 +703,8 @@
mBiometricModeListener.onResetMode();
mBiometricModeListener.notifyBiometricAuthModeChanged();
}
+ mNumConsecutiveFpFailures = 0;
+ mLastFpFailureUptimeMillis = 0;
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 353868b..9647486 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.res.ColorStateList;
+import android.hardware.biometrics.BiometricSourceType;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
@@ -81,6 +82,13 @@
public void onStrongAuthStateChanged(int userId) {
mBouncerPromptReason = mCallback.getBouncerPromptReason();
}
+
+ @Override
+ public void onLockedOutStateChanged(BiometricSourceType type) {
+ if (type == BiometricSourceType.FINGERPRINT) {
+ mBouncerPromptReason = mCallback.getBouncerPromptReason();
+ }
+ }
};
private final Runnable mRemoveViewRunnable = this::removeView;
private final KeyguardBypassController mKeyguardBypassController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
index a77a097..ae3b7ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
@@ -30,11 +30,11 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
-import android.media.AudioAttributes;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.util.Log;
@@ -106,10 +106,8 @@
private final VibrationEffect mCameraLaunchGestureVibrationEffect;
- private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
- .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
- .build();
+ private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
+ VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
@Inject
StatusBarCommandQueueCallbacks(
@@ -611,9 +609,9 @@
}
private void vibrateForCameraGesture() {
- // Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
mVibratorOptional.ifPresent(
- v -> v.vibrate(mCameraLaunchGestureVibrationEffect, VIBRATION_ATTRIBUTES));
+ v -> v.vibrate(mCameraLaunchGestureVibrationEffect,
+ HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES));
}
private static VibrationEffect getCameraGestureVibrationEffect(
@@ -627,6 +625,8 @@
.compose();
}
if (vibratorOptional.isPresent() && vibratorOptional.get().hasAmplitudeControl()) {
+ // Make sure to pass -1 for repeat so VibratorManagerService doesn't stop us when going
+ // to sleep.
return VibrationEffect.createWaveform(
StatusBar.CAMERA_LAUNCH_GESTURE_VIBRATION_TIMINGS,
StatusBar.CAMERA_LAUNCH_GESTURE_VIBRATION_AMPLITUDES,
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 7ab4a1e..0d23d66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -441,6 +441,8 @@
* dragging it and translation should be deferred {@see KeyguardBouncer#show(boolean, boolean)}
*/
public void showBouncer(boolean scrimmed) {
+ resetAlternateAuth(false);
+
if (mShowing && !mBouncer.isShowing()) {
mBouncer.show(false /* resetSecuritySelection */, scrimmed);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 1130ec2..ed52a81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -36,6 +36,8 @@
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
+import androidx.annotation.Nullable;
+
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.animation.DialogListener;
@@ -303,13 +305,32 @@
* the screen off / close system dialogs broadcast.
* <p>
* <strong>Note:</strong> Don't call dialog.setOnDismissListener() after
- * calling this because it causes a leak of BroadcastReceiver.
+ * calling this because it causes a leak of BroadcastReceiver. Instead, call the version that
+ * takes an extra Runnable as a parameter.
*
* @param dialog The dialog to be associated with the listener.
*/
public static void registerDismissListener(Dialog dialog) {
+ registerDismissListener(dialog, null);
+ }
+
+
+ /**
+ * Registers a listener that dismisses the given dialog when it receives
+ * the screen off / close system dialogs broadcast.
+ * <p>
+ * <strong>Note:</strong> Don't call dialog.setOnDismissListener() after
+ * calling this because it causes a leak of BroadcastReceiver.
+ *
+ * @param dialog The dialog to be associated with the listener.
+ * @param dismissAction An action to run when the dialog is dismissed.
+ */
+ public static void registerDismissListener(Dialog dialog, @Nullable Runnable dismissAction) {
DismissReceiver dismissReceiver = new DismissReceiver(dialog);
- dialog.setOnDismissListener(d -> dismissReceiver.unregister());
+ dialog.setOnDismissListener(d -> {
+ dismissReceiver.unregister();
+ if (dismissAction != null) dismissAction.run();
+ });
dismissReceiver.register();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
index 0e86964..1cf21ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
@@ -351,9 +351,8 @@
mSystemClock.advanceTime(205);
mController.onTouchOutsideView();
- // THEN show the bouncer and reset alt auth
+ // THEN show the bouncer
verify(mStatusBarKeyguardViewManager).showBouncer(eq(true));
- verify(mStatusBarKeyguardViewManager).resetAlternateAuth(anyBoolean());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
index d2bba36..26f04fc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
@@ -1,6 +1,8 @@
package com.android.systemui.qs
+import android.os.Handler
import android.os.UserManager
+import android.provider.Settings
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.ViewUtils
@@ -16,10 +18,12 @@
import com.android.systemui.globalactions.GlobalActionsDialogLite
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.qs.FooterActionsController.ExpansionState
+import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.phone.MultiUserSwitchController
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.statusbar.policy.UserInfoController
import com.android.systemui.tuner.TunerService
+import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.utils.leaks.FakeTunerService
import com.android.systemui.utils.leaks.LeakCheckedTest
import com.google.common.truth.Truth.assertThat
@@ -42,6 +46,8 @@
@Mock
private lateinit var userManager: UserManager
@Mock
+ private lateinit var userTracker: UserTracker
+ @Mock
private lateinit var activityStarter: ActivityStarter
@Mock
private lateinit var deviceProvisionedController: DeviceProvisionedController
@@ -62,11 +68,13 @@
private lateinit var view: FooterActionsView
private val falsingManager: FalsingManagerFake = FalsingManagerFake()
private lateinit var testableLooper: TestableLooper
+ private lateinit var fakeSettings: FakeSettings
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
testableLooper = TestableLooper.get(this)
+ fakeSettings = FakeSettings()
injectLeakCheckedDependencies(*LeakCheckedTest.ALL_SUPPORTED_CLASSES)
val fakeTunerService = Dependency.get(TunerService::class.java) as FakeTunerService
@@ -74,10 +82,11 @@
.inflate(R.layout.footer_actions, null) as FooterActionsView
controller = FooterActionsController(view, qsPanelController, activityStarter,
- userManager, userInfoController, multiUserSwitchController,
+ userManager, userTracker, userInfoController, multiUserSwitchController,
deviceProvisionedController, falsingManager, metricsLogger, fakeTunerService,
globalActionsDialog, uiEventLogger, showPMLiteButton = true,
- buttonsVisibleState = ExpansionState.EXPANDED)
+ buttonsVisibleState = ExpansionState.EXPANDED, fakeSettings,
+ Handler(testableLooper.looper))
controller.init()
ViewUtils.attachView(view)
// View looper is the testable looper associated with the test
@@ -122,4 +131,24 @@
assertThat(multiUserSwitch.visibility).isEqualTo(View.VISIBLE)
}
+
+ @Test
+ fun testMultiUserSwitchUpdatedWhenSettingChanged() {
+ // When expanded, listening is true
+ controller.setListening(true)
+ testableLooper.processAllMessages()
+
+ val multiUserSwitch = view.requireViewById<View>(R.id.multi_user_switch)
+ assertThat(multiUserSwitch.visibility).isNotEqualTo(View.VISIBLE)
+
+ // The setting is only used as an indicator for whether the view should refresh. The actual
+ // value of the setting is ignored; isMultiUserEnabled is the source of truth
+ whenever(multiUserSwitchController.isMultiUserEnabled).thenReturn(true)
+
+ // Changing the value of USER_SWITCHER_ENABLED should cause the view to update
+ fakeSettings.putIntForUser(Settings.Global.USER_SWITCHER_ENABLED, 1, userTracker.userId)
+ testableLooper.processAllMessages()
+
+ assertThat(multiUserSwitch.visibility).isEqualTo(View.VISIBLE)
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
index f99703e..3ea2cc5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
@@ -16,22 +16,28 @@
package com.android.systemui.qs.tiles
+import android.app.Dialog
import android.content.ContextWrapper
import android.content.SharedPreferences
import android.os.Handler
import android.provider.Settings
+import android.provider.Settings.Global.ZEN_MODE_OFF
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
+import android.view.View
import androidx.test.filters.SmallTest
import com.android.internal.logging.MetricsLogger
import com.android.internal.logging.UiEventLogger
import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogLaunchAnimator
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.statusbar.policy.ZenModeController
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
import com.android.systemui.util.settings.FakeSettings
import com.android.systemui.util.settings.SecureSettings
import com.google.common.truth.Truth.assertThat
@@ -40,9 +46,12 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
-import org.mockito.Mockito
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import java.io.File
+import org.mockito.Mockito.`when` as whenever
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -70,6 +79,10 @@
private lateinit var zenModeController: ZenModeController
@Mock
private lateinit var sharedPreferences: SharedPreferences
+ @Mock
+ private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
+ @Mock
+ private lateinit var hostDialog: Dialog
private lateinit var secureSettings: SecureSettings
private lateinit var testableLooper: TestableLooper
@@ -81,15 +94,17 @@
testableLooper = TestableLooper.get(this)
secureSettings = FakeSettings()
- Mockito.`when`(qsHost.userId).thenReturn(DEFAULT_USER)
- Mockito.`when`(qsHost.uiEventLogger).thenReturn(uiEventLogger)
+ whenever(qsHost.userId).thenReturn(DEFAULT_USER)
+ whenever(qsHost.uiEventLogger).thenReturn(uiEventLogger)
+ whenever(dialogLaunchAnimator.showFromView(any(), any(), anyBoolean()))
+ .thenReturn(hostDialog)
val wrappedContext = object : ContextWrapper(context) {
override fun getSharedPreferences(file: File?, mode: Int): SharedPreferences {
return sharedPreferences
}
}
- Mockito.`when`(qsHost.context).thenReturn(wrappedContext)
+ whenever(qsHost.context).thenReturn(wrappedContext)
tile = DndTile(
qsHost,
@@ -102,7 +117,8 @@
qsLogger,
zenModeController,
sharedPreferences,
- secureSettings
+ secureSettings,
+ dialogLaunchAnimator
)
}
@@ -147,4 +163,32 @@
assertThat(tile.state.forceExpandIcon).isTrue()
}
+
+ @Test
+ fun testLaunchDialogFromViewWhenPrompt() {
+ whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
+
+ secureSettings.putIntForUser(KEY, Settings.Secure.ZEN_DURATION_PROMPT, DEFAULT_USER)
+ testableLooper.processAllMessages()
+
+ val view = View(context)
+ tile.handleClick(view)
+ testableLooper.processAllMessages()
+
+ verify(dialogLaunchAnimator).showFromView(any(), eq(view), anyBoolean())
+ }
+
+ @Test
+ fun testNoLaunchDialogWhenNotPrompt() {
+ whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
+
+ secureSettings.putIntForUser(KEY, 60, DEFAULT_USER)
+ testableLooper.processAllMessages()
+
+ val view = View(context)
+ tile.handleClick(view)
+ testableLooper.processAllMessages()
+
+ verify(dialogLaunchAnimator, never()).showFromView(any(), any(), anyBoolean())
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index 25fd801..07debe6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -45,6 +45,7 @@
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -101,6 +102,8 @@
private WakefulnessLifecycle mWakefulnessLifecycle;
@Mock
private ScreenLifecycle mScreenLifecycle;
+ @Mock
+ private StatusBarStateController mStatusBarStateController;
private BiometricUnlockController mBiometricUnlockController;
@Before
@@ -123,7 +126,7 @@
mUpdateMonitor, res.getResources(), mKeyguardBypassController, mDozeParameters,
mMetricsLogger, mDumpManager, mPowerManager,
mNotificationMediaManager, mWakefulnessLifecycle, mScreenLifecycle,
- mAuthController);
+ mAuthController, mStatusBarStateController);
mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
mBiometricUnlockController.setBiometricModeListener(mBiometricModeListener);
}
@@ -378,6 +381,23 @@
}
@Test
+ public void onUdfpsConsecutivelyFailedThreeTimes_showBouncer() {
+ // GIVEN UDFPS is supported
+ when(mUpdateMonitor.isUdfpsSupported()).thenReturn(true);
+
+ // WHEN udfps fails twice - then don't show the bouncer
+ mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
+ mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
+ verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
+
+ // WHEN udfps fails the third time
+ mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
+
+ // THEN show the bouncer
+ verify(mStatusBarKeyguardViewManager).showBouncer(true);
+ }
+
+ @Test
public void onFinishedGoingToSleep_authenticatesWhenPending() {
when(mUpdateMonitor.isGoingToSleep()).thenReturn(true);
mBiometricUnlockController.onFinishedGoingToSleep(-1);
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 6f174cb..c5bdfed 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
@@ -374,6 +374,21 @@
}
@Test
+ public void testHideAltAuth_onShowBouncer() {
+ // GIVEN alt auth is showing
+ mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
+ when(mBouncer.isShowing()).thenReturn(false);
+ when(mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()).thenReturn(true);
+ reset(mAlternateAuthInterceptor);
+
+ // WHEN showBouncer is called
+ mStatusBarKeyguardViewManager.showBouncer(true);
+
+ // THEN alt bouncer should be hidden
+ verify(mAlternateAuthInterceptor).hideAlternateAuthBouncer();
+ }
+
+ @Test
public void testUpdateResources_delegatesToBouncer() {
mStatusBarKeyguardViewManager.updateResources();
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 15871aa..1fe4d14 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -12690,38 +12690,30 @@
"Receiver can't specify both RECEIVER_EXPORTED and RECEIVER_NOT_EXPORTED"
+ "flag");
}
-
- // Don't enforce the flag check if we're EITHER registering for only protected
- // broadcasts, or the receiver is null (a sticky broadcast). Sticky broadcasts should
- // not be used generally, so we will be marking them as exported by default
- final boolean requireExplicitFlagForDynamicReceivers = CompatChanges.isChangeEnabled(
- DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED, callingUid);
- if (!onlyProtectedBroadcasts) {
- if (receiver == null && !explicitExportStateDefined) {
- // sticky broadcast, no flag specified (flag isn't required)
- flags |= Context.RECEIVER_EXPORTED;
- } else if (requireExplicitFlagForDynamicReceivers && !explicitExportStateDefined) {
- if (ENFORCE_DYNAMIC_RECEIVER_EXPLICIT_EXPORT) {
- throw new SecurityException(
- callerPackage + ": Targeting T+ (version "
- + Build.VERSION_CODES.TIRAMISU
- + " and above) requires that one of RECEIVER_EXPORTED or "
- + "RECEIVER_NOT_EXPORTED be specified when registering a "
- + "receiver");
- } else {
- Slog.wtf(TAG,
- callerPackage + ": Targeting T+ (version "
- + Build.VERSION_CODES.TIRAMISU
- + " and above) requires that one of RECEIVER_EXPORTED or "
- + "RECEIVER_NOT_EXPORTED be specified when registering a "
- + "receiver");
- // Assume default behavior-- flag check is not enforced
- flags |= Context.RECEIVER_EXPORTED;
- }
- } else if (!requireExplicitFlagForDynamicReceivers) {
- // Change is not enabled, thus not targeting T+. Assume exported.
+ if (CompatChanges.isChangeEnabled(DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED,
+ callingUid)
+ && !explicitExportStateDefined) {
+ if (ENFORCE_DYNAMIC_RECEIVER_EXPLICIT_EXPORT) {
+ throw new SecurityException(
+ callerPackage + ": Targeting T+ (version "
+ + Build.VERSION_CODES.TIRAMISU
+ + " and above) requires that one of RECEIVER_EXPORTED or "
+ + "RECEIVER_NOT_EXPORTED be specified when registering a "
+ + "receiver");
+ } else {
+ Slog.wtf(TAG,
+ callerPackage + ": Targeting T+ (version "
+ + Build.VERSION_CODES.TIRAMISU
+ + " and above) requires that one of RECEIVER_EXPORTED or "
+ + "RECEIVER_NOT_EXPORTED be specified when registering a "
+ + "receiver");
+ // Assume default behavior-- flag check is not enforced
flags |= Context.RECEIVER_EXPORTED;
}
+ } else if (!CompatChanges.isChangeEnabled(DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED,
+ callingUid)) {
+ // Change is not enabled, thus not targeting T+. Assume exported.
+ flags |= Context.RECEIVER_EXPORTED;
}
}
@@ -12739,7 +12731,7 @@
(intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
continue;
}
- // If intent has scheme "content", it will need to access
+ // If intent has scheme "content", it will need to acccess
// provider that needs to lock mProviderMap in ActivityThread
// and also it may need to wait application response, so we
// cannot lock ActivityManagerService here.
diff --git a/services/core/java/com/android/server/locales/LocaleManagerService.java b/services/core/java/com/android/server/locales/LocaleManagerService.java
index ffeaad1..457c2fd 100644
--- a/services/core/java/com/android/server/locales/LocaleManagerService.java
+++ b/services/core/java/com/android/server/locales/LocaleManagerService.java
@@ -154,10 +154,10 @@
final ActivityTaskManagerInternal.PackageConfigurationUpdater updater =
mActivityTaskManagerInternal.createPackageConfigurationUpdater(appPackageName,
userId);
- boolean isSuccess = updater.setLocales(locales).commit();
+ boolean isConfigChanged = updater.setLocales(locales).commit();
//We want to send the broadcasts only if config was actually updated on commit.
- if (isSuccess) {
+ if (isConfigChanged) {
notifyAppWhoseLocaleChanged(appPackageName, userId, locales);
notifyInstallerOfAppWhoseLocaleChanged(appPackageName, userId, locales);
notifyRegisteredReceivers(appPackageName, userId, locales);
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 861fec7..6622a77 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -2050,6 +2050,7 @@
}
}
+ final String packageName = pkg.getPackageName();
for (Map.Entry<String, String> entry : fsverityCandidates.entrySet()) {
final String filePath = entry.getKey();
final String signaturePath = entry.getValue();
@@ -2077,10 +2078,13 @@
try {
// A file may already have fs-verity, e.g. when reused during a split
// install. If the measurement succeeds, no need to attempt to set up.
- mPm.mInstaller.assertFsverityRootHashMatches(filePath, rootHash);
+ mPm.mInstaller.assertFsverityRootHashMatches(packageName, filePath,
+ rootHash);
} catch (Installer.InstallerException e) {
- mPm.mInstaller.installApkVerity(filePath, fd, result.getContentSize());
- mPm.mInstaller.assertFsverityRootHashMatches(filePath, rootHash);
+ mPm.mInstaller.installApkVerity(packageName, filePath, fd,
+ result.getContentSize());
+ mPm.mInstaller.assertFsverityRootHashMatches(packageName, filePath,
+ rootHash);
}
} finally {
IoUtils.closeQuietly(fd);
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index c8bd2c0..a380344 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -497,7 +497,7 @@
*
* @throws InstallerException if {@code dexopt} fails.
*/
- public boolean dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet,
+ public boolean dexopt(String apkPath, int uid, String pkgName, String instructionSet,
int dexoptNeeded, @Nullable String outputPath, int dexFlags,
String compilerFilter, @Nullable String volumeUuid, @Nullable String classLoaderContext,
@Nullable String seInfo, boolean downgrade, int targetSdkVersion,
@@ -585,11 +585,14 @@
}
}
- public void rmPackageDir(String packageDir) throws InstallerException {
+ /**
+ * Remove a directory belonging to a package.
+ */
+ public void rmPackageDir(String packageName, String packageDir) throws InstallerException {
if (!checkBeforeRemote()) return;
BlockGuard.getVmPolicy().onPathAccess(packageDir);
try {
- mInstalld.rmPackageDir(packageDir);
+ mInstalld.rmPackageDir(packageName, packageDir);
} catch (Exception e) {
throw InstallerException.from(e);
}
@@ -662,35 +665,44 @@
}
}
- public void createOatDir(String oatDir, String dexInstructionSet)
+ /**
+ * Creates an oat dir for given package and instruction set.
+ */
+ public void createOatDir(String packageName, String oatDir, String dexInstructionSet)
throws InstallerException {
if (!checkBeforeRemote()) return;
try {
- mInstalld.createOatDir(oatDir, dexInstructionSet);
+ mInstalld.createOatDir(packageName, oatDir, dexInstructionSet);
} catch (Exception e) {
throw InstallerException.from(e);
}
}
- public void linkFile(String relativePath, String fromBase, String toBase)
+ /**
+ * Creates a hardlink for a path.
+ */
+ public void linkFile(String packageName, String relativePath, String fromBase, String toBase)
throws InstallerException {
if (!checkBeforeRemote()) return;
BlockGuard.getVmPolicy().onPathAccess(fromBase);
BlockGuard.getVmPolicy().onPathAccess(toBase);
try {
- mInstalld.linkFile(relativePath, fromBase, toBase);
+ mInstalld.linkFile(packageName, relativePath, fromBase, toBase);
} catch (Exception e) {
throw InstallerException.from(e);
}
}
- public void moveAb(String apkPath, String instructionSet, String outputPath)
+ /**
+ * Moves oat/vdex/art from "B" set defined by ro.boot.slot_suffix to the default set.
+ */
+ public void moveAb(String packageName, String apkPath, String instructionSet, String outputPath)
throws InstallerException {
if (!checkBeforeRemote()) return;
BlockGuard.getVmPolicy().onPathAccess(apkPath);
BlockGuard.getVmPolicy().onPathAccess(outputPath);
try {
- mInstalld.moveAb(apkPath, instructionSet, outputPath);
+ mInstalld.moveAb(packageName, apkPath, instructionSet, outputPath);
} catch (Exception e) {
throw InstallerException.from(e);
}
@@ -700,35 +712,41 @@
* Deletes the optimized artifacts generated by ART and returns the number
* of freed bytes.
*/
- public long deleteOdex(String apkPath, String instructionSet, String outputPath)
- throws InstallerException {
+ public long deleteOdex(String packageName, String apkPath, String instructionSet,
+ String outputPath) throws InstallerException {
if (!checkBeforeRemote()) return -1;
BlockGuard.getVmPolicy().onPathAccess(apkPath);
BlockGuard.getVmPolicy().onPathAccess(outputPath);
try {
- return mInstalld.deleteOdex(apkPath, instructionSet, outputPath);
+ return mInstalld.deleteOdex(packageName, apkPath, instructionSet, outputPath);
} catch (Exception e) {
throw InstallerException.from(e);
}
}
- public void installApkVerity(String filePath, FileDescriptor verityInput, int contentSize)
- throws InstallerException {
+ /**
+ * Enables legacy apk-verity for an apk.
+ */
+ public void installApkVerity(String packageName, String filePath, FileDescriptor verityInput,
+ int contentSize) throws InstallerException {
if (!checkBeforeRemote()) return;
BlockGuard.getVmPolicy().onPathAccess(filePath);
try {
- mInstalld.installApkVerity(filePath, verityInput, contentSize);
+ mInstalld.installApkVerity(packageName, filePath, verityInput, contentSize);
} catch (Exception e) {
throw InstallerException.from(e);
}
}
- public void assertFsverityRootHashMatches(String filePath, @NonNull byte[] expectedHash)
- throws InstallerException {
+ /**
+ * Checks if provided hash matches the file's fs-verity merkle tree root hash.
+ */
+ public void assertFsverityRootHashMatches(String packageName, String filePath,
+ @NonNull byte[] expectedHash) throws InstallerException {
if (!checkBeforeRemote()) return;
BlockGuard.getVmPolicy().onPathAccess(filePath);
try {
- mInstalld.assertFsverityRootHashMatches(filePath, expectedHash);
+ mInstalld.assertFsverityRootHashMatches(packageName, filePath, expectedHash);
} catch (Exception e) {
throw InstallerException.from(e);
}
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 9e6f4f7..c125fe1 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -411,6 +411,7 @@
final List<String> paths =
AndroidPackageUtils.getAllCodePathsExcludingResourceOnly(pkg);
final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
+ final String packageName = pkg.getPackageName();
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
for (String path : paths) {
String oatDir = PackageDexOptimizer.getOatDir(
@@ -420,7 +421,7 @@
packagePaths++;
try {
- installer.moveAb(path, dexCodeInstructionSet, oatDir);
+ installer.moveAb(packageName, path, dexCodeInstructionSet, oatDir);
pathsSuccessful++;
} catch (InstallerException e) {
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 803a283..8f14cf8 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -2402,6 +2402,7 @@
try {
final List<File> fromFiles = mResolvedInheritedFiles;
final File toDir = stageDir;
+ final String tempPackageName = toDir.getName();
if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
@@ -2411,7 +2412,7 @@
if (isLinkPossible(fromFiles, toDir)) {
if (!mResolvedInstructionSets.isEmpty()) {
final File oatDir = new File(toDir, "oat");
- createOatDirs(mResolvedInstructionSets, oatDir);
+ createOatDirs(tempPackageName, mResolvedInstructionSets, oatDir);
}
// pre-create lib dirs for linking if necessary
if (!mResolvedNativeLibPaths.isEmpty()) {
@@ -2434,7 +2435,7 @@
new File(libDir, archDirPath));
}
}
- linkFiles(fromFiles, toDir, mInheritedFilesBase);
+ linkFiles(tempPackageName, fromFiles, toDir, mInheritedFilesBase);
} else {
// TODO: this should delegate to DCS so the system process
// avoids holding open FDs into containers.
@@ -3529,18 +3530,19 @@
throw new IOException("File: " + pathStr + " outside base: " + baseStr);
}
- private void createOatDirs(List<String> instructionSets, File fromDir)
+ private void createOatDirs(String packageName, List<String> instructionSets, File fromDir)
throws PackageManagerException {
for (String instructionSet : instructionSets) {
try {
- mInstaller.createOatDir(fromDir.getAbsolutePath(), instructionSet);
+ mInstaller.createOatDir(packageName, fromDir.getAbsolutePath(), instructionSet);
} catch (InstallerException e) {
throw PackageManagerException.from(e);
}
}
}
- private void linkFile(String relativePath, String fromBase, String toBase) throws IOException {
+ private void linkFile(String packageName, String relativePath, String fromBase, String toBase)
+ throws IOException {
try {
// Try
final IncrementalFileStorages incrementalFileStorages = getIncrementalFileStorages();
@@ -3548,21 +3550,21 @@
fromBase, toBase)) {
return;
}
- mInstaller.linkFile(relativePath, fromBase, toBase);
+ mInstaller.linkFile(packageName, relativePath, fromBase, toBase);
} catch (InstallerException | IOException e) {
throw new IOException("failed linkOrCreateDir(" + relativePath + ", "
+ fromBase + ", " + toBase + ")", e);
}
}
- private void linkFiles(List<File> fromFiles, File toDir, File fromDir)
+ private void linkFiles(String packageName, List<File> fromFiles, File toDir, File fromDir)
throws IOException {
for (File fromFile : fromFiles) {
final String relativePath = getRelativePath(fromFile, fromDir);
final String fromBase = fromDir.getAbsolutePath();
final String toBase = toDir.getAbsolutePath();
- linkFile(relativePath, fromBase, toBase);
+ linkFile(packageName, relativePath, fromBase, toBase);
}
Slog.d(TAG, "Linked " + fromFiles.size() + " files into " + toDir);
@@ -4299,7 +4301,8 @@
incrementalFileStorages.cleanUpAndMarkComplete();
}
if (stageDir != null) {
- mInstaller.rmPackageDir(stageDir.getAbsolutePath());
+ final String tempPackageName = stageDir.getName();
+ mInstaller.rmPackageDir(tempPackageName, stageDir.getAbsolutePath());
}
} catch (InstallerException ignored) {
}
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index 3a2ac1c..48b893b 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -94,9 +94,10 @@
}
}
- mInstaller.rmPackageDir(codePath.getAbsolutePath());
+ final String packageName = codePath.getName();
+ mInstaller.rmPackageDir(packageName, codePath.getAbsolutePath());
if (needRemoveParent) {
- mInstaller.rmPackageDir(codePathParent.getAbsolutePath());
+ mInstaller.rmPackageDir(packageName, codePathParent.getAbsolutePath());
removeCachedResult(codePathParent);
}
} catch (Installer.InstallerException e) {
diff --git a/services/core/java/com/android/server/pm/ScanPackageHelper.java b/services/core/java/com/android/server/pm/ScanPackageHelper.java
index 6cc94ce..9b08ef9 100644
--- a/services/core/java/com/android/server/pm/ScanPackageHelper.java
+++ b/services/core/java/com/android/server/pm/ScanPackageHelper.java
@@ -894,14 +894,15 @@
* Returns if forced apk verification can be skipped for the whole package, including splits.
*/
private boolean canSkipForcedPackageVerification(AndroidPackage pkg) {
- if (!canSkipForcedApkVerification(pkg.getBaseApkPath())) {
+ final String packageName = pkg.getPackageName();
+ if (!canSkipForcedApkVerification(packageName, pkg.getBaseApkPath())) {
return false;
}
// TODO: Allow base and splits to be verified individually.
String[] splitCodePaths = pkg.getSplitCodePaths();
if (!ArrayUtils.isEmpty(splitCodePaths)) {
for (int i = 0; i < splitCodePaths.length; i++) {
- if (!canSkipForcedApkVerification(splitCodePaths[i])) {
+ if (!canSkipForcedApkVerification(packageName, splitCodePaths[i])) {
return false;
}
}
@@ -914,7 +915,7 @@
* whether the apk contains signed root hash. Note that the signer's certificate still needs to
* match one in a trusted source, and should be done separately.
*/
- private boolean canSkipForcedApkVerification(String apkPath) {
+ private boolean canSkipForcedApkVerification(String packageName, String apkPath) {
if (!PackageManagerServiceUtils.isLegacyApkVerityEnabled()) {
return VerityUtils.hasFsverity(apkPath);
}
@@ -926,7 +927,8 @@
}
synchronized (mPm.mInstallLock) {
// Returns whether the observed root hash matches what kernel has.
- mPm.mInstaller.assertFsverityRootHashMatches(apkPath, rootHashObserved);
+ mPm.mInstaller.assertFsverityRootHashMatches(packageName, apkPath,
+ rootHashObserved);
return true;
}
} catch (Installer.InstallerException | IOException | DigestException
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 302826f..40d8845 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -20,6 +20,8 @@
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import android.Manifest;
+import android.accounts.Account;
+import android.accounts.AccountManager;
import android.annotation.ColorRes;
import android.annotation.DrawableRes;
import android.annotation.NonNull;
@@ -85,6 +87,7 @@
import android.security.GateKeeper;
import android.service.gatekeeper.IGateKeeperService;
import android.stats.devicepolicy.DevicePolicyEnums;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
@@ -3512,6 +3515,39 @@
}
}
+ @Override
+ public UserHandle createUserWithAttributes(
+ String userName, String userType, @UserInfoFlag int flags,
+ Bitmap userIcon,
+ String accountName, String accountType, PersistableBundle accountOptions) {
+ checkManageOrCreateUsersPermission(flags);
+
+ if (someUserHasAccountNoChecks(accountName, accountType)) {
+ throw new ServiceSpecificException(
+ UserManager.USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS);
+ }
+
+ UserInfo userInfo;
+ try {
+ userInfo = createUserInternal(userName, userType, flags,
+ UserHandle.USER_NULL, null);
+
+ if (userInfo == null) {
+ throw new ServiceSpecificException(UserManager.USER_OPERATION_ERROR_UNKNOWN);
+ }
+ } catch (UserManager.CheckedUserOperationException e) {
+ throw e.toServiceSpecificException();
+ }
+
+ if (userIcon != null) {
+ mLocalService.setUserIcon(userInfo.id, userIcon);
+ }
+
+ setSeedAccountDataNoChecks(userInfo.id, accountName, accountType, accountOptions, true);
+
+ return userInfo.getUserHandle();
+ }
+
private UserInfo createUserInternal(@Nullable String name, @NonNull String userType,
@UserInfoFlag int flags, @UserIdInt int parentId,
@Nullable String[] disallowedPackages)
@@ -4934,7 +4970,12 @@
@Override
public void setSeedAccountData(@UserIdInt int userId, String accountName, String accountType,
PersistableBundle accountOptions, boolean persist) {
- checkManageUsersPermission("Require MANAGE_USERS permission to set user seed data");
+ checkManageUsersPermission("set user seed account data");
+ setSeedAccountDataNoChecks(userId, accountName, accountType, accountOptions, persist);
+ }
+
+ private void setSeedAccountDataNoChecks(@UserIdInt int userId, String accountName,
+ String accountType, PersistableBundle accountOptions, boolean persist) {
synchronized (mPackagesLock) {
final UserData userData;
synchronized (mUsersLock) {
@@ -4996,14 +5037,18 @@
}
@Override
- public boolean someUserHasSeedAccount(String accountName, String accountType)
- throws RemoteException {
- checkManageUsersPermission("Cannot check seed account information");
+ public boolean someUserHasSeedAccount(String accountName, String accountType) {
+ checkManageUsersPermission("check seed account information");
+ return someUserHasSeedAccountNoChecks(accountName, accountType);
+ }
+
+ private boolean someUserHasSeedAccountNoChecks(String accountName, String accountType) {
synchronized (mUsersLock) {
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
final UserData data = mUsers.valueAt(i);
if (data.info.isInitialized()) continue;
+ if (mRemovingUserIds.get(data.info.id)) continue;
if (data.seedAccountName == null || !data.seedAccountName.equals(accountName)) {
continue;
}
@@ -5017,6 +5062,25 @@
}
@Override
+ public boolean someUserHasAccount(String accountName, String accountType) {
+ checkManageOrCreateUsersPermission("check seed account information");
+ return someUserHasAccountNoChecks(accountName, accountType);
+ }
+
+ private boolean someUserHasAccountNoChecks(
+ String accountName, String accountType) {
+ if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
+ return false;
+ }
+
+ final Account account = new Account(accountName, accountType);
+
+ return Binder.withCleanCallingIdentity(() ->
+ AccountManager.get(mContext).someUserHasAccount(account)
+ || someUserHasSeedAccountNoChecks(accountName, accountType));
+ }
+
+ @Override
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 5820489..5371454 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -1043,10 +1043,12 @@
public long deleteOptimizedFiles(ArtPackageInfo packageInfo) {
long freedBytes = 0;
boolean hadErrors = false;
+ final String packageName = packageInfo.getPackageName();
for (String codePath : packageInfo.getCodePaths()) {
for (String isa : packageInfo.getInstructionSets()) {
try {
- freedBytes += mInstaller.deleteOdex(codePath, isa, packageInfo.getOatDir());
+ freedBytes += mInstaller.deleteOdex(packageName, codePath, isa,
+ packageInfo.getOatDir());
} catch (InstallerException e) {
Log.e(TAG, "Failed deleting oat files for " + codePath, e);
hadErrors = true;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 2369c5e..131e587 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -332,6 +332,10 @@
private static final int POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS = 800;
private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES =
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH);
+ private static final VibrationAttributes PHYSICAL_EMULATION_VIBRATION_ATTRIBUTES =
+ VibrationAttributes.createForUsage(VibrationAttributes.USAGE_PHYSICAL_EMULATION);
+ private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
+ VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
/**
* Keyguard stuff
@@ -1115,21 +1119,21 @@
break;
case LONG_PRESS_POWER_GLOBAL_ACTIONS:
mPowerKeyHandled = true;
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
"Power - Long Press - Global Actions");
showGlobalActions();
break;
case LONG_PRESS_POWER_SHUT_OFF:
case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
mPowerKeyHandled = true;
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
"Power - Long Press - Shut Off");
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
break;
case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST:
mPowerKeyHandled = true;
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
"Power - Long Press - Go To Voice Assist");
// Some devices allow the voice assistant intent during setup (and use that intent
// to launch something else, like Settings). So we explicitly allow that via the
@@ -1153,7 +1157,7 @@
break;
case VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS:
mPowerKeyHandled = true;
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
"Power - Very Long Press - Show Global Actions");
showGlobalActions();
break;
@@ -2098,7 +2102,8 @@
mPowerKeyHandled = true;
break;
case POWER_VOLUME_UP_BEHAVIOR_GLOBAL_ACTIONS:
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
+ performHapticFeedback(
+ HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
"Power + Volume Up - Global Actions");
showGlobalActions();
mPowerKeyHandled = true;
@@ -5291,7 +5296,7 @@
return false;
}
- mVibrator.vibrate(uid, packageName, effect, reason, TOUCH_VIBRATION_ATTRIBUTES);
+ mVibrator.vibrate(uid, packageName, effect, reason, getVibrationAttributes(effectId));
return true;
}
@@ -5320,6 +5325,7 @@
case HapticFeedbackConstants.GESTURE_START:
return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
case HapticFeedbackConstants.LONG_PRESS:
+ case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON:
case HapticFeedbackConstants.EDGE_SQUEEZE:
return VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
case HapticFeedbackConstants.REJECT:
@@ -5358,6 +5364,22 @@
}
}
+ private VibrationAttributes getVibrationAttributes(int effectId) {
+ switch (effectId) {
+ case HapticFeedbackConstants.EDGE_SQUEEZE:
+ case HapticFeedbackConstants.EDGE_RELEASE:
+ return PHYSICAL_EMULATION_VIBRATION_ATTRIBUTES;
+ case HapticFeedbackConstants.ASSISTANT_BUTTON:
+ case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON:
+ case HapticFeedbackConstants.ROTARY_SCROLL_TICK:
+ case HapticFeedbackConstants.ROTARY_SCROLL_ITEM_FOCUS:
+ case HapticFeedbackConstants.ROTARY_SCROLL_LIMIT:
+ return HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES;
+ default:
+ return TOUCH_VIBRATION_ATTRIBUTES;
+ }
+ }
+
@Override
public void keepScreenOnStartedLw() {
}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 6d0f08d..70a804b 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -110,8 +110,8 @@
private static final VibrationEffect CHARGING_VIBRATION_EFFECT =
VibrationEffect.createWaveform(CHARGING_VIBRATION_TIME, CHARGING_VIBRATION_AMPLITUDE,
-1);
- private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES =
- VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH);
+ private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
+ VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
private final Object mLock = new Object();
@@ -807,7 +807,7 @@
final boolean vibrate = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0;
if (vibrate) {
- mVibrator.vibrate(CHARGING_VIBRATION_EFFECT, TOUCH_VIBRATION_ATTRIBUTES);
+ mVibrator.vibrate(CHARGING_VIBRATION_EFFECT, HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
}
// play sound
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index bc21f1b..71a6b22 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -16,6 +16,14 @@
package com.android.server.vibrator;
+import static android.os.VibrationAttributes.USAGE_ALARM;
+import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
+import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK;
+import static android.os.VibrationAttributes.USAGE_NOTIFICATION;
+import static android.os.VibrationAttributes.USAGE_PHYSICAL_EMULATION;
+import static android.os.VibrationAttributes.USAGE_RINGTONE;
+import static android.os.VibrationAttributes.USAGE_TOUCH;
+
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.IUidObserver;
@@ -90,6 +98,8 @@
@GuardedBy("mLock")
private int mHapticFeedbackIntensity;
@GuardedBy("mLock")
+ private int mHardwareFeedbackIntensity;
+ @GuardedBy("mLock")
private int mNotificationIntensity;
@GuardedBy("mLock")
private int mRingIntensity;
@@ -232,17 +242,20 @@
* @return The vibration intensity, one of Vibrator.VIBRATION_INTENSITY_*
*/
public int getDefaultIntensity(int usageHint) {
- if (isAlarm(usageHint)) {
+ if (usageHint == USAGE_ALARM) {
return Vibrator.VIBRATION_INTENSITY_HIGH;
}
synchronized (mLock) {
if (mVibrator != null) {
- if (isRingtone(usageHint)) {
- return mVibrator.getDefaultRingVibrationIntensity();
- } else if (isNotification(usageHint)) {
- return mVibrator.getDefaultNotificationVibrationIntensity();
- } else if (isHapticFeedback(usageHint)) {
- return mVibrator.getDefaultHapticFeedbackIntensity();
+ switch (usageHint) {
+ case USAGE_RINGTONE:
+ return mVibrator.getDefaultRingVibrationIntensity();
+ case USAGE_NOTIFICATION:
+ return mVibrator.getDefaultNotificationVibrationIntensity();
+ case USAGE_TOUCH:
+ case USAGE_HARDWARE_FEEDBACK:
+ case USAGE_PHYSICAL_EMULATION:
+ return mVibrator.getDefaultHapticFeedbackIntensity();
}
}
}
@@ -257,16 +270,20 @@
*/
public int getCurrentIntensity(int usageHint) {
synchronized (mLock) {
- if (isRingtone(usageHint)) {
- return mRingIntensity;
- } else if (isNotification(usageHint)) {
- return mNotificationIntensity;
- } else if (isHapticFeedback(usageHint)) {
- return mHapticFeedbackIntensity;
- } else if (isAlarm(usageHint)) {
- return Vibrator.VIBRATION_INTENSITY_HIGH;
- } else {
- return Vibrator.VIBRATION_INTENSITY_MEDIUM;
+ switch (usageHint) {
+ case USAGE_RINGTONE:
+ return mRingIntensity;
+ case USAGE_NOTIFICATION:
+ return mNotificationIntensity;
+ case USAGE_TOUCH:
+ return mHapticFeedbackIntensity;
+ case USAGE_HARDWARE_FEEDBACK:
+ case USAGE_PHYSICAL_EMULATION:
+ return mHardwareFeedbackIntensity;
+ case USAGE_ALARM:
+ return Vibrator.VIBRATION_INTENSITY_HIGH;
+ default:
+ return Vibrator.VIBRATION_INTENSITY_MEDIUM;
}
}
}
@@ -289,7 +306,7 @@
* for ringtone usage only. All other usages are allowed independently of ringer mode.
*/
public boolean shouldVibrateForRingerMode(int usageHint) {
- if (!isRingtone(usageHint)) {
+ if (usageHint != USAGE_RINGTONE) {
return true;
}
synchronized (mLock) {
@@ -324,8 +341,10 @@
* {@link VibrationAttributes#USAGE_COMMUNICATION_REQUEST} usages are allowed to vibrate.
*/
public boolean shouldVibrateForPowerMode(int usageHint) {
- return !mLowPowerMode || isRingtone(usageHint) || isAlarm(usageHint)
- || usageHint == VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
+ synchronized (mLock) {
+ return !mLowPowerMode || usageHint == USAGE_RINGTONE || usageHint == USAGE_ALARM
+ || usageHint == USAGE_COMMUNICATION_REQUEST;
+ }
}
/** Return {@code true} if input devices should vibrate instead of this device. */
@@ -338,22 +357,6 @@
return mZenMode != Settings.Global.ZEN_MODE_OFF;
}
- private static boolean isNotification(int usageHint) {
- return usageHint == VibrationAttributes.USAGE_NOTIFICATION;
- }
-
- private static boolean isRingtone(int usageHint) {
- return usageHint == VibrationAttributes.USAGE_RINGTONE;
- }
-
- private static boolean isHapticFeedback(int usageHint) {
- return usageHint == VibrationAttributes.USAGE_TOUCH;
- }
-
- private static boolean isAlarm(int usageHint) {
- return usageHint == VibrationAttributes.USAGE_ALARM;
- }
-
private static boolean isClassAlarm(int usageHint) {
return (usageHint & VibrationAttributes.USAGE_CLASS_MASK)
== VibrationAttributes.USAGE_CLASS_ALARM;
@@ -365,18 +368,35 @@
mVibrateWhenRinging = getSystemSetting(Settings.System.VIBRATE_WHEN_RINGING, 0) != 0;
mApplyRampingRinger = getGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0) != 0;
mHapticFeedbackIntensity = getSystemSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- getDefaultIntensity(VibrationAttributes.USAGE_TOUCH));
+ getDefaultIntensity(USAGE_TOUCH));
+ mHardwareFeedbackIntensity = getSystemSetting(
+ Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY,
+ getHardwareFeedbackIntensityWhenSettingIsMissing(mHapticFeedbackIntensity));
mNotificationIntensity = getSystemSetting(
Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- getDefaultIntensity(VibrationAttributes.USAGE_NOTIFICATION));
+ getDefaultIntensity(USAGE_NOTIFICATION));
mRingIntensity = getSystemSetting(Settings.System.RING_VIBRATION_INTENSITY,
- getDefaultIntensity(VibrationAttributes.USAGE_RINGTONE));
+ getDefaultIntensity(USAGE_RINGTONE));
mVibrateInputDevices = getSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0;
mZenMode = getGlobalSetting(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
}
notifyListeners();
}
+ /**
+ * Return the value to be used for {@link Settings.System#HARDWARE_HAPTIC_FEEDBACK_INTENSITY}
+ * when the value was not set by the user.
+ *
+ * <p>This should adapt the behavior preceding the introduction of this new setting key, which
+ * is to apply {@link Settings.System#HAPTIC_FEEDBACK_INTENSITY} unless it's disabled.
+ */
+ private int getHardwareFeedbackIntensityWhenSettingIsMissing(int hapticFeedbackIntensity) {
+ if (hapticFeedbackIntensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+ return getDefaultIntensity(USAGE_HARDWARE_FEEDBACK);
+ }
+ return hapticFeedbackIntensity;
+ }
+
@Override
public String toString() {
return "VibrationSettings{"
@@ -389,18 +409,20 @@
+ ", mHapticChannelMaxVibrationAmplitude=" + getHapticChannelMaxVibrationAmplitude()
+ ", mRampStepDuration=" + mRampStepDuration
+ ", mRampDownDuration=" + mRampDownDuration
+ + ", mHardwareHapticFeedbackIntensity="
+ + intensityToString(getCurrentIntensity(USAGE_HARDWARE_FEEDBACK))
+ ", mHapticFeedbackIntensity="
- + intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_TOUCH))
+ + intensityToString(getCurrentIntensity(USAGE_TOUCH))
+ ", mHapticFeedbackDefaultIntensity="
- + intensityToString(getDefaultIntensity(VibrationAttributes.USAGE_TOUCH))
+ + intensityToString(getDefaultIntensity(USAGE_TOUCH))
+ ", mNotificationIntensity="
- + intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_NOTIFICATION))
+ + intensityToString(getCurrentIntensity(USAGE_NOTIFICATION))
+ ", mNotificationDefaultIntensity="
- + intensityToString(getDefaultIntensity(VibrationAttributes.USAGE_NOTIFICATION))
+ + intensityToString(getDefaultIntensity(USAGE_NOTIFICATION))
+ ", mRingIntensity="
- + intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_RINGTONE))
+ + intensityToString(getCurrentIntensity(USAGE_RINGTONE))
+ ", mRingDefaultIntensity="
- + intensityToString(getDefaultIntensity(VibrationAttributes.USAGE_RINGTONE))
+ + intensityToString(getDefaultIntensity(USAGE_RINGTONE))
+ '}';
}
@@ -410,15 +432,15 @@
proto.write(VibratorManagerServiceDumpProto.HAPTIC_FEEDBACK_INTENSITY,
mHapticFeedbackIntensity);
proto.write(VibratorManagerServiceDumpProto.HAPTIC_FEEDBACK_DEFAULT_INTENSITY,
- getDefaultIntensity(VibrationAttributes.USAGE_TOUCH));
+ getDefaultIntensity(USAGE_TOUCH));
proto.write(VibratorManagerServiceDumpProto.NOTIFICATION_INTENSITY,
mNotificationIntensity);
proto.write(VibratorManagerServiceDumpProto.NOTIFICATION_DEFAULT_INTENSITY,
- getDefaultIntensity(VibrationAttributes.USAGE_NOTIFICATION));
+ getDefaultIntensity(USAGE_NOTIFICATION));
proto.write(VibratorManagerServiceDumpProto.RING_INTENSITY,
mRingIntensity);
proto.write(VibratorManagerServiceDumpProto.RING_DEFAULT_INTENSITY,
- getDefaultIntensity(VibrationAttributes.USAGE_RINGTONE));
+ getDefaultIntensity(USAGE_RINGTONE));
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index ea22d92..2a1bb0b 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -6224,15 +6224,15 @@
public boolean inputDispatchingTimedOut(String reason, int windowPid) {
ActivityRecord anrActivity;
WindowProcessController anrApp;
- boolean windowFromSameProcessAsActivity;
+ boolean blameActivityProcess;
synchronized (mAtmService.mGlobalLock) {
anrActivity = getWaitingHistoryRecordLocked();
anrApp = app;
- windowFromSameProcessAsActivity =
- !hasProcess() || app.getPid() == windowPid || windowPid == INVALID_PID;
+ blameActivityProcess = hasProcess()
+ && (app.getPid() == windowPid || windowPid == INVALID_PID);
}
- if (windowFromSameProcessAsActivity) {
+ if (blameActivityProcess) {
return mAtmService.mAmInternal.inputDispatchingTimedOut(anrApp.mOwner,
anrActivity.shortComponentName, anrActivity.info.applicationInfo,
shortComponentName, app, false, reason);
diff --git a/services/core/java/com/android/server/wm/PackageConfigPersister.java b/services/core/java/com/android/server/wm/PackageConfigPersister.java
index 3de98f1..7a7fb65 100644
--- a/services/core/java/com/android/server/wm/PackageConfigPersister.java
+++ b/services/core/java/com/android/server/wm/PackageConfigPersister.java
@@ -169,21 +169,35 @@
}
}
+ /**
+ * Returns true when the app specific configuration is successfully stored or removed based on
+ * the current requested configuration. It will return false when the requested
+ * configuration is same as the pre-existing app-specific configuration.
+ */
@GuardedBy("mLock")
boolean updateFromImpl(String packageName, int userId,
PackageConfigurationUpdaterImpl impl) {
synchronized (mLock) {
- PackageConfigRecord record = findRecordOrCreate(mModified, packageName, userId);
- if (impl.getNightMode() != null) {
- record.mNightMode = impl.getNightMode();
+ boolean isRecordPresent = false;
+ PackageConfigRecord record = findRecord(mModified, packageName, userId);
+ if (record != null) {
+ isRecordPresent = true;
+ } else {
+ record = findRecordOrCreate(mModified, packageName, userId);
}
- if (impl.getLocales() != null) {
- record.mLocales = impl.getLocales();
- }
+ boolean isNightModeChanged = updateNightMode(impl.getNightMode(), record);
+ boolean isLocalesChanged = updateLocales(impl.getLocales(), record);
+
if ((record.mNightMode == null || record.isResetNightMode())
&& (record.mLocales == null || record.mLocales.isEmpty())) {
// if all values default to system settings, we can remove the package.
removePackage(packageName, userId);
+ // if there was a pre-existing record for the package that was deleted,
+ // we return true (since it was successfully deleted), else false (since there was
+ // no change to the previous state).
+ return isRecordPresent;
+ } else if (!isNightModeChanged && !isLocalesChanged) {
+ return false;
} else {
final PackageConfigRecord pendingRecord =
findRecord(mPendingWrite, record.mName, record.mUserId);
@@ -195,7 +209,8 @@
writeRecord = pendingRecord;
}
- if (!updateNightMode(record, writeRecord) && !updateLocales(record, writeRecord)) {
+ if (!updateNightMode(record.mNightMode, writeRecord)
+ && !updateLocales(record.mLocales, writeRecord)) {
return false;
}
@@ -203,24 +218,24 @@
Slog.d(TAG, "PackageConfigUpdater save config " + writeRecord);
}
mPersisterQueue.addItem(new WriteProcessItem(writeRecord), false /* flush */);
+ return true;
}
- return true;
}
}
- private boolean updateNightMode(PackageConfigRecord record, PackageConfigRecord writeRecord) {
- if (record.mNightMode == null || record.mNightMode.equals(writeRecord.mNightMode)) {
+ private boolean updateNightMode(Integer requestedNightMode, PackageConfigRecord record) {
+ if (requestedNightMode == null || requestedNightMode.equals(record.mNightMode)) {
return false;
}
- writeRecord.mNightMode = record.mNightMode;
+ record.mNightMode = requestedNightMode;
return true;
}
- private boolean updateLocales(PackageConfigRecord record, PackageConfigRecord writeRecord) {
- if (record.mLocales == null || record.mLocales.equals(writeRecord.mLocales)) {
+ private boolean updateLocales(LocaleList requestedLocaleList, PackageConfigRecord record) {
+ if (requestedLocaleList == null || requestedLocaleList.equals(record.mLocales)) {
return false;
}
- writeRecord.mLocales = record.mLocales;
+ record.mLocales = requestedLocaleList;
return true;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 727f265..3839a9f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -8460,7 +8460,9 @@
@Override
public boolean hasDeviceOwner() {
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller)
+ || canManageUsers(caller)
+ || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
return mOwners.hasDeviceOwner();
}
@@ -8640,7 +8642,8 @@
if (!mHasFeature) {
return null;
}
- Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
+ || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
synchronized (getLockObject()) {
if (!mOwners.hasDeviceOwner()) {
@@ -8986,7 +8989,8 @@
return DevicePolicyManager.STATE_USER_UNMANAGED;
}
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(canManageUsers(caller));
+ Preconditions.checkCallAuthorization(canManageUsers(caller)
+ || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
return getUserProvisioningState(caller.getUserId());
}
@@ -9240,7 +9244,8 @@
if (!mHasFeature) {
return null;
}
- Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
+ || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
return getProfileOwnerNameUnchecked(userHandle);
}
@@ -16466,7 +16471,8 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
+ || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
long id = mInjector.binderClearCallingIdentity();
try {
@@ -16492,7 +16498,8 @@
if (!mHasFeature) {
return false;
}
- Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
+ || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
return mInjector.binderWithCleanCallingIdentity(() -> isUnattendedManagedKioskUnchecked());
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 9119133..2f9e334 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -373,6 +373,8 @@
"com.android.server.blob.BlobStoreManagerService";
private static final String APP_SEARCH_MANAGER_SERVICE_CLASS =
"com.android.server.appsearch.AppSearchManagerService";
+ private static final String ISOLATED_COMPILATION_SERVICE_CLASS =
+ "com.android.server.compos.IsolatedCompilationService";
private static final String ROLLBACK_MANAGER_SERVICE_CLASS =
"com.android.server.rollback.RollbackManagerService";
private static final String ALARM_MANAGER_SERVICE_CLASS =
@@ -2718,6 +2720,12 @@
mSystemServiceManager.startService(APP_SEARCH_MANAGER_SERVICE_CLASS);
t.traceEnd();
+ if (SystemProperties.getBoolean("ro.config.isolated_compilation_enabled", false)) {
+ t.traceBegin("IsolatedCompilationService");
+ mSystemServiceManager.startService(ISOLATED_COMPILATION_SERVICE_CLASS);
+ t.traceEnd();
+ }
+
t.traceBegin("StartMediaCommunicationService");
mSystemServiceManager.startService(MEDIA_COMMUNICATION_SERVICE_CLASS);
t.traceEnd();
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
index 7d24a2f..a9cbad2 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -16,6 +16,19 @@
package com.android.server.vibrator;
+import static android.os.VibrationAttributes.USAGE_ALARM;
+import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
+import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK;
+import static android.os.VibrationAttributes.USAGE_NOTIFICATION;
+import static android.os.VibrationAttributes.USAGE_PHYSICAL_EMULATION;
+import static android.os.VibrationAttributes.USAGE_RINGTONE;
+import static android.os.VibrationAttributes.USAGE_TOUCH;
+import static android.os.VibrationAttributes.USAGE_UNKNOWN;
+import static android.os.Vibrator.VIBRATION_INTENSITY_HIGH;
+import static android.os.Vibrator.VIBRATION_INTENSITY_LOW;
+import static android.os.Vibrator.VIBRATION_INTENSITY_MEDIUM;
+import static android.os.Vibrator.VIBRATION_INTENSITY_OFF;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -39,9 +52,7 @@
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.UserHandle;
-import android.os.VibrationAttributes;
import android.os.VibrationEffect;
-import android.os.Vibrator;
import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
@@ -70,16 +81,19 @@
public class VibrationSettingsTest {
private static final int UID = 1;
- private static final int USER_OPERATION_TIMEOUT_MILLIS = 60_000; // 1 min
private static final PowerSaveState NORMAL_POWER_STATE = new PowerSaveState.Builder().build();
private static final PowerSaveState LOW_POWER_STATE = new PowerSaveState.Builder()
.setBatterySaverEnabled(true).build();
- @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
- @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
+ @Rule
+ public MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Rule
+ public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
- @Mock private VibrationSettings.OnVibratorSettingsChanged mListenerMock;
- @Mock private PowerManagerInternal mPowerManagerInternalMock;
+ @Mock
+ private VibrationSettings.OnVibratorSettingsChanged mListenerMock;
+ @Mock
+ private PowerManagerInternal mPowerManagerInternalMock;
private TestLooper mTestLooper;
private ContextWrapper mContextSpy;
@@ -129,14 +143,12 @@
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0);
setGlobalSetting(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_ALARMS);
- setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_OFF);
- setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_OFF);
- setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
- verify(mListenerMock, times(7)).onChange();
+ verify(mListenerMock, times(8)).onChange();
}
@Test
@@ -171,89 +183,83 @@
VibrationSettings vibrationSettings = new VibrationSettings(mContextSpy,
new Handler(mTestLooper.getLooper()));
- assertFalse(vibrationSettings.shouldVibrateForRingerMode(
- VibrationAttributes.USAGE_RINGTONE));
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_ALARM));
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_TOUCH));
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(
- VibrationAttributes.USAGE_NOTIFICATION));
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(
- VibrationAttributes.USAGE_COMMUNICATION_REQUEST));
+ assertFalse(vibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_ALARM));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_TOUCH));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_NOTIFICATION));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_COMMUNICATION_REQUEST));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_HARDWARE_FEEDBACK));
}
@Test
public void shouldVibrateForRingerMode_withoutRingtoneUsage_returnsTrue() {
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_ALARM));
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_TOUCH));
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(
- VibrationAttributes.USAGE_NOTIFICATION));
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(
- VibrationAttributes.USAGE_COMMUNICATION_REQUEST));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_ALARM));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_TOUCH));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_NOTIFICATION));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_COMMUNICATION_REQUEST));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_HARDWARE_FEEDBACK));
}
@Test
public void shouldVibrateForRingerMode_withVibrateWhenRinging_ignoreSettingsForSilentMode() {
- int usageRingtone = VibrationAttributes.USAGE_RINGTONE;
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
setRingerMode(AudioManager.RINGER_MODE_SILENT);
- assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+ assertFalse(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
setRingerMode(AudioManager.RINGER_MODE_MAX);
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
setRingerMode(AudioManager.RINGER_MODE_NORMAL);
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
}
@Test
public void shouldVibrateForRingerMode_withApplyRampingRinger_ignoreSettingsForSilentMode() {
- int usageRingtone = VibrationAttributes.USAGE_RINGTONE;
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 1);
setRingerMode(AudioManager.RINGER_MODE_SILENT);
- assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+ assertFalse(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
setRingerMode(AudioManager.RINGER_MODE_MAX);
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
setRingerMode(AudioManager.RINGER_MODE_NORMAL);
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
}
@Test
public void shouldVibrateForRingerMode_withAllSettingsOff_onlyVibratesForVibrateMode() {
- int usageRingtone = VibrationAttributes.USAGE_RINGTONE;
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0);
setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
- assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+ assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
setRingerMode(AudioManager.RINGER_MODE_SILENT);
- assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+ assertFalse(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
setRingerMode(AudioManager.RINGER_MODE_MAX);
- assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+ assertFalse(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
setRingerMode(AudioManager.RINGER_MODE_NORMAL);
- assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+ assertFalse(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
}
@Test
public void shouldVibrateForUid_withForegroundOnlyUsage_returnsTrueWhInForeground() {
- assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_TOUCH));
+ assertTrue(mVibrationSettings.shouldVibrateForUid(UID, USAGE_TOUCH));
mVibrationSettings.mUidObserver.onUidStateChanged(
UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
- assertFalse(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_TOUCH));
+ assertFalse(mVibrationSettings.shouldVibrateForUid(UID, USAGE_TOUCH));
}
@Test
@@ -261,38 +267,32 @@
mVibrationSettings.mUidObserver.onUidStateChanged(
UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
- assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_ALARM));
- assertTrue(mVibrationSettings.shouldVibrateForUid(UID,
- VibrationAttributes.USAGE_COMMUNICATION_REQUEST));
- assertTrue(mVibrationSettings.shouldVibrateForUid(UID,
- VibrationAttributes.USAGE_NOTIFICATION));
- assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_RINGTONE));
+ assertTrue(mVibrationSettings.shouldVibrateForUid(UID, USAGE_ALARM));
+ assertTrue(mVibrationSettings.shouldVibrateForUid(UID, USAGE_COMMUNICATION_REQUEST));
+ assertTrue(mVibrationSettings.shouldVibrateForUid(UID, USAGE_NOTIFICATION));
+ assertTrue(mVibrationSettings.shouldVibrateForUid(UID, USAGE_RINGTONE));
}
@Test
public void shouldVibrateForPowerMode_withLowPowerAndAllowedUsage_returnTrue() {
mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
- assertTrue(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_ALARM));
- assertTrue(mVibrationSettings.shouldVibrateForPowerMode(
- VibrationAttributes.USAGE_RINGTONE));
- assertTrue(mVibrationSettings.shouldVibrateForPowerMode(
- VibrationAttributes.USAGE_COMMUNICATION_REQUEST));
+ assertTrue(mVibrationSettings.shouldVibrateForPowerMode(USAGE_ALARM));
+ assertTrue(mVibrationSettings.shouldVibrateForPowerMode(USAGE_RINGTONE));
+ assertTrue(mVibrationSettings.shouldVibrateForPowerMode(USAGE_COMMUNICATION_REQUEST));
}
@Test
public void shouldVibrateForPowerMode_withRestrictedUsage_returnsFalseWhileInLowPowerMode() {
mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
- assertTrue(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_TOUCH));
- assertTrue(mVibrationSettings.shouldVibrateForPowerMode(
- VibrationAttributes.USAGE_NOTIFICATION));
+ assertTrue(mVibrationSettings.shouldVibrateForPowerMode(USAGE_TOUCH));
+ assertTrue(mVibrationSettings.shouldVibrateForPowerMode(USAGE_NOTIFICATION));
mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
- assertFalse(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_TOUCH));
- assertFalse(mVibrationSettings.shouldVibrateForPowerMode(
- VibrationAttributes.USAGE_NOTIFICATION));
+ assertFalse(mVibrationSettings.shouldVibrateForPowerMode(USAGE_TOUCH));
+ assertFalse(mVibrationSettings.shouldVibrateForPowerMode(USAGE_NOTIFICATION));
}
@Test
@@ -324,108 +324,128 @@
@Test
public void getDefaultIntensity_beforeSystemReady_returnsMediumToAllExceptAlarm() {
- mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
- mFakeVibrator.setDefaultNotificationVibrationIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
- mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
+ mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_HIGH);
+ mFakeVibrator.setDefaultNotificationVibrationIntensity(VIBRATION_INTENSITY_HIGH);
+ mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_HIGH);
- setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_OFF);
- setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_OFF);
- setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
VibrationSettings vibrationSettings = new VibrationSettings(mContextSpy,
new Handler(mTestLooper.getLooper()));
- assertEquals(Vibrator.VIBRATION_INTENSITY_HIGH,
- vibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_ALARM));
- assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
- vibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_TOUCH));
- assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
- vibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_NOTIFICATION));
- assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
- vibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_UNKNOWN));
- assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
- vibrationSettings.getDefaultIntensity(
- VibrationAttributes.USAGE_PHYSICAL_EMULATION));
- assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
- vibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_RINGTONE));
+ assertEquals(VIBRATION_INTENSITY_HIGH,
+ vibrationSettings.getDefaultIntensity(USAGE_ALARM));
+ assertEquals(VIBRATION_INTENSITY_MEDIUM,
+ vibrationSettings.getDefaultIntensity(USAGE_TOUCH));
+ assertEquals(VIBRATION_INTENSITY_MEDIUM,
+ vibrationSettings.getDefaultIntensity(USAGE_HARDWARE_FEEDBACK));
+ assertEquals(VIBRATION_INTENSITY_MEDIUM,
+ vibrationSettings.getDefaultIntensity(USAGE_PHYSICAL_EMULATION));
+ assertEquals(VIBRATION_INTENSITY_MEDIUM,
+ vibrationSettings.getDefaultIntensity(USAGE_NOTIFICATION));
+ assertEquals(VIBRATION_INTENSITY_MEDIUM,
+ vibrationSettings.getDefaultIntensity(USAGE_UNKNOWN));
+ assertEquals(VIBRATION_INTENSITY_MEDIUM,
+ vibrationSettings.getDefaultIntensity(USAGE_RINGTONE));
}
@Test
public void getDefaultIntensity_returnsIntensityFromVibratorService() {
- mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
- mFakeVibrator.setDefaultNotificationVibrationIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM);
- mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_LOW);
+ mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_HIGH);
+ mFakeVibrator.setDefaultNotificationVibrationIntensity(VIBRATION_INTENSITY_MEDIUM);
+ mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_LOW);
- setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_OFF);
- setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_OFF);
- setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
- assertEquals(Vibrator.VIBRATION_INTENSITY_HIGH,
- mVibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_ALARM));
- assertEquals(Vibrator.VIBRATION_INTENSITY_HIGH,
- mVibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_TOUCH));
- assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
- mVibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_NOTIFICATION));
- assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
- mVibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_UNKNOWN));
- assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
- mVibrationSettings.getDefaultIntensity(
- VibrationAttributes.USAGE_PHYSICAL_EMULATION));
- assertEquals(Vibrator.VIBRATION_INTENSITY_LOW,
- mVibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_RINGTONE));
+ assertEquals(VIBRATION_INTENSITY_HIGH,
+ mVibrationSettings.getDefaultIntensity(USAGE_ALARM));
+ assertEquals(VIBRATION_INTENSITY_HIGH,
+ mVibrationSettings.getDefaultIntensity(USAGE_TOUCH));
+ assertEquals(VIBRATION_INTENSITY_HIGH,
+ mVibrationSettings.getDefaultIntensity(USAGE_HARDWARE_FEEDBACK));
+ assertEquals(VIBRATION_INTENSITY_HIGH,
+ mVibrationSettings.getDefaultIntensity(USAGE_PHYSICAL_EMULATION));
+ assertEquals(VIBRATION_INTENSITY_MEDIUM,
+ mVibrationSettings.getDefaultIntensity(USAGE_NOTIFICATION));
+ assertEquals(VIBRATION_INTENSITY_MEDIUM,
+ mVibrationSettings.getDefaultIntensity(USAGE_UNKNOWN));
+ assertEquals(VIBRATION_INTENSITY_LOW,
+ mVibrationSettings.getDefaultIntensity(USAGE_RINGTONE));
}
@Test
public void getCurrentIntensity_returnsIntensityFromSettings() {
- mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_OFF);
- mFakeVibrator.setDefaultNotificationVibrationIntensity(Vibrator.VIBRATION_INTENSITY_OFF);
- mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_OFF);
+ mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_OFF);
+ mFakeVibrator.setDefaultNotificationVibrationIntensity(VIBRATION_INTENSITY_OFF);
+ mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_OFF);
- setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_HIGH);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH);
+ setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_LOW);
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_MEDIUM);
- setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_LOW);
+ VIBRATION_INTENSITY_MEDIUM);
+ setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
- assertEquals(Vibrator.VIBRATION_INTENSITY_HIGH,
- mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_ALARM));
- assertEquals(Vibrator.VIBRATION_INTENSITY_HIGH,
- mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_TOUCH));
- assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
- mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_NOTIFICATION));
- assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
- mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_UNKNOWN));
- assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
- mVibrationSettings.getCurrentIntensity(
- VibrationAttributes.USAGE_PHYSICAL_EMULATION));
- assertEquals(Vibrator.VIBRATION_INTENSITY_LOW,
- mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_RINGTONE));
+ assertEquals(VIBRATION_INTENSITY_HIGH, mVibrationSettings.getCurrentIntensity(USAGE_ALARM));
+ assertEquals(VIBRATION_INTENSITY_HIGH, mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
+ assertEquals(VIBRATION_INTENSITY_LOW,
+ mVibrationSettings.getCurrentIntensity(USAGE_HARDWARE_FEEDBACK));
+ assertEquals(VIBRATION_INTENSITY_LOW,
+ mVibrationSettings.getCurrentIntensity(USAGE_PHYSICAL_EMULATION));
+ assertEquals(VIBRATION_INTENSITY_MEDIUM,
+ mVibrationSettings.getCurrentIntensity(USAGE_NOTIFICATION));
+ assertEquals(VIBRATION_INTENSITY_MEDIUM,
+ mVibrationSettings.getCurrentIntensity(USAGE_UNKNOWN));
+ assertEquals(VIBRATION_INTENSITY_LOW,
+ mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
}
@Test
public void getCurrentIntensity_updateTriggeredAfterUserSwitched() {
- mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_OFF);
- setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_HIGH);
- assertEquals(Vibrator.VIBRATION_INTENSITY_HIGH,
- mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_RINGTONE));
+ mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
+ assertEquals(VIBRATION_INTENSITY_HIGH,
+ mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
// Switching user is not working with FakeSettingsProvider.
// Testing the broadcast flow manually.
Settings.System.putIntForUser(mContextSpy.getContentResolver(),
- Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW,
+ Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW,
UserHandle.USER_CURRENT);
mVibrationSettings.mUserReceiver.onReceive(mContextSpy,
new Intent(Intent.ACTION_USER_SWITCHED));
- assertEquals(Vibrator.VIBRATION_INTENSITY_LOW,
- mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_RINGTONE));
+ assertEquals(VIBRATION_INTENSITY_LOW,
+ mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
+ }
+
+ @Test
+ public void getCurrentIntensity_noHardwareFeedbackValueUsesHapticFeedbackValue() {
+ mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_MEDIUM);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
+ assertEquals(VIBRATION_INTENSITY_OFF, mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
+ // If haptic feedback is off, fallback to default value.
+ assertEquals(VIBRATION_INTENSITY_MEDIUM,
+ mVibrationSettings.getCurrentIntensity(USAGE_HARDWARE_FEEDBACK));
+ assertEquals(VIBRATION_INTENSITY_MEDIUM,
+ mVibrationSettings.getCurrentIntensity(USAGE_PHYSICAL_EMULATION));
+
+ // Switching user is not working with FakeSettingsProvider.
+ // Testing the broadcast flow manually.
+ Settings.System.putIntForUser(mContextSpy.getContentResolver(),
+ Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH,
+ UserHandle.USER_CURRENT);
+ mVibrationSettings.mUserReceiver.onReceive(mContextSpy,
+ new Intent(Intent.ACTION_USER_SWITCHED));
+ assertEquals(VIBRATION_INTENSITY_HIGH,
+ mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
+ assertEquals(VIBRATION_INTENSITY_HIGH,
+ mVibrationSettings.getCurrentIntensity(USAGE_HARDWARE_FEEDBACK));
+ assertEquals(VIBRATION_INTENSITY_HIGH,
+ mVibrationSettings.getCurrentIntensity(USAGE_PHYSICAL_EMULATION));
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 1266b2e..afc2b87 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -854,12 +854,19 @@
ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
mAtm.mInternal.createPackageConfigurationUpdater(DEFAULT_PACKAGE_NAME,
DEFAULT_USER_ID);
+
+ // committing empty locales, when no config is set should return false.
+ assertFalse(packageConfigUpdater.setLocales(LocaleList.getEmptyLocaleList()).commit());
+
// committing new configuration returns true;
assertTrue(packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
.commit());
// applying the same configuration returns false.
assertFalse(packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
.commit());
+
+ // committing empty locales and undefined nightMode should return true (deletes the
+ // pre-existing record) if some config was previously set.
assertTrue(packageConfigUpdater.setLocales(LocaleList.getEmptyLocaleList())
.setNightMode(Configuration.UI_MODE_NIGHT_UNDEFINED).commit());
}
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 23cf511..e88106c 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -1,6 +1,8 @@
package android.telephony;
import android.annotation.IntDef;
+import android.net.NetworkAgent;
+import android.net.NetworkCapabilities;
import android.telecom.Connection;
import android.telephony.data.ApnSetting;
@@ -664,4 +666,59 @@
TelephonyManager.THERMAL_MITIGATION_RESULT_INVALID_STATE,
TelephonyManager.THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR})
public @interface ThermalMitigationResult {}
+
+ /**
+ * Per Android API guideline 8.15, annotation can't be public APIs. So duplicate
+ * android.net.NetworkCapabilities.NetCapability here. Must update here when new capabilities
+ * are added in {@link NetworkCapabilities}.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "NET_CAPABILITY_" }, value = {
+ NetworkCapabilities.NET_CAPABILITY_MMS,
+ NetworkCapabilities.NET_CAPABILITY_SUPL,
+ NetworkCapabilities.NET_CAPABILITY_DUN,
+ NetworkCapabilities.NET_CAPABILITY_FOTA,
+ NetworkCapabilities.NET_CAPABILITY_IMS,
+ NetworkCapabilities.NET_CAPABILITY_CBS,
+ NetworkCapabilities.NET_CAPABILITY_WIFI_P2P,
+ NetworkCapabilities.NET_CAPABILITY_IA,
+ NetworkCapabilities.NET_CAPABILITY_RCS,
+ NetworkCapabilities.NET_CAPABILITY_XCAP,
+ NetworkCapabilities.NET_CAPABILITY_EIMS,
+ NetworkCapabilities.NET_CAPABILITY_NOT_METERED,
+ NetworkCapabilities.NET_CAPABILITY_INTERNET,
+ NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED,
+ NetworkCapabilities.NET_CAPABILITY_TRUSTED,
+ NetworkCapabilities.NET_CAPABILITY_NOT_VPN,
+ NetworkCapabilities.NET_CAPABILITY_VALIDATED,
+ NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL,
+ NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING,
+ NetworkCapabilities.NET_CAPABILITY_FOREGROUND,
+ NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED,
+ NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED,
+ NetworkCapabilities.NET_CAPABILITY_OEM_PAID,
+ NetworkCapabilities.NET_CAPABILITY_MCX,
+ NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY,
+ NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED,
+ NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE,
+ NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL,
+ NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED,
+ NetworkCapabilities.NET_CAPABILITY_ENTERPRISE,
+ NetworkCapabilities.NET_CAPABILITY_VSIM,
+ NetworkCapabilities.NET_CAPABILITY_BIP,
+ NetworkCapabilities.NET_CAPABILITY_HEAD_UNIT,
+ })
+ public @interface NetCapability { }
+
+ /**
+ * Per Android API guideline 8.15, annotation can't be public APIs. So duplicate
+ * android.net.NetworkAgent.ValidationStatus here. Must update here when new validation status
+ * are added in {@link NetworkAgent}.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "VALIDATION_STATUS_" }, value = {
+ NetworkAgent.VALIDATION_STATUS_VALID,
+ NetworkAgent.VALIDATION_STATUS_NOT_VALID
+ })
+ public @interface ValidationStatus {}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 3f0f50c..c7e5aaf 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -5951,9 +5951,9 @@
"capabilities=eims, retry_interval=1000, maximum_retries=20",
"fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|-3|2253|"
+ "2254, maximum_retries=0", // No retry for those causes
+ "capabilities=mms|supl|cbs, retry_interval=2000",
"capabilities=internet|enterprise|dun|ims|fota, retry_interval=2000, "
+ "backoff=true, maximum_retries=13",
- "capabilities=mms|supl|cbs, retry_interval=2000"
});
sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]);
sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false);
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 88efe1f..56bf303 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1076,6 +1076,13 @@
*/
public static final int SERVICE_TEMPORARILY_UNAVAILABLE = 0x10009;
+ /**
+ * The request is not supported by the vendor.
+ *
+ * @hide
+ */
+ public static final int REQUEST_NOT_SUPPORTED = 0x1000A;
+
private static final Map<Integer, String> sFailCauseMap;
static {
sFailCauseMap = new HashMap<>();
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index 93903d2..43ad982 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -22,9 +22,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.net.NetworkCapabilities;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.ApnType;
+import android.telephony.Annotation.NetCapability;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.NetworkTypeBitMask;
import android.telephony.data.ApnSetting.AuthType;
@@ -66,7 +68,7 @@
private final @Nullable TrafficDescriptor mTrafficDescriptor;
- private final boolean mPreferred;
+ private boolean mPreferred;
private DataProfile(@NonNull Builder builder) {
mApnSetting = builder.mApnSetting;
@@ -291,6 +293,16 @@
}
/**
+ * Set the preferred flag for the data profile.
+ *
+ * @param preferred {@code true} if this data profile is preferred for internet.
+ * @hide
+ */
+ public void setPreferred(boolean preferred) {
+ mPreferred = preferred;
+ }
+
+ /**
* @return {@code true} if this data profile was used to bring up the last default
* (i.e internet) data connection successfully, or the one chosen by the user in Settings'
* APN editor. For one carrier there can be only one profiled preferred.
@@ -315,6 +327,76 @@
return mTrafficDescriptor;
}
+ /**
+ * Check if this data profile can satisfy certain network capabilities
+ *
+ * @param networkCapabilities The network capabilities. Note that the non-APN-type capabilities
+ * will be ignored.
+ *
+ * @return {@code true} if this data profile can satisfy the given network capabilities.
+ * @hide
+ */
+ public boolean canSatisfy(@NonNull @NetCapability int[] networkCapabilities) {
+ if (mApnSetting != null) {
+ for (int netCap : networkCapabilities) {
+ if (!canSatisfy(netCap)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check if this data profile can satisfy a certain network capability.
+ *
+ * @param networkCapability The network capability. Note that the non-APN-type capability
+ * will always be satisfied.
+ * @return {@code true} if this data profile can satisfy the given network capability.
+ * @hide
+ */
+ public boolean canSatisfy(@NetCapability int networkCapability) {
+ return mApnSetting != null && mApnSetting.canHandleType(
+ networkCapabilityToApnType(networkCapability));
+ }
+
+ /**
+ * Convert network capability into APN type.
+ *
+ * @param networkCapability Network capability.
+ * @return APN type.
+ * @hide
+ */
+ private static @ApnType int networkCapabilityToApnType(@NetCapability int networkCapability) {
+ switch (networkCapability) {
+ case NetworkCapabilities.NET_CAPABILITY_MMS:
+ return ApnSetting.TYPE_MMS;
+ case NetworkCapabilities.NET_CAPABILITY_SUPL:
+ return ApnSetting.TYPE_SUPL;
+ case NetworkCapabilities.NET_CAPABILITY_DUN:
+ return ApnSetting.TYPE_DUN;
+ case NetworkCapabilities.NET_CAPABILITY_FOTA:
+ return ApnSetting.TYPE_FOTA;
+ case NetworkCapabilities.NET_CAPABILITY_IMS:
+ return ApnSetting.TYPE_IMS;
+ case NetworkCapabilities.NET_CAPABILITY_CBS:
+ return ApnSetting.TYPE_CBS;
+ case NetworkCapabilities.NET_CAPABILITY_XCAP:
+ return ApnSetting.TYPE_XCAP;
+ case NetworkCapabilities.NET_CAPABILITY_EIMS:
+ return ApnSetting.TYPE_EMERGENCY;
+ case NetworkCapabilities.NET_CAPABILITY_INTERNET:
+ return ApnSetting.TYPE_DEFAULT;
+ case NetworkCapabilities.NET_CAPABILITY_MCX:
+ return ApnSetting.TYPE_MCX;
+ case NetworkCapabilities.NET_CAPABILITY_IA:
+ return ApnSetting.TYPE_IA;
+ default:
+ return ApnSetting.TYPE_NONE;
+ }
+ }
+
@Override
public int describeContents() {
return 0;