summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-10-13 07:57:20 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-10-13 07:57:20 +0000
commit4b66c386f91a49c7a8bf5cbf085c342729acb95d (patch)
tree0198c013a8f053e4db3ba75035e7ee465a13f80b
parented2d1dac87d01a2f65821a8b10ebd3112b458ecb (diff)
parent676cefb0eee79e9246199e93b46f9ee1a786924c (diff)
downloadbase-android10-mainline-tzdata-release.tar.gz
Snap for 9170954 from 676cefb0eee79e9246199e93b46f9ee1a786924c to qt-aml-tzdata-releaseq_tzdata_aml_295500002q_tzdata_aml_295500001android10-mainline-tzdata-release
Change-Id: I76cb97b83888824bcc235eb51e36093535a42716
-rw-r--r--core/java/android/accounts/Account.java7
-rw-r--r--core/java/android/app/AutomaticZenRule.java79
-rw-r--r--core/java/android/app/INotificationManager.aidl2
-rw-r--r--core/java/android/app/NotificationChannel.java19
-rw-r--r--core/java/android/app/NotificationChannelGroup.java20
-rw-r--r--core/java/android/app/NotificationManager.java8
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java30
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl3
-rw-r--r--core/java/android/appwidget/AppWidgetManager.java4
-rw-r--r--core/java/android/content/AbstractThreadedSyncAdapter.java20
-rw-r--r--core/java/android/content/pm/IPackageInstallerSession.aidl1
-rw-r--r--core/java/android/content/pm/PackageInstaller.java12
-rw-r--r--core/java/android/content/pm/PackageManagerInternal.java6
-rw-r--r--core/java/android/content/pm/PackageParser.java52
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java9
-rw-r--r--core/java/android/os/Parcel.java1
-rw-r--r--core/java/android/os/UserManagerInternal.java8
-rw-r--r--core/java/android/service/gatekeeper/GateKeeperResponse.java2
-rw-r--r--core/java/android/service/notification/Condition.java38
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java15
-rw-r--r--core/java/android/service/voice/AlwaysOnHotwordDetector.java40
-rw-r--r--core/java/android/service/voice/VoiceInteractionService.java2
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java2
-rw-r--r--core/java/com/android/internal/app/HarmfulAppWarningActivity.java4
-rw-r--r--core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java10
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl2
-rw-r--r--core/res/AndroidManifest.xml1
-rw-r--r--core/tests/coretests/src/android/app/AutomaticZenRuleTest.java153
-rw-r--r--core/tests/coretests/src/android/app/NotificationChannelGroupTest.java89
-rw-r--r--core/tests/coretests/src/android/app/NotificationChannelTest.java102
-rw-r--r--core/tests/coretests/src/android/service/notification/ConditionTest.java101
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java13
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java6
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java6
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java32
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java9
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java104
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java38
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java3
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java7
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java13
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java7
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java15
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java52
-rw-r--r--services/core/java/com/android/server/connectivity/PacManager.java19
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java75
-rw-r--r--services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java2
-rwxr-xr-x[-rw-r--r--]services/core/java/com/android/server/notification/NotificationManagerService.java54
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java3
-rw-r--r--services/core/java/com/android/server/notification/SnoozeHelper.java9
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java58
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java11
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java33
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java14
-rw-r--r--services/core/java/com/android/server/pm/UserDataPreparer.java11
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java83
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java36
-rw-r--r--services/core/java/com/android/server/slice/SliceManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java22
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java11
-rw-r--r--services/core/java/com/android/server/wm/TaskRecord.java51
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotPersister.java34
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java7
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java33
-rw-r--r--services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java19
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java7
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java15
-rwxr-xr-x[-rw-r--r--]services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java167
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java13
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java18
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java55
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java114
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java24
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java14
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java19
-rw-r--r--telecomm/java/com/android/internal/telecom/ITelecomService.aidl13
88 files changed, 2028 insertions, 246 deletions
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index 15b70b405823..c822d20445ec 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -30,7 +30,6 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
-import java.util.Objects;
import java.util.Set;
/**
@@ -86,12 +85,6 @@ public class Account implements Parcelable {
if (TextUtils.isEmpty(type)) {
throw new IllegalArgumentException("the type must not be empty: " + type);
}
- if (name.length() > 200) {
- throw new IllegalArgumentException("account name is longer than 200 characters");
- }
- if (type.length() > 200) {
- throw new IllegalArgumentException("account type is longer than 200 characters");
- }
this.name = name;
this.type = type;
this.accessId = accessId;
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index 7180c01143a5..37b336382769 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -45,6 +45,14 @@ public final class AutomaticZenRule implements Parcelable {
private long creationTime;
private ZenPolicy mZenPolicy;
private boolean mModified = false;
+ private String mPkg;
+
+ /**
+ * The maximum string length for any string contained in this automatic zen rule. This pertains
+ * both to fields in the rule itself (such as its name) and items with sub-fields.
+ * @hide
+ */
+ public static final int MAX_STRING_LENGTH = 1000;
/**
* Creates an automatic zen rule.
@@ -92,10 +100,10 @@ public final class AutomaticZenRule implements Parcelable {
public AutomaticZenRule(@NonNull String name, @Nullable ComponentName owner,
@Nullable ComponentName configurationActivity, @NonNull Uri conditionId,
@Nullable ZenPolicy policy, int interruptionFilter, boolean enabled) {
- this.name = name;
- this.owner = owner;
- this.configurationActivity = configurationActivity;
- this.conditionId = conditionId;
+ this.name = getTrimmedString(name);
+ this.owner = getTrimmedComponentName(owner);
+ this.configurationActivity = getTrimmedComponentName(configurationActivity);
+ this.conditionId = getTrimmedUri(conditionId);
this.interruptionFilter = interruptionFilter;
this.enabled = enabled;
this.mZenPolicy = policy;
@@ -114,15 +122,16 @@ public final class AutomaticZenRule implements Parcelable {
public AutomaticZenRule(Parcel source) {
enabled = source.readInt() == ENABLED;
if (source.readInt() == ENABLED) {
- name = source.readString();
+ name = getTrimmedString(source.readString());
}
interruptionFilter = source.readInt();
conditionId = source.readParcelable(null);
- owner = source.readParcelable(null);
- configurationActivity = source.readParcelable(null);
+ owner = getTrimmedComponentName(source.readParcelable(null));
+ configurationActivity = getTrimmedComponentName(source.readParcelable(null));
creationTime = source.readLong();
mZenPolicy = source.readParcelable(null);
mModified = source.readInt() == ENABLED;
+ mPkg = source.readString();
}
/**
@@ -194,7 +203,7 @@ public final class AutomaticZenRule implements Parcelable {
* Sets the representation of the state that causes this rule to become active.
*/
public void setConditionId(Uri conditionId) {
- this.conditionId = conditionId;
+ this.conditionId = getTrimmedUri(conditionId);
}
/**
@@ -209,7 +218,7 @@ public final class AutomaticZenRule implements Parcelable {
* Sets the name of this rule.
*/
public void setName(String name) {
- this.name = name;
+ this.name = getTrimmedString(name);
}
/**
@@ -241,7 +250,21 @@ public final class AutomaticZenRule implements Parcelable {
* that are not backed by {@link android.service.notification.ConditionProviderService}.
*/
public void setConfigurationActivity(@Nullable ComponentName componentName) {
- this.configurationActivity = componentName;
+ this.configurationActivity = getTrimmedComponentName(componentName);
+ }
+
+ /**
+ * @hide
+ */
+ public void setPackageName(String pkgName) {
+ mPkg = pkgName;
+ }
+
+ /**
+ * @hide
+ */
+ public String getPackageName() {
+ return mPkg;
}
@Override
@@ -265,6 +288,7 @@ public final class AutomaticZenRule implements Parcelable {
dest.writeLong(creationTime);
dest.writeParcelable(mZenPolicy, 0);
dest.writeInt(mModified ? ENABLED : DISABLED);
+ dest.writeString(mPkg);
}
@Override
@@ -273,6 +297,7 @@ public final class AutomaticZenRule implements Parcelable {
.append("enabled=").append(enabled)
.append(",name=").append(name)
.append(",interruptionFilter=").append(interruptionFilter)
+ .append(",pkg=").append(mPkg)
.append(",conditionId=").append(conditionId)
.append(",owner=").append(owner)
.append(",configActivity=").append(configurationActivity)
@@ -294,13 +319,14 @@ public final class AutomaticZenRule implements Parcelable {
&& Objects.equals(other.owner, owner)
&& Objects.equals(other.mZenPolicy, mZenPolicy)
&& Objects.equals(other.configurationActivity, configurationActivity)
+ && Objects.equals(other.mPkg, mPkg)
&& other.creationTime == creationTime;
}
@Override
public int hashCode() {
return Objects.hash(enabled, name, interruptionFilter, conditionId, owner,
- configurationActivity, mZenPolicy, mModified, creationTime);
+ configurationActivity, mZenPolicy, mModified, creationTime, mPkg);
}
public static final @android.annotation.NonNull Parcelable.Creator<AutomaticZenRule> CREATOR
@@ -314,4 +340,35 @@ public final class AutomaticZenRule implements Parcelable {
return new AutomaticZenRule[size];
}
};
+
+ /**
+ * If the package or class name of the provided ComponentName are longer than MAX_STRING_LENGTH,
+ * return a trimmed version that truncates each of the package and class name at the max length.
+ */
+ private static ComponentName getTrimmedComponentName(ComponentName cn) {
+ if (cn == null) return null;
+ return new ComponentName(getTrimmedString(cn.getPackageName()),
+ getTrimmedString(cn.getClassName()));
+ }
+
+ /**
+ * Returns a truncated copy of the string if the string is longer than MAX_STRING_LENGTH.
+ */
+ private static String getTrimmedString(String input) {
+ if (input != null && input.length() > MAX_STRING_LENGTH) {
+ return input.substring(0, MAX_STRING_LENGTH);
+ }
+ return input;
+ }
+
+ /**
+ * Returns a truncated copy of the Uri by trimming the string representation to the maximum
+ * string length.
+ */
+ private static Uri getTrimmedUri(Uri input) {
+ if (input != null && input.toString().length() > MAX_STRING_LENGTH) {
+ return Uri.parse(getTrimmedString(input.toString()));
+ }
+ return input;
+ }
}
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 32668980d131..bcd578ad0130 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -184,7 +184,7 @@ interface INotificationManager
void setNotificationPolicyAccessGrantedForUser(String pkg, int userId, boolean granted);
AutomaticZenRule getAutomaticZenRule(String id);
List<ZenModeConfig.ZenRule> getZenRules();
- String addAutomaticZenRule(in AutomaticZenRule automaticZenRule);
+ String addAutomaticZenRule(in AutomaticZenRule automaticZenRule, String pkg);
boolean updateAutomaticZenRule(String id, in AutomaticZenRule automaticZenRule);
boolean removeAutomaticZenRule(String id);
boolean removeAutomaticZenRules(String packageName);
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 69ec831b5d1d..0f569f6473a8 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -61,8 +61,13 @@ public final class NotificationChannel implements Parcelable {
/**
* The maximum length for text fields in a NotificationChannel. Fields will be truncated at this
* limit.
+ * @hide
*/
- private static final int MAX_TEXT_LENGTH = 1000;
+ public static final int MAX_TEXT_LENGTH = 1000;
+ /**
+ * @hide
+ */
+ public static final int MAX_VIBRATION_LENGTH = 1000;
private static final String TAG_CHANNEL = "channel";
private static final String ATT_NAME = "name";
@@ -195,17 +200,17 @@ public final class NotificationChannel implements Parcelable {
*/
protected NotificationChannel(Parcel in) {
if (in.readByte() != 0) {
- mId = in.readString();
+ mId = getTrimmedString(in.readString());
} else {
mId = null;
}
if (in.readByte() != 0) {
- mName = in.readString();
+ mName = getTrimmedString(in.readString());
} else {
mName = null;
}
if (in.readByte() != 0) {
- mDesc = in.readString();
+ mDesc = getTrimmedString(in.readString());
} else {
mDesc = null;
}
@@ -214,18 +219,22 @@ public final class NotificationChannel implements Parcelable {
mLockscreenVisibility = in.readInt();
if (in.readByte() != 0) {
mSound = Uri.CREATOR.createFromParcel(in);
+ mSound = Uri.parse(getTrimmedString(mSound.toString()));
} else {
mSound = null;
}
mLights = in.readByte() != 0;
mVibration = in.createLongArray();
+ if (mVibration != null && mVibration.length > MAX_VIBRATION_LENGTH) {
+ mVibration = Arrays.copyOf(mVibration, MAX_VIBRATION_LENGTH);
+ }
mUserLockedFields = in.readInt();
mFgServiceShown = in.readByte() != 0;
mVibrationEnabled = in.readByte() != 0;
mShowBadge = in.readByte() != 0;
mDeleted = in.readByte() != 0;
if (in.readByte() != 0) {
- mGroup = in.readString();
+ mGroup = getTrimmedString(in.readString());
} else {
mGroup = null;
}
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index a8ee414cac0a..cb20b7f84256 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -42,8 +42,9 @@ public final class NotificationChannelGroup implements Parcelable {
/**
* The maximum length for text fields in a NotificationChannelGroup. Fields will be truncated at
* this limit.
+ * @hide
*/
- private static final int MAX_TEXT_LENGTH = 1000;
+ public static final int MAX_TEXT_LENGTH = 1000;
private static final String TAG_GROUP = "channelGroup";
private static final String ATT_NAME = "name";
@@ -89,13 +90,17 @@ public final class NotificationChannelGroup implements Parcelable {
*/
protected NotificationChannelGroup(Parcel in) {
if (in.readByte() != 0) {
- mId = in.readString();
+ mId = getTrimmedString(in.readString());
} else {
mId = null;
}
- mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
if (in.readByte() != 0) {
- mDescription = in.readString();
+ mName = getTrimmedString(in.readString());
+ } else {
+ mName = "";
+ }
+ if (in.readByte() != 0) {
+ mDescription = getTrimmedString(in.readString());
} else {
mDescription = null;
}
@@ -119,7 +124,12 @@ public final class NotificationChannelGroup implements Parcelable {
} else {
dest.writeByte((byte) 0);
}
- TextUtils.writeToParcel(mName, dest, flags);
+ if (mName != null) {
+ dest.writeByte((byte) 1);
+ dest.writeString(mName.toString());
+ } else {
+ dest.writeByte((byte) 0);
+ }
if (mDescription != null) {
dest.writeByte((byte) 1);
dest.writeString(mDescription);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index c6aa4fd86594..b81a86331ca0 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -923,10 +923,12 @@ public class NotificationManager {
List<ZenModeConfig.ZenRule> rules = service.getZenRules();
Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
for (ZenModeConfig.ZenRule rule : rules) {
- ruleMap.put(rule.id, new AutomaticZenRule(rule.name, rule.component,
+ AutomaticZenRule azr = new AutomaticZenRule(rule.name, rule.component,
rule.configurationActivity, rule.conditionId, rule.zenPolicy,
zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
- rule.creationTime));
+ rule.creationTime);
+ azr.setPackageName(rule.pkg);
+ ruleMap.put(rule.id, azr);
}
return ruleMap;
} catch (RemoteException e) {
@@ -967,7 +969,7 @@ public class NotificationManager {
public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
INotificationManager service = getService();
try {
- return service.addAutomaticZenRule(automaticZenRule);
+ return service.addAutomaticZenRule(automaticZenRule, mContext.getPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 08527c79c242..c3e777f584ed 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -19,6 +19,7 @@ package android.app.admin;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import android.Manifest.permission;
+import android.accounts.Account;
import android.annotation.CallbackExecutor;
import android.annotation.ColorInt;
import android.annotation.IntDef;
@@ -151,6 +152,26 @@ public class DevicePolicyManager {
this(context, service, false);
}
+ /**
+ * Called when a managed profile has been provisioned.
+ *
+ * @throws SecurityException if the caller does not hold
+ * {@link android.Manifest.permission#MANAGE_PROFILE_AND_DEVICE_OWNERS}.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
+ public void finalizeWorkProfileProvisioning(
+ @NonNull UserHandle managedProfileUser, @Nullable Account migratedAccount) {
+ if (mService == null) {
+ throw new IllegalStateException("Could not find DevicePolicyManagerService");
+ }
+ try {
+ mService.finalizeWorkProfileProvisioning(managedProfileUser, migratedAccount);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/** @hide */
@VisibleForTesting
protected DevicePolicyManager(Context context, IDevicePolicyManager service,
@@ -8815,6 +8836,15 @@ public class DevicePolicyManager {
* {@link android.os.Build.VERSION_CODES#M} the app-op matching the permission is set to
* {@link android.app.AppOpsManager#MODE_IGNORED}, but the permission stays granted.
*
+ * Control over the following permissions are restricted for managed profile owners:
+ * <ul>
+ * <li>Manifest.permission.READ_SMS</li>
+ * </ul>
+ * <p>
+ * A managed profile owner may not grant these permissions (i.e. call this method with any of
+ * the permissions listed above and {@code grantState} of
+ * {@code #PERMISSION_GRANT_STATE_GRANTED}), but may deny them.
+ *
* @param admin Which profile or device owner this request is associated with.
* @param packageName The application to grant or revoke a permission to.
* @param permission The permission to grant or revoke.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 2b9641999019..bf245803260b 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -17,6 +17,7 @@
package android.app.admin;
+import android.accounts.Account;
import android.app.admin.NetworkEvent;
import android.app.IApplicationThread;
import android.app.IServiceConnection;
@@ -87,6 +88,8 @@ interface IDevicePolicyManager {
int getCurrentFailedPasswordAttempts(int userHandle, boolean parent);
int getProfileWithMinimumFailedPasswordsForWipe(int userHandle, boolean parent);
+ void finalizeWorkProfileProvisioning(in UserHandle managedProfileUser, in Account migratedAccount);
+
void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num, boolean parent);
int getMaximumFailedPasswordsForWipe(in ComponentName admin, int userHandle, boolean parent);
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index dbc1c199cb4d..437783c4f680 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -1095,7 +1095,9 @@ public class AppWidgetManager {
* @param intent The intent of the service which will be providing the data to the
* RemoteViewsAdapter.
* @param connection The callback interface to be notified when a connection is made or lost.
- * @param flags Flags used for binding to the service
+ * @param flags Flags used for binding to the service. Currently only
+ * {@link Context#BIND_AUTO_CREATE} and
+ * {@link Context#BIND_FOREGROUND_SERVICE_WHILE_AWAKE} are supported.
*
* @see Context#getServiceDispatcher(ServiceConnection, Handler, int)
* @hide
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
index a086a308d0d9..da4ecdd8c1f2 100644
--- a/core/java/android/content/AbstractThreadedSyncAdapter.java
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -21,6 +21,7 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa
import android.accounts.Account;
import android.annotation.MainThread;
import android.annotation.NonNull;
+import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -171,8 +172,20 @@ public abstract class AbstractThreadedSyncAdapter {
}
private class ISyncAdapterImpl extends ISyncAdapter.Stub {
+ private boolean isCallerSystem() {
+ final long callingUid = Binder.getCallingUid();
+ if (callingUid != Process.SYSTEM_UID) {
+ android.util.EventLog.writeEvent(0x534e4554, "203229608", -1, "");
+ return false;
+ }
+ return true;
+ }
+
@Override
public void onUnsyncableAccount(ISyncAdapterUnsyncableAccountCallback cb) {
+ if (!isCallerSystem()) {
+ return;
+ }
Handler.getMain().sendMessage(obtainMessage(
AbstractThreadedSyncAdapter::handleOnUnsyncableAccount,
AbstractThreadedSyncAdapter.this, cb));
@@ -181,12 +194,16 @@ public abstract class AbstractThreadedSyncAdapter {
@Override
public void startSync(ISyncContext syncContext, String authority, Account account,
Bundle extras) {
+ if (!isCallerSystem()) {
+ return;
+ }
if (ENABLE_LOG) {
if (extras != null) {
extras.size(); // Unparcel so its toString() will show the contents.
}
Log.d(TAG, "startSync() start " + authority + " " + account + " " + extras);
}
+
try {
final SyncContext syncContextClient = new SyncContext(syncContext);
@@ -242,6 +259,9 @@ public abstract class AbstractThreadedSyncAdapter {
@Override
public void cancelSync(ISyncContext syncContext) {
+ if (!isCallerSystem()) {
+ return;
+ }
try {
// synchronize to make sure that mSyncThreads doesn't change between when we
// check it and when we use it
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index 04e15c7957bd..b26a2403ba38 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -46,4 +46,5 @@ interface IPackageInstallerSession {
int getParentSessionId();
boolean isStaged();
+ int getInstallFlags();
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 44842c62a3c8..b44b6d90811e 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1176,6 +1176,18 @@ public class PackageInstaller {
}
/**
+ * @return Session's {@link SessionParams#installFlags}.
+ * @hide
+ */
+ public int getInstallFlags() {
+ try {
+ return mSession.getInstallFlags();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* @return the session ID of the multi-package session that this belongs to or
* {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session.
*/
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 3e880f03b222..84d9743eec9e 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -1011,4 +1011,10 @@ public abstract class PackageManagerInternal {
* that b/141413692 is not reproducible on Q.
*/
public abstract void userRemovedForTest();
+
+ /**
+ * Get installed SDK version of the package
+ * @param pkg package for which to retrieve the installed sdk version
+ */
+ public abstract int getInstalledSdkVersion(PackageParser.Package pkg);
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 535a8bc9db75..766539e5ce48 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -90,6 +90,7 @@ import android.util.AttributeSet;
import android.util.Base64;
import android.util.ByteStringUtils;
import android.util.DisplayMetrics;
+import android.util.EventLog;
import android.util.Log;
import android.util.PackageUtils;
import android.util.Pair;
@@ -134,6 +135,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
@@ -2502,6 +2504,12 @@ public class PackageParser {
}
}
+ if (declareDuplicatePermission(pkg)) {
+ outError[0] = "Found duplicate permission with a different attribute value.";
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ return null;
+ }
+
if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
&& pkg.applicationInfo.targetSdkVersion
>= android.os.Build.VERSION_CODES.DONUT)) {
@@ -2558,6 +2566,50 @@ public class PackageParser {
}
}
+ /**
+ * @return {@code true} if the package declares malformed duplicate permissions.
+ */
+ public static boolean declareDuplicatePermission(@NonNull Package pkg) {
+ final List<Permission> permissions = pkg.permissions;
+ final int size = permissions.size();
+ if (size > 0) {
+ final ArrayMap<String, Permission> checkDuplicatePerm = new ArrayMap<>(size);
+ for (int i = 0; i < size; i++) {
+ final Permission permissionDefinition = permissions.get(i);
+ final String name = permissionDefinition.info.name;
+ final Permission perm = checkDuplicatePerm.get(name);
+ if (isMalformedDuplicate(permissionDefinition, perm)) {
+ // Fix for b/213323615
+ EventLog.writeEvent(0x534e4554, "213323615");
+ return true;
+ }
+ checkDuplicatePerm.put(name, permissionDefinition);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determines if a duplicate permission is malformed .i.e. defines different protection level
+ * or group.
+ */
+ private static boolean isMalformedDuplicate(Permission p1, Permission p2) {
+ // Since a permission tree is also added as a permission with normal protection
+ // level, we need to skip if the parsedPermission is a permission tree.
+ if (p1 == null || p2 == null || p1.tree || p2.tree) {
+ return false;
+ }
+
+ if (p1.info.getProtection() != p2.info.getProtection()) {
+ return true;
+ }
+ if (!Objects.equals(p1.info.group, p2.info.group)) {
+ return true;
+ }
+
+ return false;
+ }
+
private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
diff --git a/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java b/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java
index df13ade2bf5e..bd25b8f2ad88 100644
--- a/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java
+++ b/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java
@@ -16,9 +16,9 @@
package android.hardware.location;
+import android.os.BadParcelableException;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
/**
* Geofence Hardware Request used for internal location services communication.
@@ -139,11 +139,8 @@ public final class GeofenceHardwareRequestParcelable implements Parcelable {
@Override
public GeofenceHardwareRequestParcelable createFromParcel(Parcel parcel) {
int geofenceType = parcel.readInt();
- if(geofenceType != GeofenceHardwareRequest.GEOFENCE_TYPE_CIRCLE) {
- Log.e(
- "GeofenceHardwareRequest",
- String.format("Invalid Geofence type: %d", geofenceType));
- return null;
+ if (geofenceType != GeofenceHardwareRequest.GEOFENCE_TYPE_CIRCLE) {
+ throw new BadParcelableException("Invalid Geofence type: " + geofenceType);
}
GeofenceHardwareRequest request = GeofenceHardwareRequest.createCircularGeofence(
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index fe2e948bfcd9..bb68f9516a55 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -416,6 +416,7 @@ public final class Parcel {
*/
public final void recycle() {
if (DEBUG_RECYCLE) mStack = null;
+ mClassCookies = null;
freeBuffer();
final Parcel[] pool;
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index 1f6c3cc76ddd..674dcc024ddc 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -221,4 +221,12 @@ public abstract class UserManagerInternal {
*/
public abstract boolean isSettingRestrictedForUser(String setting, int userId, String value,
int callingUid);
+
+ /**
+ * Returns {@code true} if the system should ignore errors when preparing
+ * the storage directories for the user with ID {@code userId}. This will
+ * return {@code false} for all new users; it will only return {@code true}
+ * for users that already existed on-disk from an older version of Android.
+ */
+ public abstract boolean shouldIgnorePrepareStorageErrors(int userId);
}
diff --git a/core/java/android/service/gatekeeper/GateKeeperResponse.java b/core/java/android/service/gatekeeper/GateKeeperResponse.java
index 66fee1e90aff..6b7a1e183794 100644
--- a/core/java/android/service/gatekeeper/GateKeeperResponse.java
+++ b/core/java/android/service/gatekeeper/GateKeeperResponse.java
@@ -103,7 +103,7 @@ public final class GateKeeperResponse implements Parcelable {
dest.writeInt(mTimeout);
} else if (mResponseCode == RESPONSE_OK) {
dest.writeInt(mShouldReEnroll ? 1 : 0);
- if (mPayload != null) {
+ if (mPayload != null && mPayload.length > 0) {
dest.writeInt(mPayload.length);
dest.writeByteArray(mPayload);
} else {
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index e506509bb1be..50597ec3972e 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -90,6 +90,12 @@ public final class Condition implements Parcelable {
public final int icon;
/**
+ * The maximum string length for any string contained in this condition.
+ * @hide
+ */
+ public static final int MAX_STRING_LENGTH = 1000;
+
+ /**
* An object representing the current state of a {@link android.app.AutomaticZenRule}.
* @param id the {@link android.app.AutomaticZenRule#getConditionId()} of the zen rule
* @param summary a user visible description of the rule state.
@@ -103,16 +109,19 @@ public final class Condition implements Parcelable {
if (id == null) throw new IllegalArgumentException("id is required");
if (summary == null) throw new IllegalArgumentException("summary is required");
if (!isValidState(state)) throw new IllegalArgumentException("state is invalid: " + state);
- this.id = id;
- this.summary = summary;
- this.line1 = line1;
- this.line2 = line2;
+ this.id = getTrimmedUri(id);
+ this.summary = getTrimmedString(summary);
+ this.line1 = getTrimmedString(line1);
+ this.line2 = getTrimmedString(line2);
this.icon = icon;
this.state = state;
this.flags = flags;
}
public Condition(Parcel source) {
+ // This constructor passes all fields directly into the constructor that takes all the
+ // fields as arguments; that constructor will trim each of the input strings to
+ // max length if necessary.
this((Uri)source.readParcelable(Condition.class.getClassLoader()),
source.readString(),
source.readString(),
@@ -239,4 +248,25 @@ public final class Condition implements Parcelable {
return new Condition[size];
}
};
+
+ /**
+ * Returns a truncated copy of the string if the string is longer than MAX_STRING_LENGTH.
+ */
+ private static String getTrimmedString(String input) {
+ if (input != null && input.length() > MAX_STRING_LENGTH) {
+ return input.substring(0, MAX_STRING_LENGTH);
+ }
+ return input;
+ }
+
+ /**
+ * Returns a truncated copy of the Uri by trimming the string representation to the maximum
+ * string length.
+ */
+ private static Uri getTrimmedUri(Uri input) {
+ if (input != null && input.toString().length() > MAX_STRING_LENGTH) {
+ return Uri.parse(getTrimmedString(input.toString()));
+ }
+ return input;
+ }
}
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 93bcdbffd133..e473417ed828 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -43,6 +43,7 @@ import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
+import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -151,6 +152,7 @@ public class ZenModeConfig implements Parcelable {
private static final String RULE_ATT_ENABLED = "enabled";
private static final String RULE_ATT_SNOOZING = "snoozing";
private static final String RULE_ATT_NAME = "name";
+ private static final String RULE_ATT_PKG = "pkg";
private static final String RULE_ATT_COMPONENT = "component";
private static final String RULE_ATT_CONFIG_ACTIVITY = "configActivity";
private static final String RULE_ATT_ZEN = "zen";
@@ -644,11 +646,11 @@ public class ZenModeConfig implements Parcelable {
rt.conditionId = safeUri(parser, RULE_ATT_CONDITION_ID);
rt.component = safeComponentName(parser, RULE_ATT_COMPONENT);
rt.configurationActivity = safeComponentName(parser, RULE_ATT_CONFIG_ACTIVITY);
- rt.pkg = (rt.component != null)
- ? rt.component.getPackageName()
- : (rt.configurationActivity != null)
- ? rt.configurationActivity.getPackageName()
- : null;
+ rt.pkg = XmlUtils.readStringAttribute(parser, RULE_ATT_PKG);
+ if (rt.pkg == null) {
+ // backfill from component, if present. configActivity is not safe to backfill from
+ rt.pkg = rt.component != null ? rt.component.getPackageName() : null;
+ }
rt.creationTime = safeLong(parser, RULE_ATT_CREATION_TIME, 0);
rt.enabler = parser.getAttributeValue(null, RULE_ATT_ENABLER);
rt.condition = readConditionXml(parser);
@@ -670,6 +672,9 @@ public class ZenModeConfig implements Parcelable {
out.attribute(null, RULE_ATT_NAME, rule.name);
}
out.attribute(null, RULE_ATT_ZEN, Integer.toString(rule.zenMode));
+ if (rule.pkg != null) {
+ out.attribute(null, RULE_ATT_PKG, rule.pkg);
+ }
if (rule.component != null) {
out.attribute(null, RULE_ATT_COMPONENT, rule.component.flattenToString());
}
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index bd953cad2b75..ca250691aa7a 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -16,12 +16,15 @@
package android.service.voice;
+import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
import android.hardware.soundtrigger.KeyphraseMetadata;
@@ -195,8 +198,10 @@ public class AlwaysOnHotwordDetector {
private final Callback mExternalCallback;
private final Object mLock = new Object();
private final Handler mHandler;
+ private final Context mContext;
private int mAvailability = STATE_NOT_READY;
+ private boolean mIsGrantedHotwordPermission;
/**
* Additional payload for {@link Callback#onDetected}.
@@ -324,19 +329,32 @@ public class AlwaysOnHotwordDetector {
public abstract void onRecognitionResumed();
}
+ private static boolean hasHotwordPermission(Context context) {
+ return context.checkSelfPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ private static boolean hasRecordAudioPermission(Context context) {
+ return context.checkSelfPermission(Manifest.permission.RECORD_AUDIO)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
/**
+ * @param context The context to check permission
* @param text The keyphrase text to get the detector for.
* @param locale The java locale for the detector.
* @param callback A non-null Callback for receiving the recognition events.
+ * @param keyphraseEnrollmentInfo The Enrollment info of key phrase
* @param voiceInteractionService The current voice interaction service.
* @param modelManagementService A service that allows management of sound models.
*
* @hide
*/
- public AlwaysOnHotwordDetector(String text, Locale locale, Callback callback,
+ public AlwaysOnHotwordDetector(Context context, String text, Locale locale, Callback callback,
KeyphraseEnrollmentInfo keyphraseEnrollmentInfo,
IVoiceInteractionService voiceInteractionService,
IVoiceInteractionManagerService modelManagementService) {
+ mContext = context;
mText = text;
mLocale = locale;
mKeyphraseEnrollmentInfo = keyphraseEnrollmentInfo;
@@ -346,6 +364,7 @@ public class AlwaysOnHotwordDetector {
mInternalCallback = new SoundTriggerListener(mHandler);
mVoiceInteractionService = voiceInteractionService;
mModelManagementService = modelManagementService;
+ mIsGrantedHotwordPermission = hasHotwordPermission(mContext);
new RefreshAvailabiltyTask().execute();
}
@@ -402,6 +421,12 @@ public class AlwaysOnHotwordDetector {
*/
public boolean startRecognition(@RecognitionFlags int recognitionFlags) {
if (DBG) Slog.d(TAG, "startRecognition(" + recognitionFlags + ")");
+
+ if (!mIsGrantedHotwordPermission || !hasRecordAudioPermission(mContext)) {
+ throw new IllegalStateException("Must have the RECORD_AUDIO and CAPTURE_AUDIO_HOTWORD "
+ + "permissions to access the detector.");
+ }
+
synchronized (mLock) {
if (mAvailability == STATE_INVALID) {
throw new IllegalStateException("startRecognition called on an invalid detector");
@@ -430,6 +455,12 @@ public class AlwaysOnHotwordDetector {
*/
public boolean stopRecognition() {
if (DBG) Slog.d(TAG, "stopRecognition()");
+
+ if (!mIsGrantedHotwordPermission || !hasRecordAudioPermission(mContext)) {
+ throw new IllegalStateException("Must have the RECORD_AUDIO and CAPTURE_AUDIO_HOTWORD "
+ + "permissions to access the detector.");
+ }
+
synchronized (mLock) {
if (mAvailability == STATE_INVALID) {
throw new IllegalStateException("stopRecognition called on an invalid detector");
@@ -546,7 +577,8 @@ public class AlwaysOnHotwordDetector {
synchronized (mLock) {
if (mAvailability == STATE_INVALID
|| mAvailability == STATE_HARDWARE_UNAVAILABLE
- || mAvailability == STATE_KEYPHRASE_UNSUPPORTED) {
+ || mAvailability == STATE_KEYPHRASE_UNSUPPORTED
+ || !hasRecordAudioPermission(mContext)) {
Slog.w(TAG, "Received onSoundModelsChanged for an unsupported keyphrase/config");
return;
}
@@ -717,6 +749,10 @@ public class AlwaysOnHotwordDetector {
* @return The initial availability without checking the enrollment status.
*/
private int internalGetInitialAvailability() {
+ if (!mIsGrantedHotwordPermission) {
+ return STATE_HARDWARE_UNAVAILABLE;
+ }
+
synchronized (mLock) {
// This detector has already been invalidated.
if (mAvailability == STATE_INVALID) {
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 0de17ca3b960..3d85ad7935c6 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -297,7 +297,7 @@ public class VoiceInteractionService extends Service {
synchronized (mLock) {
// Allow only one concurrent recognition via the APIs.
safelyShutdownHotwordDetector();
- mHotwordDetector = new AlwaysOnHotwordDetector(keyphrase, locale, callback,
+ mHotwordDetector = new AlwaysOnHotwordDetector(this, keyphrase, locale, callback,
mKeyphraseEnrollmentInfo, mInterface, mSystemService);
}
return mHotwordDetector;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 032af1c5c7b5..71fdad529111 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -2842,7 +2842,7 @@ public final class InputMethodManager {
@UnsupportedAppUsage
public int getInputMethodWindowVisibleHeight() {
try {
- return mService.getInputMethodWindowVisibleHeight();
+ return mService.getInputMethodWindowVisibleHeight(mClient);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/com/android/internal/app/HarmfulAppWarningActivity.java b/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
index ce2d229d41b3..33209e110123 100644
--- a/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
+++ b/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
@@ -16,6 +16,8 @@
package com.android.internal.app;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -27,6 +29,7 @@ import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
+
import com.android.internal.R;
/**
@@ -48,6 +51,7 @@ public class HarmfulAppWarningActivity extends AlertActivity implements
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
final Intent intent = getIntent();
mPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
mTarget = intent.getParcelableExtra(Intent.EXTRA_INTENT);
diff --git a/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
index 4ce6f609ef73..fdf0e9046eef 100644
--- a/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
+++ b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
@@ -17,6 +17,7 @@
package com.android.internal.notification;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
public final class NotificationAccessConfirmationActivityContract {
@@ -25,13 +26,14 @@ public final class NotificationAccessConfirmationActivityContract {
"com.android.settings.notification.NotificationAccessConfirmationActivity");
public static final String EXTRA_USER_ID = "user_id";
public static final String EXTRA_COMPONENT_NAME = "component_name";
- public static final String EXTRA_PACKAGE_TITLE = "package_title";
- public static Intent launcherIntent(int userId, ComponentName component, String packageTitle) {
+ /**
+ * Creates a launcher intent for NotificationAccessConfirmationActivity.
+ */
+ public static Intent launcherIntent(Context context, int userId, ComponentName component) {
return new Intent()
.setComponent(COMPONENT_NAME)
.putExtra(EXTRA_USER_ID, userId)
- .putExtra(EXTRA_COMPONENT_NAME, component)
- .putExtra(EXTRA_PACKAGE_TITLE, packageTitle);
+ .putExtra(EXTRA_COMPONENT_NAME, component);
}
}
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index c29e823218eb..19731b27374a 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -67,7 +67,7 @@ interface IInputMethodManager {
void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
// This is kept due to @UnsupportedAppUsage.
// TODO(Bug 113914148): Consider removing this.
- int getInputMethodWindowVisibleHeight();
+ int getInputMethodWindowVisibleHeight(in IInputMethodClient client);
void reportActivityView(in IInputMethodClient parentClient, int childDisplayId,
in float[] matrixValues);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0fff075b961d..de6420debf63 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -95,6 +95,7 @@
<protected-broadcast android:name="android.intent.action.USER_ACTIVITY_NOTIFICATION" />
<protected-broadcast android:name="android.intent.action.MY_PACKAGE_SUSPENDED" />
<protected-broadcast android:name="android.intent.action.MY_PACKAGE_UNSUSPENDED" />
+ <protected-broadcast android:name="android.app.action.MANAGED_PROFILE_PROVISIONED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
diff --git a/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java b/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
new file mode 100644
index 000000000000..282fdad294eb
--- /dev/null
+++ b/core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.fail;
+
+import android.content.ComponentName;
+import android.net.Uri;
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.google.common.base.Strings;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class AutomaticZenRuleTest {
+ private static final String CLASS = "android.app.AutomaticZenRule";
+
+ @Test
+ public void testLongFields_inConstructor() {
+ String longString = Strings.repeat("A", 65536);
+ Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
+
+ // test both variants where there's an owner, and where there's a configuration activity
+ AutomaticZenRule rule1 = new AutomaticZenRule(
+ longString, // name
+ new ComponentName("pkg", longString), // owner
+ null, // configuration activity
+ longUri, // conditionId
+ null, // zen policy
+ 0, // interruption filter
+ true); // enabled
+
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule1.getName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ rule1.getConditionId().toString().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule1.getOwner().getClassName().length());
+
+ AutomaticZenRule rule2 = new AutomaticZenRule(
+ longString, // name
+ null, // owner
+ new ComponentName(longString, "SomeClassName"), // configuration activity
+ longUri, // conditionId
+ null, // zen policy
+ 0, // interruption filter
+ false); // enabled
+
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule2.getName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ rule2.getConditionId().toString().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ rule2.getConfigurationActivity().getPackageName().length());
+ }
+
+ @Test
+ public void testLongFields_inSetters() {
+ String longString = Strings.repeat("A", 65536);
+ Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
+
+ AutomaticZenRule rule = new AutomaticZenRule(
+ "sensible name",
+ new ComponentName("pkg", "ShortClass"),
+ null,
+ Uri.parse("uri://short"),
+ null, 0, true);
+
+ rule.setName(longString);
+ rule.setConditionId(longUri);
+ rule.setConfigurationActivity(new ComponentName(longString, longString));
+
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule.getName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ rule.getConditionId().toString().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ rule.getConfigurationActivity().getPackageName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ rule.getConfigurationActivity().getClassName().length());
+ }
+
+ @Test
+ public void testLongInputsFromParcel() {
+ // Create a rule with long fields, set directly via reflection so that we can confirm that
+ // a rule with too-long fields that comes in via a parcel has its fields truncated directly.
+ AutomaticZenRule rule = new AutomaticZenRule(
+ "placeholder",
+ new ComponentName("place", "holder"),
+ null,
+ Uri.parse("uri://placeholder"),
+ null, 0, true);
+
+ try {
+ String longString = Strings.repeat("A", 65536);
+ Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
+ Field name = Class.forName(CLASS).getDeclaredField("name");
+ name.setAccessible(true);
+ name.set(rule, longString);
+ Field conditionId = Class.forName(CLASS).getDeclaredField("conditionId");
+ conditionId.setAccessible(true);
+ conditionId.set(rule, longUri);
+ Field owner = Class.forName(CLASS).getDeclaredField("owner");
+ owner.setAccessible(true);
+ owner.set(rule, new ComponentName(longString, longString));
+ Field configActivity = Class.forName(CLASS).getDeclaredField("configurationActivity");
+ configActivity.setAccessible(true);
+ configActivity.set(rule, new ComponentName(longString, longString));
+ } catch (NoSuchFieldException e) {
+ fail(e.toString());
+ } catch (ClassNotFoundException e) {
+ fail(e.toString());
+ } catch (IllegalAccessException e) {
+ fail(e.toString());
+ }
+
+ Parcel parcel = Parcel.obtain();
+ rule.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ AutomaticZenRule fromParcel = new AutomaticZenRule(parcel);
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, fromParcel.getName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ fromParcel.getConditionId().toString().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ fromParcel.getConfigurationActivity().getPackageName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ fromParcel.getConfigurationActivity().getClassName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ fromParcel.getOwner().getPackageName().length());
+ assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
+ fromParcel.getOwner().getClassName().length());
+ }
+}
diff --git a/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java b/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java
new file mode 100644
index 000000000000..625c66a4c60e
--- /dev/null
+++ b/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+import android.text.TextUtils;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.base.Strings;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NotificationChannelGroupTest {
+ private final String CLASS = "android.app.NotificationChannelGroup";
+
+ @Test
+ public void testLongStringFields() {
+ NotificationChannelGroup group = new NotificationChannelGroup("my_group_01", "groupName");
+
+ try {
+ String longString = Strings.repeat("A", 65536);
+ Field mName = Class.forName(CLASS).getDeclaredField("mName");
+ mName.setAccessible(true);
+ mName.set(group, longString);
+ Field mId = Class.forName(CLASS).getDeclaredField("mId");
+ mId.setAccessible(true);
+ mId.set(group, longString);
+ Field mDescription = Class.forName(CLASS).getDeclaredField("mDescription");
+ mDescription.setAccessible(true);
+ mDescription.set(group, longString);
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+
+ Parcel parcel = Parcel.obtain();
+ group.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ NotificationChannelGroup fromParcel =
+ NotificationChannelGroup.CREATOR.createFromParcel(parcel);
+ assertEquals(NotificationChannelGroup.MAX_TEXT_LENGTH, fromParcel.getId().length());
+ assertEquals(NotificationChannelGroup.MAX_TEXT_LENGTH, fromParcel.getName().length());
+ assertEquals(NotificationChannelGroup.MAX_TEXT_LENGTH,
+ fromParcel.getDescription().length());
+ }
+
+ @Test
+ public void testNullableFields() {
+ NotificationChannelGroup group = new NotificationChannelGroup("my_group_01", null);
+
+ Parcel parcel = Parcel.obtain();
+ group.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ NotificationChannelGroup fromParcel =
+ NotificationChannelGroup.CREATOR.createFromParcel(parcel);
+ assertEquals(group.getId(), fromParcel.getId());
+ assertTrue(TextUtils.isEmpty(fromParcel.getName()));
+ }
+}
diff --git a/core/tests/coretests/src/android/app/NotificationChannelTest.java b/core/tests/coretests/src/android/app/NotificationChannelTest.java
new file mode 100644
index 000000000000..d8be502e6db6
--- /dev/null
+++ b/core/tests/coretests/src/android/app/NotificationChannelTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import static junit.framework.TestCase.assertEquals;
+
+import android.net.Uri;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.base.Strings;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NotificationChannelTest {
+ private final String CLASS = "android.app.NotificationChannel";
+
+ @Test
+ public void testLongStringFields() {
+ NotificationChannel channel = new NotificationChannel("id", "name", 3);
+
+ try {
+ String longString = Strings.repeat("A", 65536);
+ Field mName = Class.forName(CLASS).getDeclaredField("mName");
+ mName.setAccessible(true);
+ mName.set(channel, longString);
+ Field mId = Class.forName(CLASS).getDeclaredField("mId");
+ mId.setAccessible(true);
+ mId.set(channel, longString);
+ Field mDesc = Class.forName(CLASS).getDeclaredField("mDesc");
+ mDesc.setAccessible(true);
+ mDesc.set(channel, longString);
+ Field mParentId = Class.forName(CLASS).getDeclaredField("mParentId");
+ mParentId.setAccessible(true);
+ mParentId.set(channel, longString);
+ Field mGroup = Class.forName(CLASS).getDeclaredField("mGroup");
+ mGroup.setAccessible(true);
+ mGroup.set(channel, longString);
+ Field mConversationId = Class.forName(CLASS).getDeclaredField("mConversationId");
+ mConversationId.setAccessible(true);
+ mConversationId.set(channel, longString);
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+
+ Parcel parcel = Parcel.obtain();
+ channel.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ NotificationChannel fromParcel = NotificationChannel.CREATOR.createFromParcel(parcel);
+ assertEquals(NotificationChannel.MAX_TEXT_LENGTH, fromParcel.getId().length());
+ assertEquals(NotificationChannel.MAX_TEXT_LENGTH, fromParcel.getName().length());
+ assertEquals(NotificationChannel.MAX_TEXT_LENGTH,
+ fromParcel.getDescription().length());
+ assertEquals(NotificationChannel.MAX_TEXT_LENGTH,
+ fromParcel.getGroup().length());
+ }
+
+ @Test
+ public void testLongAlertFields() {
+ NotificationChannel channel = new NotificationChannel("id", "name", 3);
+
+ channel.setSound(Uri.parse("content://" + Strings.repeat("A",65536)),
+ Notification.AUDIO_ATTRIBUTES_DEFAULT);
+ channel.setVibrationPattern(new long[65550/2]);
+
+ Parcel parcel = Parcel.obtain();
+ channel.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ NotificationChannel fromParcel = NotificationChannel.CREATOR.createFromParcel(parcel);
+ assertEquals(NotificationChannel.MAX_VIBRATION_LENGTH,
+ fromParcel.getVibrationPattern().length);
+ assertEquals(NotificationChannel.MAX_TEXT_LENGTH,
+ fromParcel.getSound().toString().length());
+ }
+}
diff --git a/core/tests/coretests/src/android/service/notification/ConditionTest.java b/core/tests/coretests/src/android/service/notification/ConditionTest.java
new file mode 100644
index 000000000000..42629ba41287
--- /dev/null
+++ b/core/tests/coretests/src/android/service/notification/ConditionTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.fail;
+
+import android.net.Uri;
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.google.common.base.Strings;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ConditionTest {
+ private static final String CLASS = "android.service.notification.Condition";
+
+ @Test
+ public void testLongFields_inConstructors() {
+ String longString = Strings.repeat("A", 65536);
+ Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
+
+ // Confirm strings are truncated via short constructor
+ Condition cond1 = new Condition(longUri, longString, Condition.STATE_TRUE);
+
+ assertEquals(Condition.MAX_STRING_LENGTH, cond1.id.toString().length());
+ assertEquals(Condition.MAX_STRING_LENGTH, cond1.summary.length());
+
+ // Confirm strings are truncated via long constructor
+ Condition cond2 = new Condition(longUri, longString, longString, longString,
+ -1, Condition.STATE_TRUE, Condition.FLAG_RELEVANT_ALWAYS);
+
+ assertEquals(Condition.MAX_STRING_LENGTH, cond2.id.toString().length());
+ assertEquals(Condition.MAX_STRING_LENGTH, cond2.summary.length());
+ assertEquals(Condition.MAX_STRING_LENGTH, cond2.line1.length());
+ assertEquals(Condition.MAX_STRING_LENGTH, cond2.line2.length());
+ }
+
+ @Test
+ public void testLongFields_viaParcel() {
+ // Set fields via reflection to force them to be long, then parcel and unparcel to make sure
+ // it gets truncated upon unparcelling.
+ Condition cond = new Condition(Uri.parse("uri://placeholder"), "placeholder",
+ Condition.STATE_TRUE);
+
+ try {
+ String longString = Strings.repeat("A", 65536);
+ Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
+ Field id = Class.forName(CLASS).getDeclaredField("id");
+ id.setAccessible(true);
+ id.set(cond, longUri);
+ Field summary = Class.forName(CLASS).getDeclaredField("summary");
+ summary.setAccessible(true);
+ summary.set(cond, longString);
+ Field line1 = Class.forName(CLASS).getDeclaredField("line1");
+ line1.setAccessible(true);
+ line1.set(cond, longString);
+ Field line2 = Class.forName(CLASS).getDeclaredField("line2");
+ line2.setAccessible(true);
+ line2.set(cond, longString);
+ } catch (NoSuchFieldException e) {
+ fail(e.toString());
+ } catch (ClassNotFoundException e) {
+ fail(e.toString());
+ } catch (IllegalAccessException e) {
+ fail(e.toString());
+ }
+
+ Parcel parcel = Parcel.obtain();
+ cond.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ Condition fromParcel = new Condition(parcel);
+ assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.id.toString().length());
+ assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.summary.length());
+ assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.line1.length());
+ assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.line2.length());
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
index fb109d2bda5b..672c0ae822f2 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
@@ -196,7 +196,6 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
filter.addAction(DISABLE_PLUGIN);
filter.addDataScheme("package");
mContext.registerReceiver(this, filter, PluginInstanceManager.PLUGIN_PERMISSION, null);
- mContext.registerReceiver(this, filter);
filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
mContext.registerReceiver(this, filter);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index d45603fd23ff..c1585baaf22a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -30,6 +30,7 @@ import android.view.KeyEvent;
import android.view.View;
import android.widget.LinearLayout;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils;
@@ -97,6 +98,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
protected abstract int getPasswordTextViewId();
protected abstract void resetState();
+ protected abstract SecurityMode getSecurityMode();
@Override
protected void onFinishInflate() {
@@ -204,7 +206,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
mCallback.reportUnlockAttempt(userId, true, 0);
if (dismissKeyguard) {
mDismissing = true;
- mCallback.dismiss(true, userId);
+ mCallback.dismiss(true, userId, getSecurityMode());
}
} else {
if (isValidPassword) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index 8e1f6d384d1d..10a747ccf74d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -84,7 +84,7 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback {
// the user proved presence via some other way to the trust agent.
Log.i(TAG, "TrustAgent dismissed Keyguard.");
}
- dismiss(false /* authenticated */, userId);
+ dismiss(false /* authenticated */, userId, SecurityMode.Invalid);
} else {
mViewMediatorCallback.playTrustedSound();
}
@@ -188,12 +188,13 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback {
* @return True if the keyguard is done.
*/
public boolean dismiss(int targetUserId) {
- return dismiss(false, targetUserId);
+ return dismiss(false, targetUserId, getCurrentSecurityMode());
}
public boolean handleBackKey() {
if (mSecurityContainer.getCurrentSecuritySelection() != SecurityMode.None) {
- mSecurityContainer.dismiss(false, KeyguardUpdateMonitor.getCurrentUser());
+ mSecurityContainer.dismiss(false, KeyguardUpdateMonitor.getCurrentUser(),
+ getCurrentSecurityMode());
return true;
}
return false;
@@ -204,8 +205,10 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback {
}
@Override
- public boolean dismiss(boolean authenticated, int targetUserId) {
- return mSecurityContainer.showNextSecurityScreenOrFinish(authenticated, targetUserId);
+ public boolean dismiss(boolean authenticated, int targetUserId,
+ SecurityMode expectedSecurityMode) {
+ return mSecurityContainer.showNextSecurityScreenOrFinish(authenticated, targetUserId,
+ expectedSecurityMode);
}
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index 15d2ea7c3280..f8a19f3b87b2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -22,6 +22,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils;
import com.android.systemui.R;
@@ -182,4 +183,9 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
public boolean hasOverlappingRendering() {
return false;
}
+
+ @Override
+ public SecurityMode getSecurityMode() {
+ return SecurityMode.PIN;
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index e3ac0f684e44..61f9f009d44e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -37,6 +37,7 @@ import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import com.android.internal.widget.TextViewInputDisabler;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.R;
import java.util.List;
@@ -393,4 +394,9 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView
}
return bytes;
}
+
+ @Override
+ public SecurityMode getSecurityMode() {
+ return SecurityMode.Password;
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 34c15e64ff54..90511df3bbd5 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -39,6 +39,7 @@ import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.settingslib.animation.AppearAnimationCreator;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils;
@@ -349,7 +350,7 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
mCallback.reportUnlockAttempt(userId, true, 0);
if (dismissKeyguard) {
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
- mCallback.dismiss(true, userId);
+ mCallback.dismiss(true, userId, SecurityMode.Pattern);
}
} else {
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
index 49dcfffb0d72..2f90b5112f6e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
@@ -15,14 +15,17 @@
*/
package com.android.keyguard;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+
public interface KeyguardSecurityCallback {
/**
* Dismiss the given security screen.
* @param securityVerified true if the user correctly entered credentials for the given screen.
* @param targetUserId a user that needs to be the foreground user at the dismissal completion.
+ * @param expectedSecurityMode The security mode that is invoking this dismiss.
*/
- void dismiss(boolean securityVerified, int targetUserId);
+ void dismiss(boolean securityVerified, int targetUserId, SecurityMode expectedSecurityMode);
/**
* Manually report user activity to keep the device awake.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index ace24a3b7ce1..9313a54f2bbb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -103,7 +103,8 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
// Used to notify the container when something interesting happens.
public interface SecurityCallback {
- public boolean dismiss(boolean authenticated, int targetUserId);
+ public boolean dismiss(boolean authenticated, int targetUserId,
+ SecurityMode expectedSecurityMode);
public void userActivity();
public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput);
@@ -480,10 +481,20 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
* @param authenticated true if the user entered the correct authentication
* @param targetUserId a user that needs to be the foreground user at the finish (if called)
* completion.
+ * @param expectedSecurityMode SecurityMode that is invoking this request. SecurityMode.Invalid
+ * indicates that no check should be done
* @return true if keyguard is done
*/
- boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId) {
+ boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId,
+ SecurityMode expectedSecurityMode) {
if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
+ if (expectedSecurityMode != SecurityMode.Invalid
+ && expectedSecurityMode != getCurrentSecurityMode()) {
+ Log.w(TAG, "Attempted to invoke showNextSecurityScreenOrFinish with securityMode "
+ + expectedSecurityMode + ", but current mode is " + getCurrentSecurityMode());
+ return false;
+ }
+
boolean finish = false;
boolean strongAuth = false;
int eventSubtype = -1;
@@ -603,8 +614,13 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
mUpdateMonitor.cancelFaceAuth();
}
- public void dismiss(boolean authenticated, int targetId) {
- mSecurityCallback.dismiss(authenticated, targetId);
+ /**
+ * Potentially dismiss the current security screen, after validating that all device
+ * security has been unlocked. Otherwise show the next screen.
+ */
+ public void dismiss(boolean authenticated, int targetId,
+ SecurityMode expectedSecurityMode) {
+ mSecurityCallback.dismiss(authenticated, targetId, expectedSecurityMode);
}
public boolean isVerifyUnlockOnly() {
@@ -654,7 +670,8 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
@Override
public boolean isVerifyUnlockOnly() { return false; }
@Override
- public void dismiss(boolean securityVerified, int targetUserId) { }
+ public void dismiss(boolean securityVerified, int targetUserId,
+ SecurityMode expectedSecurityMode) { }
@Override
public void onUserInput() { }
@Override
@@ -706,8 +723,9 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
return mCurrentSecuritySelection;
}
- public void dismiss(boolean authenticated, int targetUserId) {
- mCallback.dismiss(authenticated, targetUserId);
+ public void dismiss(boolean authenticated, int targetUserId,
+ SecurityMode expectedSecurityMode) {
+ mCallback.dismiss(authenticated, targetUserId, expectedSecurityMode);
}
public boolean needsInput() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 367a7bd4aed7..140bb7dcb097 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -41,6 +41,7 @@ import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.PhoneConstants;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.R;
/**
@@ -343,7 +344,8 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
mRemainingAttempts = -1;
mShowDefaultMessage = true;
if (mCallback != null) {
- mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+ mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser(),
+ SecurityMode.SimPin);
}
} else {
mShowDefaultMessage = false;
@@ -391,5 +393,10 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
return getContext().getString(
com.android.internal.R.string.keyguard_accessibility_sim_pin_unlock);
}
+
+ @Override
+ public SecurityMode getSecurityMode() {
+ return SecurityMode.SimPin;
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 81f8c67605fe..4e5c8a0e4d90 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -40,6 +40,7 @@ import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.PhoneConstants;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.R;
@@ -79,7 +80,8 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {
// mCallback can be null if onSimStateChanged callback is called when keyguard
// isn't active.
if (mCallback != null) {
- mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+ mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser(),
+ SecurityMode.SimPuk);
}
break;
}
@@ -414,7 +416,8 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {
mRemainingAttempts = -1;
mShowDefaultMessage = true;
if (mCallback != null) {
- mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+ mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser(),
+ SecurityMode.SimPuk);
}
} else {
mShowDefaultMessage = false;
@@ -469,6 +472,11 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {
return getContext().getString(
com.android.internal.R.string.keyguard_accessibility_sim_puk_unlock);
}
+
+ @Override
+ public SecurityMode getSecurityMode() {
+ return SecurityMode.SimPuk;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index abf29c47e803..3ca8d97e2919 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -126,11 +126,11 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll
}
@Override
- public boolean setState(int state) {
+ public boolean setState(int state, boolean force) {
if (state > MAX_STATE || state < MIN_STATE) {
throw new IllegalArgumentException("Invalid state " + state);
}
- if (state == mState) {
+ if (!force && state == mState) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
index 2ad979ab64e3..f2d798171c32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java
@@ -58,7 +58,19 @@ public interface SysuiStatusBarStateController extends StatusBarStateController
* @param state see {@link StatusBarState} for valid options
* @return {@code true} if the state changed, else {@code false}
*/
- boolean setState(int state);
+ default boolean setState(int state) {
+ return setState(state, false /* force */);
+ }
+
+ /**
+ * Update the status bar state
+ * @param state see {@link StatusBarState} for valid options
+ * @param force whether to set the state even if it's the same as the current state. This will
+ * dispatch the state to all StatusBarStateListeners, ensuring that all listening
+ * components are reset to this state.
+ * @return {@code true} if the state was changed or set forcefully
+ */
+ boolean setState(int state, boolean force);
/**
* Update the dozing state from {@link StatusBar}'s perspective
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
index ef09434aa395..a3f4db6f3fcd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
@@ -201,6 +201,89 @@ public class NotificationInterruptionStateProvider {
return true;
}
+ public boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry) {
+ if (entry.notification.getNotification().fullScreenIntent == null) {
+ return false;
+ }
+
+ // Never show FSI when suppressed by DND
+ if (entry.shouldSuppressFullScreenIntent()) {
+ if (DEBUG) {
+ Log.d(TAG, "No FullScreenIntent: Suppressed by DND: " + entry.key);
+ }
+ return false;
+ }
+
+ // Never show FSI if importance is not HIGH
+ if (entry.importance < NotificationManager.IMPORTANCE_HIGH) {
+ if (DEBUG) {
+ Log.d(TAG, "No FullScreenIntent: Not important enough: " + entry.key);
+ }
+ return false;
+ }
+
+ // If the notification has suppressive GroupAlertBehavior, block FSI and warn.
+ StatusBarNotification sbn = entry.notification;
+ if (sbn.isGroup() && sbn.getNotification().suppressAlertingDueToGrouping()) {
+ // b/231322873: Detect and report an event when a notification has both an FSI and a
+ // suppressive groupAlertBehavior, and now correctly block the FSI from firing.
+ final int uid = entry.notification.getUid();
+ android.util.EventLog.writeEvent(0x534e4554, "231322873", uid, "groupAlertBehavior");
+ if (DEBUG) {
+ Log.w(TAG, "No FullScreenIntent: WARNING: GroupAlertBehavior will prevent HUN: "
+ + entry.key);
+ }
+ return false;
+ }
+
+ // If the screen is off, then launch the FullScreenIntent
+ if (!mPowerManager.isInteractive()) {
+ if (DEBUG) {
+ Log.d(TAG, "FullScreenIntent: Device is not interactive: " + entry.key);
+ }
+ return true;
+ }
+
+ // If the device is currently dreaming, then launch the FullScreenIntent
+ if (isDreaming()) {
+ if (DEBUG) {
+ Log.d(TAG, "FullScreenIntent: Device is dreaming: " + entry.key);
+ }
+ return true;
+ }
+
+ // If the keyguard is showing, then launch the FullScreenIntent
+ if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
+ if (DEBUG) {
+ Log.d(TAG, "FullScreenIntent: Keyguard is showing: " + entry.key);
+ }
+ return true;
+ }
+
+ // If the notification should HUN, then we don't need FSI
+ if (shouldHeadsUp(entry)) {
+ if (DEBUG) {
+ Log.d(TAG, "No FullScreenIntent: Expected to HUN: " + entry.key);
+ }
+ return false;
+ }
+
+ // If the notification won't HUN for some other reason (DND/snooze/etc), launch FSI.
+ if (DEBUG) {
+ Log.d(TAG, "FullScreenIntent: Expected not to HUN: " + entry.key);
+ }
+ return true;
+ }
+
+ private boolean isDreaming() {
+ try {
+ return mDreamManager.isDreaming();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to query dream manager.", e);
+ return false;
+ }
+ }
+
/**
* Whether the notification should peek in from the top and alert the user.
*
@@ -256,13 +339,7 @@ public class NotificationInterruptionStateProvider {
return false;
}
- boolean isDreaming = false;
- try {
- isDreaming = mDreamManager.isDreaming();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to query dream manager.", e);
- }
- boolean inUse = mPowerManager.isScreenOn() && !isDreaming;
+ boolean inUse = mPowerManager.isScreenOn() && !isDreaming();
if (!inUse) {
if (DEBUG_HEADS_UP) {
@@ -415,19 +492,6 @@ public class NotificationInterruptionStateProvider {
return mPresenter;
}
- /**
- * When an entry was added, should we launch its fullscreen intent? Examples are Alarms or
- * incoming calls.
- *
- * @param entry the entry that was added
- * @return {@code true} if we should launch the full screen intent
- */
- public boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry) {
- return entry.notification.getNotification().fullScreenIntent != null
- && (!shouldHeadsUp(entry)
- || mStatusBarStateController.getState() == StatusBarState.KEYGUARD);
- }
-
/** A component which can suppress heads-up notifications due to the overall state of the UI. */
public interface HeadsUpSuppressor {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 98febd451012..a00f625198dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -714,6 +714,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@VisibleForTesting
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void updateFooter() {
+ if (mFooterView == null) {
+ return;
+ }
boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications(ROWS_ALL);
boolean showFooterView = (showDismissView ||
mEntryManager.getNotificationData().getActiveNotifications().size() != 0)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index cc691ae2d9be..abe6868e6c9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -3069,7 +3069,11 @@ public class StatusBar extends SystemUI implements DemoMode,
&& mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
}
- private boolean updateIsKeyguard() {
+ boolean updateIsKeyguard() {
+ return updateIsKeyguard(false /* force */);
+ }
+
+ boolean updateIsKeyguard(boolean force) {
boolean wakeAndUnlocking = mBiometricUnlockController.getMode()
== BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
@@ -3098,7 +3102,7 @@ public class StatusBar extends SystemUI implements DemoMode,
showKeyguardImpl();
}
} else {
- return hideKeyguardImpl();
+ return hideKeyguardImpl(force);
}
return false;
}
@@ -3240,11 +3244,11 @@ public class StatusBar extends SystemUI implements DemoMode,
/**
* @return true if we would like to stay in the shade, false if it should go away entirely
*/
- public boolean hideKeyguardImpl() {
+ public boolean hideKeyguardImpl(boolean force) {
mIsKeyguard = false;
Trace.beginSection("StatusBar#hideKeyguard");
boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
- if (!(mStatusBarStateController.setState(StatusBarState.SHADE))) {
+ if (!(mStatusBarStateController.setState(StatusBarState.SHADE, force))) {
//TODO: StatusBarStateController should probably know about hiding the keyguard and
// notify listeners.
@@ -3745,7 +3749,8 @@ public class StatusBar extends SystemUI implements DemoMode,
// is correct.
mHandler.post(() -> onCameraLaunchGestureDetected(mLastCameraLaunchSource));
}
- updateIsKeyguard();
+ // When finished going to sleep, force the status bar state to avoid stale state.
+ updateIsKeyguard(true /* force */);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 946fe0b3a2f8..1998f5a77302 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -27,6 +27,7 @@ import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.os.Binder;
+import android.os.Build;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.Trace;
@@ -248,6 +249,16 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
}
Trace.setCounter("display_mode_id", mLpChanged.preferredDisplayModeId);
}
+
+ if (state.bouncerShowing && !isDebuggable()) {
+ mLpChanged.flags |= LayoutParams.FLAG_SECURE;
+ } else {
+ mLpChanged.flags &= ~LayoutParams.FLAG_SECURE;
+ }
+ }
+
+ protected boolean isDebuggable() {
+ return Build.IS_DEBUGGABLE;
}
private void adjustScreenOrientation(State state) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 02215a984203..1d15622599f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -715,13 +715,15 @@ public class StatusBarTest extends SysuiTestCase {
// By default, showKeyguardImpl sets state to KEYGUARD.
mStatusBar.showKeyguardImpl();
- verify(mStatusBarStateController).setState(eq(StatusBarState.KEYGUARD));
+ verify(mStatusBarStateController).setState(
+ eq(StatusBarState.KEYGUARD), eq(false) /* force */);
// If useFullscreenUserSwitcher is true, state is set to FULLSCREEN_USER_SWITCHER.
mStatusBar.mUserSwitcherController = mock(UserSwitcherController.class);
when(mStatusBar.mUserSwitcherController.useFullscreenUserSwitcher()).thenReturn(true);
mStatusBar.showKeyguardImpl();
- verify(mStatusBarStateController).setState(eq(StatusBarState.FULLSCREEN_USER_SWITCHER));
+ verify(mStatusBarStateController).setState(
+ eq(StatusBarState.FULLSCREEN_USER_SWITCHER), eq(false) /* force */);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
index 4ffaeaef77b4..a1526d438b18 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -40,6 +42,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -62,6 +65,8 @@ public class StatusBarWindowControllerTest extends SysuiTestCase {
private ConfigurationController mConfigurationController;
@Mock
private KeyguardBypassController mKeyguardBypassController;
+ @Captor
+ private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters;
private StatusBarWindowController mStatusBarWindowController;
@@ -72,24 +77,27 @@ public class StatusBarWindowControllerTest extends SysuiTestCase {
mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
mActivityManager, mDozeParameters, mStatusBarStateController,
- mConfigurationController, mKeyguardBypassController);
+ mConfigurationController, mKeyguardBypassController) {
+ @Override
+ protected boolean isDebuggable() {
+ return false;
+ }
+ };
mStatusBarWindowController.add(mStatusBarView, 100 /* height */);
}
@Test
public void testSetDozing_hidesSystemOverlays() {
mStatusBarWindowController.setDozing(true);
- ArgumentCaptor<WindowManager.LayoutParams> captor =
- ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
- verify(mWindowManager).updateViewLayout(any(), captor.capture());
- int flag = captor.getValue().privateFlags
+ verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+ int flag = mLayoutParameters.getValue().privateFlags
& WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
assertThat(flag).isNotEqualTo(0);
reset(mWindowManager);
mStatusBarWindowController.setDozing(false);
- verify(mWindowManager).updateViewLayout(any(), captor.capture());
- flag = captor.getValue().privateFlags
+ verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+ flag = mLayoutParameters.getValue().privateFlags
& WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
assertThat(flag).isEqualTo(0);
}
@@ -114,4 +122,20 @@ public class StatusBarWindowControllerTest extends SysuiTestCase {
mConfigurationController, mKeyguardBypassController);
mStatusBarWindowController.setForcePluginOpen(true);
}
+
+ @Test
+ public void setKeyguardShowing_enablesSecureFlag() {
+ mStatusBarWindowController.setBouncerShowing(true);
+
+ verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+ assertThat((mLayoutParameters.getValue().flags & FLAG_SECURE) != 0).isTrue();
+ }
+
+ @Test
+ public void setKeyguardNotShowing_disablesSecureFlag() {
+ mStatusBarWindowController.setBouncerShowing(false);
+
+ verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
+ assertThat((mLayoutParameters.getValue().flags & FLAG_SECURE) == 0).isTrue();
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 9bad734cfcfb..379e3d0c71b2 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -673,7 +673,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
final List<AccessibilityServiceInfo> result = new ArrayList<>(serviceCount);
for (int i = 0; i < serviceCount; ++i) {
final AccessibilityServiceConnection service = services.get(i);
- if ((service.mFeedbackType & feedbackType) != 0) {
+ if ((service.mFeedbackType & feedbackType) != 0
+ || feedbackType == AccessibilityServiceInfo.FEEDBACK_ALL_MASK) {
result.add(service.getServiceInfo());
}
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 39866a72ab98..2fe14e36ec51 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1300,11 +1300,12 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
try {
// Ask ActivityManager to bind it. Notice that we are binding the service with the
// caller app instead of DevicePolicyManagerService.
- if(ActivityManager.getService().bindService(
+ if (ActivityManager.getService().bindService(
caller, activtiyToken, intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- connection, flags, mContext.getOpPackageName(),
- widget.provider.getUserId()) != 0) {
+ connection, flags & (Context.BIND_AUTO_CREATE
+ | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE),
+ mContext.getOpPackageName(), widget.provider.getUserId()) != 0) {
// Add it to the mapping of RemoteViewsService to appWidgetIds so that we
// can determine when we can call back to the RemoteViewsService later to
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index d7d457395798..c11a9b058562 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -39,7 +39,6 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageInfo;
-import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.net.NetworkPolicyManager;
import android.os.Binder;
@@ -310,20 +309,12 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
String callingPackage = component.getPackageName();
checkCanCallNotificationApi(callingPackage);
int userId = getCallingUserId();
- String packageTitle = BidiFormatter.getInstance().unicodeWrap(
- getPackageInfo(callingPackage, userId)
- .applicationInfo
- .loadSafeLabel(getContext().getPackageManager(),
- PackageItemInfo.DEFAULT_MAX_LABEL_SIZE_PX,
- PackageItemInfo.SAFE_LABEL_FLAG_TRIM
- | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE)
- .toString());
- long identity = Binder.clearCallingIdentity();
+ final long identity = Binder.clearCallingIdentity();
try {
return PendingIntent.getActivity(getContext(),
0 /* request code */,
NotificationAccessConfirmationActivityContract.launcherIntent(
- userId, component, packageTitle),
+ getContext(), userId, component),
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT
| PendingIntent.FLAG_CANCEL_CURRENT);
} finally {
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 386b49ebaa11..a8b7019a2dab 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -75,6 +75,7 @@ import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.EventLog;
import android.util.KeyValueListParser;
import android.util.Log;
import android.util.LongArrayQueue;
@@ -1761,7 +1762,11 @@ class AlarmManagerService extends SystemService {
+ " reached for uid: " + UserHandle.formatUid(callingUid)
+ ", callingPackage: " + callingPackage;
Slog.w(TAG, errorMsg);
- throw new IllegalStateException(errorMsg);
+ if (callingUid != Process.SYSTEM_UID) {
+ throw new IllegalStateException(errorMsg);
+ } else {
+ EventLog.writeEvent(0x534e4554, "234441463", -1, errorMsg);
+ }
}
setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
interval, operation, directReceiver, listenerTag, flags, true, workSource,
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index deff7ef7d39a..a252ba4452ea 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -117,6 +117,7 @@ import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.DataUnit;
+import android.util.EventLog;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -2848,7 +2849,21 @@ class StorageManagerService extends IStorageManager.Stub
try {
mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
} catch (Exception e) {
+ EventLog.writeEvent(0x534e4554, "224585613", -1, "");
Slog.wtf(TAG, e);
+ // Make sure to re-throw this exception; we must not ignore failure
+ // to prepare the user storage as it could indicate that encryption
+ // wasn't successfully set up.
+ //
+ // Very unfortunately, these errors need to be ignored for broken
+ // users that already existed on-disk from older Android versions.
+ UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class);
+ if (umInternal.shouldIgnorePrepareStorageErrors(userId)) {
+ Slog.wtf(TAG, "ignoring error preparing storage for existing user " + userId
+ + "; device may be insecure!");
+ return;
+ }
+ throw new RuntimeException(e);
}
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 755f95774b31..58978a55a32a 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -46,6 +46,7 @@ import android.app.admin.DeviceAdminInfo;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.BroadcastReceiver;
+import android.content.ClipData;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -86,6 +87,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
+import android.util.EventLog;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -1800,6 +1802,14 @@ public class AccountManagerService
if (account == null) {
return false;
}
+ if (account.name != null && account.name.length() > 200) {
+ Log.w(TAG, "Account cannot be added - Name longer than 200 chars");
+ return false;
+ }
+ if (account.type != null && account.type.length() > 200) {
+ Log.w(TAG, "Account cannot be added - Name longer than 200 chars");
+ return false;
+ }
if (!isLocalUnlockedUser(accounts.userId)) {
Log.w(TAG, "Account " + account.toSafeString() + " cannot be added - user "
+ accounts.userId + " is locked. callingUid=" + callingUid);
@@ -1993,6 +2003,10 @@ public class AccountManagerService
+ ", pid " + Binder.getCallingPid());
}
if (accountToRename == null) throw new IllegalArgumentException("account is null");
+ if (newName != null && newName.length() > 200) {
+ Log.e(TAG, "renameAccount failed - account name longer than 200");
+ throw new IllegalArgumentException("account name longer than 200");
+ }
int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(accountToRename.type, callingUid, userId)) {
String msg = String.format(
@@ -3014,7 +3028,7 @@ public class AccountManagerService
*/
if (!checkKeyIntent(
Binder.getCallingUid(),
- intent)) {
+ result)) {
onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"invalid intent in bundle returned");
return;
@@ -3424,7 +3438,7 @@ public class AccountManagerService
&& (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
if (!checkKeyIntent(
Binder.getCallingUid(),
- intent)) {
+ result)) {
onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"invalid intent in bundle returned");
return;
@@ -4781,7 +4795,18 @@ public class AccountManagerService
* into launching arbitrary intents on the device via by tricking to click authenticator
* supplied entries in the system Settings app.
*/
- protected boolean checkKeyIntent(int authUid, Intent intent) {
+ protected boolean checkKeyIntent(int authUid, Bundle bundle) {
+ if (!checkKeyIntentParceledCorrectly(bundle)) {
+ EventLog.writeEvent(0x534e4554, "250588548", authUid, "");
+ return false;
+ }
+
+ Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
+ // Explicitly set an empty ClipData to ensure that we don't offer to
+ // promote any Uris contained inside for granting purposes
+ if (intent.getClipData() == null) {
+ intent.setClipData(ClipData.newPlainText(null, null));
+ }
intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
@@ -4813,6 +4838,25 @@ public class AccountManagerService
}
}
+ /**
+ * Simulate the client side's deserialization of KEY_INTENT value, to make sure they don't
+ * violate our security policy.
+ *
+ * In particular we want to make sure the Authenticator doesn't trick users
+ * into launching arbitrary intents on the device via exploiting any other Parcel read/write
+ * mismatch problems.
+ */
+ private boolean checkKeyIntentParceledCorrectly(Bundle bundle) {
+ Parcel p = Parcel.obtain();
+ p.writeBundle(bundle);
+ p.setDataPosition(0);
+ Bundle simulateBundle = p.readBundle();
+ p.recycle();
+ Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
+ Intent simulateIntent = simulateBundle.getParcelable(AccountManager.KEY_INTENT);
+ return (intent.filterEquals(simulateIntent));
+ }
+
private boolean isExportedSystemActivity(ActivityInfo activityInfo) {
String className = activityInfo.name;
return "android".equals(activityInfo.packageName) &&
@@ -4959,7 +5003,7 @@ public class AccountManagerService
&& (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
if (!checkKeyIntent(
Binder.getCallingUid(),
- intent)) {
+ result)) {
onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
"invalid intent in bundle returned");
return;
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index f6ce2dc68b99..621c9c71df58 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -37,6 +37,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Log;
+import android.webkit.URLUtil;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.TrafficStatsConstants;
@@ -215,8 +216,22 @@ public class PacManager {
* @throws IOException if the URL is malformed, or the PAC file is too big.
*/
private static String get(Uri pacUri) throws IOException {
- URL url = new URL(pacUri.toString());
- URLConnection urlConnection = url.openConnection(java.net.Proxy.NO_PROXY);
+ if (!URLUtil.isValidUrl(pacUri.toString())) {
+ throw new IOException("Malformed URL:" + pacUri);
+ }
+
+ final URL url = new URL(pacUri.toString());
+ URLConnection urlConnection;
+ try {
+ urlConnection = url.openConnection(java.net.Proxy.NO_PROXY);
+ // Catch the possible exceptions and rethrow as IOException to not to crash the system
+ // for illegal input.
+ } catch (IllegalArgumentException e) {
+ throw new IOException("Incorrect proxy type for " + pacUri);
+ } catch (UnsupportedOperationException e) {
+ throw new IOException("Unsupported URL connection type for " + pacUri);
+ }
+
long contentLength = -1;
try {
contentLength = Long.parseLong(urlConnection.getHeaderField("Content-Length"));
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 63302705b36f..d3ddc805d2ae 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -100,6 +100,7 @@ import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.view.ContextThemeWrapper;
import android.view.DisplayInfo;
import android.view.IWindowManager;
@@ -303,6 +304,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
final InputMethodSettings mSettings;
final SettingsObserver mSettingsObserver;
final IWindowManager mIWindowManager;
+ private final SparseBooleanArray mLoggedDeniedGetInputMethodWindowVisibleHeightForUid =
+ new SparseBooleanArray(0);
final WindowManagerInternal mWindowManagerInternal;
private final DisplayManagerInternal mDisplayManagerInternal;
final HandlerCaller mCaller;
@@ -1219,6 +1222,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
clearPackageChangeState();
}
+ @Override
+ public void onUidRemoved(int uid) {
+ synchronized (mMethodMap) {
+ mLoggedDeniedGetInputMethodWindowVisibleHeightForUid.delete(uid);
+ }
+ }
+
private void clearPackageChangeState() {
// No need to lock them because we access these fields only on getRegisteredHandler().
mChangedPackages.clear();
@@ -1484,7 +1494,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
Intent intent = new Intent(ACTION_SHOW_INPUT_METHOD_PICKER)
.setPackage(mContext.getPackageName());
- mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+ mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent,
+ PendingIntent.FLAG_IMMUTABLE);
mShowOngoingImeSwitcherForPhones = false;
@@ -2176,7 +2187,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mCurIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
com.android.internal.R.string.input_method_binding_label);
mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
- mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
+ mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS),
+ PendingIntent.FLAG_IMMUTABLE));
if (bindCurrentInputMethodServiceLocked(mCurIntent, this, IME_CONNECTION_BIND_FLAGS)) {
mLastBindTime = SystemClock.uptimeMillis();
@@ -2754,20 +2766,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
final long ident = Binder.clearCallingIdentity();
try {
- if (mCurClient == null || client == null
- || mCurClient.client.asBinder() != client.asBinder()) {
- // We need to check if this is the current client with
- // focus in the window manager, to allow this call to
- // be made before input is started in it.
- final ClientState cs = mClients.get(client.asBinder());
- if (cs == null) {
- throw new IllegalArgumentException("unknown client " + client.asBinder());
- }
- if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
- cs.selfReportedDisplayId)) {
- Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
- return false;
- }
+ if (!canInteractWithImeLocked(uid, client, "showSoftInput")) {
+ return false;
}
if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
return showCurrentInputLocked(flags, resultReceiver);
@@ -3462,9 +3462,46 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
* @return {@link WindowManagerInternal#getInputMethodWindowVisibleHeight()}
*/
@Override
- public int getInputMethodWindowVisibleHeight() {
- // TODO(yukawa): Should we verify the display ID?
- return mWindowManagerInternal.getInputMethodWindowVisibleHeight(mCurTokenDisplayId);
+ @Deprecated
+ public int getInputMethodWindowVisibleHeight(@NonNull IInputMethodClient client) {
+ int callingUid = Binder.getCallingUid();
+ return Binder.withCleanCallingIdentity(() -> {
+ final int curTokenDisplayId;
+ synchronized (mMethodMap) {
+ if (!canInteractWithImeLocked(callingUid, client,
+ "getInputMethodWindowVisibleHeight")) {
+ if (!mLoggedDeniedGetInputMethodWindowVisibleHeightForUid.get(callingUid)) {
+ EventLog.writeEvent(0x534e4554, "204906124", callingUid, "");
+ mLoggedDeniedGetInputMethodWindowVisibleHeightForUid.put(callingUid, true);
+ }
+ return 0;
+ }
+ // This should probably use the caller's display id, but because this is unsupported
+ // and maintained only for compatibility, there's no point in fixing it.
+ curTokenDisplayId = mCurTokenDisplayId;
+ }
+ return mWindowManagerInternal.getInputMethodWindowVisibleHeight(curTokenDisplayId);
+ });
+ }
+
+ private boolean canInteractWithImeLocked(int callingUid, IInputMethodClient client,
+ String method) {
+ if (mCurClient == null || client == null
+ || mCurClient.client.asBinder() != client.asBinder()) {
+ // We need to check if this is the current client with
+ // focus in the window manager, to allow this call to
+ // be made before input is started in it.
+ final ClientState cs = mClients.get(client.asBinder());
+ if (cs == null) {
+ throw new IllegalArgumentException("unknown client " + client.asBinder());
+ }
+ if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
+ cs.selfReportedDisplayId)) {
+ Slog.w(TAG, "Ignoring " + method + " of uid " + callingUid + ": " + client);
+ return false;
+ }
+ }
+ return true;
}
@Override
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 3dd730471dca..bd4ea08d55d2 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -1694,7 +1694,7 @@ public final class MultiClientInputMethodManagerService {
@BinderThread
@Override
- public int getInputMethodWindowVisibleHeight() {
+ public int getInputMethodWindowVisibleHeight(IInputMethodClient client) {
reportNotSupported();
return 0;
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index a93a884c841f..d881aad3e22b 100644..100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2054,7 +2054,7 @@ public class NotificationManagerService extends SystemService {
}
}
- private void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
+ void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
boolean fromApp, boolean fromListener) {
Preconditions.checkNotNull(group);
Preconditions.checkNotNull(pkg);
@@ -2835,7 +2835,8 @@ public class NotificationManagerService extends SystemService {
final int callingUid = Binder.getCallingUid();
NotificationChannelGroup groupToDelete =
- mPreferencesHelper.getNotificationChannelGroup(groupId, pkg, callingUid);
+ mPreferencesHelper.getNotificationChannelGroupWithChannels(
+ pkg, callingUid, groupId, false);
if (groupToDelete != null) {
// Preflight for allowability
final int userId = UserHandle.getUserId(callingUid);
@@ -3570,7 +3571,7 @@ public class NotificationManagerService extends SystemService {
}
@Override
- public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
+ public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String pkg) {
Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null");
Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null");
if (automaticZenRule.getOwner() == null
@@ -3579,6 +3580,7 @@ public class NotificationManagerService extends SystemService {
"Rule must have a conditionproviderservice and/or configuration activity");
}
Preconditions.checkNotNull(automaticZenRule.getConditionId(), "ConditionId is null");
+ checkCallerIsSameApp(pkg);
if (automaticZenRule.getZenPolicy() != null
&& automaticZenRule.getInterruptionFilter() != INTERRUPTION_FILTER_PRIORITY) {
throw new IllegalArgumentException("ZenPolicy is only applicable to "
@@ -3586,7 +3588,16 @@ public class NotificationManagerService extends SystemService {
}
enforcePolicyAccess(Binder.getCallingUid(), "addAutomaticZenRule");
- return mZenModeHelper.addAutomaticZenRule(automaticZenRule,
+ // If the caller is system, take the package name from the rule's owner rather than
+ // from the caller's package.
+ String rulePkg = pkg;
+ if (isCallingUidSystem()) {
+ if (automaticZenRule.getOwner() != null) {
+ rulePkg = automaticZenRule.getOwner().getPackageName();
+ }
+ }
+
+ return mZenModeHelper.addAutomaticZenRule(rulePkg, automaticZenRule,
"addAutomaticZenRule");
}
@@ -4835,8 +4846,11 @@ public class NotificationManagerService extends SystemService {
try {
fixNotification(notification, pkg, userId);
- } catch (NameNotFoundException e) {
- Slog.e(TAG, "Cannot create a context for sending app", e);
+ } catch (Exception e) {
+ if (notification.isForegroundService()) {
+ throw new SecurityException("Invalid FGS notification", e);
+ }
+ Slog.e(TAG, "Cannot fix notification", e);
return;
}
@@ -5350,13 +5364,17 @@ public class NotificationManagerService extends SystemService {
@GuardedBy("mNotificationLock")
void snoozeLocked(NotificationRecord r) {
+ final List<NotificationRecord> recordsToSnooze = new ArrayList<>();
if (r.sbn.isGroup()) {
- final List<NotificationRecord> groupNotifications = findGroupNotificationsLocked(
- r.sbn.getPackageName(), r.sbn.getGroupKey(), r.sbn.getUserId());
+ final List<NotificationRecord> groupNotifications =
+ findGroupNotificationsLocked(r.sbn.getPackageName(),
+ r.sbn.getGroupKey(), r.sbn.getUserId());
if (r.getNotification().isGroupSummary()) {
// snooze summary and all children
for (int i = 0; i < groupNotifications.size(); i++) {
- snoozeNotificationLocked(groupNotifications.get(i));
+ if (!mKey.equals(groupNotifications.get(i).getKey())) {
+ recordsToSnooze.add(groupNotifications.get(i));
+ }
}
} else {
// if there is a valid summary for this group, and we are snoozing the only
@@ -5367,7 +5385,9 @@ public class NotificationManagerService extends SystemService {
} else {
// snooze summary and the one child
for (int i = 0; i < groupNotifications.size(); i++) {
- snoozeNotificationLocked(groupNotifications.get(i));
+ if (!mKey.equals(groupNotifications.get(i).getKey())) {
+ recordsToSnooze.add(groupNotifications.get(i));
+ }
}
}
} else {
@@ -5378,6 +5398,17 @@ public class NotificationManagerService extends SystemService {
// just snooze the one notification
snoozeNotificationLocked(r);
}
+
+ // snooze the notification
+ recordsToSnooze.add(r);
+
+ if (mSnoozeHelper.canSnooze(recordsToSnooze.size())) {
+ for (int i = 0; i < recordsToSnooze.size(); i++) {
+ snoozeNotificationLocked(recordsToSnooze.get(i));
+ }
+ } else {
+ Log.w(TAG, "Cannot snooze " + r.getKey() + ": too many snoozed notifications");
+ }
}
@GuardedBy("mNotificationLock")
@@ -5951,7 +5982,8 @@ public class NotificationManagerService extends SystemService {
boolean sentAccessibilityEvent = false;
// If the notification will appear in the status bar, it should send an accessibility
// event
- if (!record.isUpdate && record.getImportance() > IMPORTANCE_MIN) {
+ if (!record.isUpdate && record.getImportance() > IMPORTANCE_MIN
+ && isNotificationForCurrentUser(record)) {
sendAccessibilityEvent(notification, record.sbn.getPackageName());
sentAccessibilityEvent = true;
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 4835c97f0bb7..4795d3d6ead1 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -601,6 +601,9 @@ public class PreferencesHelper implements RankingConfig {
if (r == null) {
throw new IllegalArgumentException("Invalid package");
}
+ if (fromTargetApp) {
+ group.setBlocked(false);
+ }
final NotificationChannelGroup oldGroup = r.groups.get(group.getId());
if (!group.equals(oldGroup)) {
// will log for new entries as well as name/description changes
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index 037cc6066518..ba1f1e91ec45 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -57,6 +57,8 @@ import java.util.Set;
* NotificationManagerService helper for handling snoozed notifications.
*/
public class SnoozeHelper {
+ static final int CONCURRENT_SNOOZE_LIMIT = 500;
+
private static final String TAG = "SnoozeHelper";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final String INDENT = " ";
@@ -91,6 +93,13 @@ public class SnoozeHelper {
mUserProfiles = userProfiles;
}
+ protected boolean canSnooze(int numberToSnooze) {
+ if ((mPackages.size() + numberToSnooze) > CONCURRENT_SNOOZE_LIMIT) {
+ return false;
+ }
+ return true;
+ }
+
protected boolean isSnoozed(int userId, String pkg, String key) {
return mSnoozedNotifications.containsKey(userId)
&& mSnoozedNotifications.get(userId).containsKey(pkg)
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index ebc41916d034..7970ad547c9e 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -92,6 +92,7 @@ public class ZenModeHelper {
// The amount of time rules instances can exist without their owning app being installed.
private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72;
+ static final int RULE_LIMIT_PER_PACKAGE = 100;
private final Context mContext;
private final H mHandler;
@@ -288,8 +289,9 @@ public class ZenModeHelper {
return null;
}
- public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
- if (!isSystemRule(automaticZenRule)) {
+ public String addAutomaticZenRule(String pkg, AutomaticZenRule automaticZenRule,
+ String reason) {
+ if (!ZenModeConfig.SYSTEM_AUTHORITY.equals(pkg)) {
PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
if (component == null) {
component = getActivityInfo(automaticZenRule.getConfigurationActivity());
@@ -305,10 +307,11 @@ public class ZenModeHelper {
int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner())
+ getCurrentInstanceCount(automaticZenRule.getConfigurationActivity())
+ 1;
- if (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount) {
+ int newPackageRuleCount = getPackageRuleCount(pkg) + 1;
+ if (newPackageRuleCount > RULE_LIMIT_PER_PACKAGE
+ || (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount)) {
throw new IllegalArgumentException("Rule instance limit exceeded");
}
-
}
ZenModeConfig newConfig;
@@ -321,7 +324,7 @@ public class ZenModeHelper {
}
newConfig = mConfig.copy();
ZenRule rule = new ZenRule();
- populateZenRule(automaticZenRule, rule, true);
+ populateZenRule(pkg, automaticZenRule, rule, true);
newConfig.automaticRules.put(rule.id, rule);
if (setConfigLocked(newConfig, reason, rule.component, true)) {
return rule.id;
@@ -351,7 +354,7 @@ public class ZenModeHelper {
"Cannot update rules not owned by your condition provider");
}
}
- populateZenRule(automaticZenRule, rule, false);
+ populateZenRule(rule.pkg, automaticZenRule, rule, false);
return setConfigLocked(newConfig, reason, rule.component, true);
}
}
@@ -381,7 +384,14 @@ public class ZenModeHelper {
newConfig = mConfig.copy();
for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
- if (rule.pkg.equals(packageName) && canManageAutomaticZenRule(rule)) {
+ String pkg = rule.pkg != null
+ ? rule.pkg
+ : (rule.component != null)
+ ? rule.component.getPackageName()
+ : (rule.configurationActivity != null)
+ ? rule.configurationActivity.getPackageName()
+ : null;
+ if (Objects.equals(pkg, packageName) && canManageAutomaticZenRule(rule)) {
newConfig.automaticRules.removeAt(i);
}
}
@@ -464,6 +474,23 @@ public class ZenModeHelper {
return count;
}
+ // Equivalent method to getCurrentInstanceCount, but for all rules associated with a specific
+ // package rather than a condition provider service or activity.
+ private int getPackageRuleCount(String pkg) {
+ if (pkg == null) {
+ return 0;
+ }
+ int count = 0;
+ synchronized (mConfig) {
+ for (ZenRule rule : mConfig.automaticRules.values()) {
+ if (pkg.equals(rule.pkg)) {
+ count++;
+ }
+ }
+ }
+ return count;
+ }
+
public boolean canManageAutomaticZenRule(ZenRule rule) {
final int callingUid = Binder.getCallingUid();
if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
@@ -505,11 +532,6 @@ public class ZenModeHelper {
}
}
- private boolean isSystemRule(AutomaticZenRule rule) {
- return rule.getOwner() != null
- && ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
- }
-
private ServiceInfo getServiceInfo(ComponentName owner) {
Intent queryIntent = new Intent();
queryIntent.setComponent(owner);
@@ -545,15 +567,14 @@ public class ZenModeHelper {
return null;
}
- private void populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew) {
+ private void populateZenRule(String pkg, AutomaticZenRule automaticZenRule, ZenRule rule,
+ boolean isNew) {
if (isNew) {
rule.id = ZenModeConfig.newRuleId();
rule.creationTime = System.currentTimeMillis();
rule.component = automaticZenRule.getOwner();
rule.configurationActivity = automaticZenRule.getConfigurationActivity();
- rule.pkg = (rule.component != null)
- ? rule.component.getPackageName()
- : rule.configurationActivity.getPackageName();
+ rule.pkg = pkg;
}
if (rule.enabled != automaticZenRule.isEnabled()) {
@@ -570,10 +591,13 @@ public class ZenModeHelper {
}
protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
- return new AutomaticZenRule(rule.name, rule.component, rule.configurationActivity,
+ AutomaticZenRule azr = new AutomaticZenRule(rule.name, rule.component,
+ rule.configurationActivity,
rule.conditionId, rule.zenPolicy,
NotificationManager.zenModeToInterruptionFilter(rule.zenMode),
rule.enabled, rule.creationTime);
+ azr.setPackageName(rule.pkg);
+ return azr;
}
public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5d4c7d57fdff..d1455bf6a00e 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -91,6 +91,7 @@ import android.system.OsConstants;
import android.system.StructStat;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.EventLog;
import android.util.ExceptionUtils;
import android.util.MathUtils;
import android.util.Slog;
@@ -1708,6 +1709,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
resolveInheritedFile(baseDexMetadataFile);
}
baseApk = existingBase;
+ } else if ((params.installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
+ EventLog.writeEvent(0x534e4554, "219044664");
+
+ // Installing base.apk. Make sure the app is restarted.
+ params.setDontKillApp(false);
}
// Inherit splits if not overridden
@@ -2127,6 +2133,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
@Override
+ public int getInstallFlags() {
+ return params.installFlags;
+ }
+
+ @Override
public int[] getChildSessionIds() {
final int[] childSessionIds = mChildSessionIds.copyKeys();
if (childSessionIds != null) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7f6f729da541..a856697a0e10 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -18390,6 +18390,20 @@ public class PackageManagerService extends IPackageManager.Stub
final String packageName = versionedPackage.getPackageName();
final long versionCode = versionedPackage.getLongVersionCode();
+
+ if (mProtectedPackages.isPackageStateProtected(userId, packageName)) {
+ mHandler.post(() -> {
+ try {
+ Slog.w(TAG, "Attempted to delete protected package: " + packageName);
+ observer.onPackageDeleted(packageName,
+ PackageManager.DELETE_FAILED_INTERNAL_ERROR, null);
+ } catch (RemoteException re) {
+ }
+ });
+ return;
+ }
+
+
final String internalPackageName;
synchronized (mPackages) {
// Normalize package name to handle renamed packages and static libs
@@ -18729,6 +18743,17 @@ public class PackageManagerService extends IPackageManager.Stub
return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
}
+ if (isSystemApp(uninstalledPs)
+ && (deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0) {
+ UserInfo userInfo = sUserManager.getUserInfo(userId);
+ if (userInfo == null || !userInfo.isAdmin()) {
+ Slog.w(TAG, "Not removing package " + packageName
+ + " as only admin user may downgrade system apps");
+ EventLog.writeEvent(0x534e4554, "170646036", -1, packageName);
+ return PackageManager.DELETE_FAILED_USER_RESTRICTED;
+ }
+ }
+
disabledSystemPs = mSettings.getDisabledSystemPkgLPr(packageName);
// Save the enabled state before we delete the package. When deleting a stub
// application we always set the enabled state to 'disabled'.
@@ -21520,6 +21545,9 @@ public class PackageManagerService extends IPackageManager.Stub
} else {
Slog.w(TAG, "Failed setComponentEnabledSetting: component class "
+ className + " does not exist in " + packageName);
+ // Safetynet logging for b/240936919
+ EventLog.writeEvent(0x534e4554, "240936919", callingUid);
+ return;
}
}
switch (newState) {
@@ -25246,6 +25274,11 @@ public class PackageManagerService extends IPackageManager.Stub
public void userRemovedForTest() {
mBlockDeleteOnUserRemoveForTest.open();
}
+
+ @Override
+ public int getInstalledSdkVersion(PackageParser.Package pkg) {
+ return PackageManagerService.this.getSettingsVersionForPackage(pkg).sdkVersion;
+ }
}
@GuardedBy("mPackages")
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 06c71baade42..c6bc7576147f 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -1629,11 +1629,15 @@ class ShortcutPackage extends ShortcutPackageItem {
continue;
case TAG_SHORTCUT:
- final ShortcutInfo si = parseShortcut(parser, packageName,
- shortcutUser.getUserId(), fromBackup);
-
- // Don't use addShortcut(), we don't need to save the icon.
- ret.mShortcuts.put(si.getId(), si);
+ try {
+ final ShortcutInfo si = parseShortcut(parser, packageName,
+ shortcutUser.getUserId(), fromBackup);
+ // Don't use addShortcut(), we don't need to save the icon.
+ ret.mShortcuts.put(si.getId(), si);
+ } catch (Exception e) {
+ // b/246540168 malformed shortcuts should be ignored
+ Slog.e(TAG, "Failed parsing shortcut.", e);
+ }
continue;
case TAG_SHARE_TARGET:
ret.mShareTargets.add(ShareTargetInfo.loadFromXml(parser));
diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java
index 045a295da965..95482d7c7f1a 100644
--- a/services/core/java/com/android/server/pm/UserDataPreparer.java
+++ b/services/core/java/com/android/server/pm/UserDataPreparer.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.pm.UserInfo;
import android.os.Environment;
import android.os.FileUtils;
+import android.os.RecoverySystem;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.os.SystemProperties;
@@ -115,6 +116,16 @@ class UserDataPreparer {
// Try one last time; if we fail again we're really in trouble
prepareUserDataLI(volumeUuid, userId, userSerial,
flags | StorageManager.FLAG_STORAGE_DE, false);
+ } else {
+ try {
+ Log.wtf(TAG, "prepareUserData failed for user " + userId, e);
+ if (userId == UserHandle.USER_SYSTEM) {
+ RecoverySystem.rebootPromptAndWipeUserData(mContext,
+ "prepareUserData failed for system user");
+ }
+ } catch (IOException e2) {
+ throw new RuntimeException("error rebooting into recovery", e2);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 29543e36959a..6880918df5b4 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -80,6 +80,7 @@ import android.security.GateKeeper;
import android.service.gatekeeper.IGateKeeperService;
import android.stats.devicepolicy.DevicePolicyEnums;
import android.util.AtomicFile;
+import android.util.EventLog;
import android.util.IntArray;
import android.util.Log;
import android.util.Slog;
@@ -184,6 +185,8 @@ public class UserManagerService extends IUserManager.Stub {
private static final String TAG_SEED_ACCOUNT_OPTIONS = "seedAccountOptions";
private static final String TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL =
"lastRequestQuietModeEnabledCall";
+ private static final String TAG_IGNORE_PREPARE_STORAGE_ERRORS =
+ "ignorePrepareStorageErrors";
private static final String ATTR_KEY = "key";
private static final String ATTR_VALUE_TYPE = "type";
private static final String ATTR_MULTIPLE = "m";
@@ -282,6 +285,14 @@ public class UserManagerService extends IUserManager.Stub {
private long mLastRequestQuietModeEnabledMillis;
+ /**
+ * {@code true} if the system should ignore errors when preparing the
+ * storage directories for this user. This is {@code false} for all new
+ * users; it will only be {@code true} for users that already existed
+ * on-disk from an older version of Android.
+ */
+ private boolean mIgnorePrepareStorageErrors;
+
void setLastRequestQuietModeEnabledMillis(long millis) {
mLastRequestQuietModeEnabledMillis = millis;
}
@@ -290,6 +301,14 @@ public class UserManagerService extends IUserManager.Stub {
return mLastRequestQuietModeEnabledMillis;
}
+ boolean getIgnorePrepareStorageErrors() {
+ return mIgnorePrepareStorageErrors;
+ }
+
+ void setIgnorePrepareStorageErrors() {
+ mIgnorePrepareStorageErrors = true;
+ }
+
void clearSeedAccountData() {
seedAccountName = null;
seedAccountType = null;
@@ -2438,6 +2457,10 @@ public class UserManagerService extends IUserManager.Stub {
serializer.endTag(/* namespace */ null, TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL);
}
+ serializer.startTag(/* namespace */ null, TAG_IGNORE_PREPARE_STORAGE_ERRORS);
+ serializer.text(String.valueOf(userData.getIgnorePrepareStorageErrors()));
+ serializer.endTag(/* namespace */ null, TAG_IGNORE_PREPARE_STORAGE_ERRORS);
+
serializer.endTag(null, TAG_USER);
serializer.endDocument();
@@ -2547,6 +2570,7 @@ public class UserManagerService extends IUserManager.Stub {
Bundle baseRestrictions = null;
Bundle localRestrictions = null;
Bundle globalRestrictions = null;
+ boolean ignorePrepareStorageErrors = true; // default is true for old users
XmlPullParser parser = Xml.newPullParser();
parser.setInput(is, StandardCharsets.UTF_8.name());
@@ -2629,6 +2653,11 @@ public class UserManagerService extends IUserManager.Stub {
if (type == XmlPullParser.TEXT) {
lastRequestQuietModeEnabledTimestamp = Long.parseLong(parser.getText());
}
+ } else if (TAG_IGNORE_PREPARE_STORAGE_ERRORS.equals(tag)) {
+ type = parser.next();
+ if (type == XmlPullParser.TEXT) {
+ ignorePrepareStorageErrors = Boolean.parseBoolean(parser.getText());
+ }
}
}
}
@@ -2655,6 +2684,9 @@ public class UserManagerService extends IUserManager.Stub {
userData.persistSeedData = persistSeedData;
userData.seedAccountOptions = seedAccountOptions;
userData.setLastRequestQuietModeEnabledMillis(lastRequestQuietModeEnabledTimestamp);
+ if (ignorePrepareStorageErrors) {
+ userData.setIgnorePrepareStorageErrors();
+ }
synchronized (mRestrictionsLock) {
if (baseRestrictions != null) {
@@ -3393,6 +3425,13 @@ public class UserManagerService extends IUserManager.Stub {
public void setApplicationRestrictions(String packageName, Bundle restrictions,
int userId) {
checkSystemOrRoot("set application restrictions");
+ String validationResult = validateName(packageName);
+ if (validationResult != null) {
+ if (packageName.contains("../")) {
+ EventLog.writeEvent(0x534e4554, "239701237", -1, "");
+ }
+ throw new IllegalArgumentException("Invalid package name: " + validationResult);
+ }
if (restrictions != null) {
restrictions.setDefusable(true);
}
@@ -3412,6 +3451,39 @@ public class UserManagerService extends IUserManager.Stub {
mContext.sendBroadcastAsUser(changeIntent, UserHandle.of(userId));
}
+ /**
+ * Check if the given name is valid.
+ *
+ * Note: the logic is taken from FrameworkParsingPackageUtils in master, edited to remove
+ * unnecessary parts. Copied here for a security fix.
+ *
+ * @param name The name to check.
+ * @return null if it's valid, error message if not
+ */
+ @VisibleForTesting
+ static String validateName(String name) {
+ final int n = name.length();
+ boolean front = true;
+ for (int i = 0; i < n; i++) {
+ final char c = name.charAt(i);
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+ front = false;
+ continue;
+ }
+ if (!front) {
+ if ((c >= '0' && c <= '9') || c == '_') {
+ continue;
+ }
+ if (c == '.') {
+ front = true;
+ continue;
+ }
+ }
+ return "bad character '" + c + "'";
+ }
+ return null;
+ }
+
private int getUidForPackage(String packageName) {
long ident = Binder.clearCallingIdentity();
try {
@@ -4047,6 +4119,9 @@ public class UserManagerService extends IUserManager.Stub {
pw.println();
}
}
+
+ pw.println(" Ignore errors preparing storage: "
+ + userData.getIgnorePrepareStorageErrors());
}
}
pw.println();
@@ -4394,6 +4469,14 @@ public class UserManagerService extends IUserManager.Stub {
return UserRestrictionsUtils.isSettingRestrictedForUser(mContext, setting, userId,
value, callingUid);
}
+
+ @Override
+ public boolean shouldIgnorePrepareStorageErrors(int userId) {
+ synchronized (mUsersLock) {
+ UserData userData = mUsers.get(userId);
+ return userData != null && userData.getIgnorePrepareStorageErrors();
+ }
+ }
}
/* Remove all the users except of the system one. */
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 82f963e1df2a..42ed16268919 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1096,23 +1096,29 @@ public class PermissionManagerService {
// or has updated its target SDK and AR is no longer implicit to it.
// This is a compatibility workaround for apps when AR permission was
// split in Q.
- final List<PermissionManager.SplitPermissionInfo> permissionList =
- getSplitPermissions();
- int numSplitPerms = permissionList.size();
- for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
- PermissionManager.SplitPermissionInfo sp =
- permissionList.get(splitPermNum);
- String splitPermName = sp.getSplitPermission();
- if (sp.getNewPermissions().contains(permName)
- && origPermissions.hasInstallPermission(splitPermName)) {
- upgradedActivityRecognitionPermission = splitPermName;
- newImplicitPermissions.add(permName);
+ // b/210065877: Check that the installed version is pre Q to auto-grant in
+ // case of OS update
+ if (mPackageManagerInt.getInstalledSdkVersion(pkg)
+ < Build.VERSION_CODES.Q) {
+ final List<PermissionManager.SplitPermissionInfo> permissionList =
+ getSplitPermissions();
+ int numSplitPerms = permissionList.size();
+ for (int splitPermNum = 0; splitPermNum < numSplitPerms;
+ splitPermNum++) {
+ PermissionManager.SplitPermissionInfo sp =
+ permissionList.get(splitPermNum);
+ String splitPermName = sp.getSplitPermission();
+ if (sp.getNewPermissions().contains(permName)
+ && origPermissions.hasInstallPermission(splitPermName)) {
+ upgradedActivityRecognitionPermission = splitPermName;
+ newImplicitPermissions.add(permName);
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, permName + " is newly added for "
- + pkg.packageName);
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, permName + " is newly added for "
+ + pkg.packageName);
+ }
+ break;
}
- break;
}
}
}
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 5fd2ab87f410..b1728cde6f7e 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -237,6 +237,8 @@ public class SliceManagerService extends ISliceManager.Stub {
if (autoGrantPermissions != null && callingPkg != null) {
// Need to own the Uri to call in with permissions to grant.
enforceOwner(callingPkg, uri, userId);
+ // b/208232850: Needs to verify caller before granting slice access
+ verifyCaller(callingPkg);
for (String perm : autoGrantPermissions) {
if (mContext.checkPermission(perm, pid, uid) == PERMISSION_GRANTED) {
int providerUser = ContentProvider.getUserIdFromUri(uri, userId);
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 1a9b11cd62d5..52309cafe10b 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -2147,7 +2147,9 @@ class ActivityStack extends ConfigurationContainer {
boolean aboveTop = top != null;
final boolean stackShouldBeVisible = shouldBeVisible(starting);
boolean behindFullscreenActivity = !stackShouldBeVisible;
- boolean resumeNextActivity = isFocusable() && isInStackLocked(starting) == null;
+ boolean resumeNextActivity = isFocusable()
+ && getVisibility(starting) == STACK_VISIBILITY_VISIBLE
+ && isInStackLocked(starting) == null;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -4322,7 +4324,23 @@ class ActivityStack extends ConfigurationContainer {
parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
(destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
- parent.deliverNewIntentLocked(callingUid, destIntent, srec.packageName);
+ boolean abort;
+ try {
+ final int callingPid = srec.app != null ? srec.app.getPid() : 0;
+ abort = !mStackSupervisor.checkStartAnyActivityPermission(destIntent,
+ parent.info, null /* resultWho */, -1 /* requestCode */, callingPid,
+ callingUid, srec.info.packageName, false /* ignoreTargetSecurity */,
+ false /* launchingInTask */, srec.app, null /* resultRecord */,
+ null /* resultRootTask */);
+ } catch (SecurityException e) {
+ abort = true;
+ }
+ if (abort) {
+ android.util.EventLog.writeEvent(0x534e4554, "238605611", callingUid, "");
+ foundParentInTask = false;
+ } else {
+ parent.deliverNewIntentLocked(callingUid, destIntent, srec.packageName);
+ }
} else {
try {
ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 8a5f52f8c453..b9ff000a2129 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -25,6 +25,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PER
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
@@ -317,13 +318,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
/**
- * Returns true if the callingUid has any non-toast window currently visible to the user.
- * Also ignores TYPE_APPLICATION_STARTING, since those windows don't belong to apps.
+ * Returns {@code true} if the callingUid has any non-toast window currently visible to the
+ * user. Also ignores {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_STARTING},
+ * and{@link android.view.WindowManager.LayoutParams#TYPE_PRIVATE_PRESENTATION}, as they
+ * should not count towards the apps visibility
+ * @see WindowState#isNonToastOrStartingOrPrivatePresentation()
*/
boolean isAnyNonToastWindowVisibleForUid(int callingUid) {
return forAllWindows(w ->
w.getOwningUid() == callingUid && w.mAttrs.type != TYPE_TOAST
- && w.mAttrs.type != TYPE_APPLICATION_STARTING && w.isVisibleNow(),
+ && w.mAttrs.type != TYPE_APPLICATION_STARTING
+ && w.mAttrs.type != TYPE_PRIVATE_PRESENTATION && w.isVisibleNow(),
true /* traverseTopToBottom */);
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 3fd4e83b9494..361f66e3106a 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -110,6 +110,7 @@ import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Debug;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
@@ -204,6 +205,11 @@ class TaskRecord extends ConfigurationContainer {
static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
/**
+ * Used to identify if the activity that is installed from device's system image.
+ */
+ boolean mIsEffectivelySystemApp;
+
+ /**
* The factory used to create {@link TaskRecord}. This allows OEM subclass {@link TaskRecord}.
*/
private static TaskRecordFactory sTaskRecordFactory;
@@ -869,17 +875,25 @@ class TaskRecord extends ConfigurationContainer {
/** Sets the original intent, and the calling uid and package. */
void setIntent(ActivityRecord r) {
- mCallingUid = r.launchedFromUid;
- mCallingPackage = r.launchedFromPackage;
- setIntent(r.intent, r.info);
+ boolean updateIdentity = false;
+ if (this.intent == null) {
+ updateIdentity = true;
+ } else if (!mNeverRelinquishIdentity) {
+ updateIdentity = (effectiveUid == Process.SYSTEM_UID || mIsEffectivelySystemApp
+ || effectiveUid == r.info.applicationInfo.uid);
+ }
+ if (updateIdentity) {
+ mCallingUid = r.launchedFromUid;
+ mCallingPackage = r.launchedFromPackage;
+ setIntent(r.intent, r.info);
+ }
setLockTaskAuth(r);
}
/** Sets the original intent, _without_ updating the calling uid or package. */
private void setIntent(Intent _intent, ActivityInfo info) {
if (intent == null) {
- mNeverRelinquishIdentity =
- (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
+ mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
} else if (mNeverRelinquishIdentity) {
return;
}
@@ -892,6 +906,7 @@ class TaskRecord extends ConfigurationContainer {
rootAffinity = affinity;
}
effectiveUid = info.applicationInfo.uid;
+ mIsEffectivelySystemApp = info.applicationInfo.isSystemApp();
stringName = null;
if (info.targetActivity == null) {
@@ -1662,12 +1677,12 @@ class TaskRecord extends ConfigurationContainer {
// utility activities.
int activityNdx;
final int numActivities = mActivities.size();
- final boolean relinquish = numActivities != 0 &&
- (mActivities.get(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
- for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
- ++activityNdx) {
+ for (activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
final ActivityRecord r = mActivities.get(activityNdx);
- if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
+ if ((r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0
+ || (r.info.applicationInfo.uid != Process.SYSTEM_UID
+ && !r.info.applicationInfo.isSystemApp()
+ && r.info.applicationInfo.uid != effectiveUid)) {
// This will be the top activity for determining taskDescription. Pre-inc to
// overcome initial decrement below.
++activityNdx;
@@ -1739,15 +1754,27 @@ class TaskRecord extends ConfigurationContainer {
int findEffectiveRootIndex() {
int effectiveNdx = 0;
final int topActivityNdx = mActivities.size() - 1;
+ ActivityRecord root = null;
for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
final ActivityRecord r = mActivities.get(activityNdx);
if (r.finishing) {
continue;
}
- effectiveNdx = activityNdx;
- if ((r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
+
+ if (root == null) {
+ // Set this as the candidate root since it isn't finishing.
+ root = r;
+ effectiveNdx = activityNdx;
+ }
+ final int uid = root == r ? effectiveUid : r.info.applicationInfo.uid;
+ if ((root.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0
+ || (root.info.applicationInfo.uid != Process.SYSTEM_UID
+ && !root.info.applicationInfo.isSystemApp()
+ && root.info.applicationInfo.uid != uid)) {
break;
}
+ effectiveNdx = activityNdx;
+ root = r;
}
return effectiveNdx;
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 72fc18937ece..64e245d8dbaf 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -28,12 +28,14 @@ import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.os.Process;
import android.os.SystemClock;
+import android.os.UserManagerInternal;
import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.AtomicFile;
+import com.android.server.LocalServices;
import com.android.server.wm.nano.WindowManagerProtos.TaskSnapshotProto;
import java.io.File;
@@ -74,6 +76,7 @@ class TaskSnapshotPersister {
private final Object mLock = new Object();
private final DirectoryResolver mDirectoryResolver;
private final float mReducedScale;
+ private final UserManagerInternal mUserManagerInternal;
/**
* The list of ids of the tasks that have been persisted since {@link #removeObsoleteFiles} was
@@ -84,6 +87,9 @@ class TaskSnapshotPersister {
TaskSnapshotPersister(WindowManagerService service, DirectoryResolver resolver) {
mDirectoryResolver = resolver;
+
+ mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
+
if (service.mLowRamTaskSnapshotsAndRecents) {
// Use very low res snapshots if we are using Go version of recents.
mReducedScale = LOW_RAM_RECENTS_REDUCED_SCALE;
@@ -172,7 +178,7 @@ class TaskSnapshotPersister {
return;
}
}
- SystemClock.sleep(100);
+ SystemClock.sleep(DELAY_MS);
}
}
@@ -218,7 +224,7 @@ class TaskSnapshotPersister {
private boolean createDirectory(int userId) {
final File dir = getDirectory(userId);
- return dir.exists() || dir.mkdirs();
+ return dir.exists() || dir.mkdir();
}
private void deleteSnapshot(int taskId, int userId) {
@@ -243,18 +249,26 @@ class TaskSnapshotPersister {
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
while (true) {
WriteQueueItem next;
+ boolean isReadyToWrite = false;
synchronized (mLock) {
if (mPaused) {
next = null;
} else {
next = mWriteQueue.poll();
if (next != null) {
- next.onDequeuedLocked();
+ if (next.isReady()) {
+ isReadyToWrite = true;
+ next.onDequeuedLocked();
+ } else {
+ mWriteQueue.addLast(next);
+ }
}
}
}
if (next != null) {
- next.write();
+ if (isReadyToWrite) {
+ next.write();
+ }
SystemClock.sleep(DELAY_MS);
}
synchronized (mLock) {
@@ -274,6 +288,13 @@ class TaskSnapshotPersister {
};
private abstract class WriteQueueItem {
+ /**
+ * @return {@code true} if item is ready to have {@link WriteQueueItem#write} called
+ */
+ boolean isReady() {
+ return true;
+ }
+
abstract void write();
/**
@@ -313,6 +334,11 @@ class TaskSnapshotPersister {
}
@Override
+ boolean isReady() {
+ return mUserManagerInternal.isUserUnlocked(mUserId);
+ }
+
+ @Override
void write() {
if (!createDirectory(mUserId)) {
Slog.e(TAG, "Unable to create snapshot directory for user dir="
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index cfa99445f45f..4eec7ef7d625 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -15,7 +15,9 @@
*/
package com.android.server.devicepolicy;
+import android.accounts.Account;
import android.app.admin.IDevicePolicyManager;
+import android.os.UserHandle;
import com.android.server.SystemService;
@@ -56,4 +58,9 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub {
public void clearSystemUpdatePolicyFreezePeriodRecord() {
}
+
+ public void finalizeWorkProfileProvisioning(
+ UserHandle managedProfileUser, Account migratedAccount) {
+
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index c3749c3b0a92..70a1529645e9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -21,6 +21,7 @@ import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
+import static android.app.admin.DevicePolicyManager.ACTION_MANAGED_PROFILE_PROVISIONED;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
import static android.app.admin.DevicePolicyManager.CODE_ACCOUNTS_NOT_EMPTY;
import static android.app.admin.DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED;
@@ -48,6 +49,7 @@ import static android.app.admin.DevicePolicyManager.DELEGATION_KEEP_UNINSTALLED_
import static android.app.admin.DevicePolicyManager.DELEGATION_NETWORK_LOGGING;
import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO;
import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI;
import static android.app.admin.DevicePolicyManager.ID_TYPE_MEID;
@@ -9622,6 +9624,37 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
+ public void finalizeWorkProfileProvisioning(UserHandle managedProfileUser,
+ Account migratedAccount) {
+ if (mContext.checkCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Calling identity is not authorized");
+ }
+
+ if (!isManagedProfile(managedProfileUser.getIdentifier())) {
+ throw new IllegalStateException("Given user is not a managed profile");
+ }
+ ComponentName profileOwnerComponent =
+ mOwners.getProfileOwnerComponent(managedProfileUser.getIdentifier());
+ if (profileOwnerComponent == null) {
+ throw new IllegalStateException("There is no profile owner on the given profile");
+ }
+ Intent primaryProfileSuccessIntent = new Intent(ACTION_MANAGED_PROFILE_PROVISIONED);
+ primaryProfileSuccessIntent.setPackage(profileOwnerComponent.getPackageName());
+ primaryProfileSuccessIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES
+ | Intent.FLAG_RECEIVER_FOREGROUND);
+ primaryProfileSuccessIntent.putExtra(Intent.EXTRA_USER, managedProfileUser);
+
+ if (migratedAccount != null) {
+ primaryProfileSuccessIntent.putExtra(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE,
+ migratedAccount);
+ }
+
+ mContext.sendBroadcastAsUser(primaryProfileSuccessIntent,
+ UserHandle.of(getProfileParentId(managedProfileUser.getIdentifier())));
+ }
+
+ @Override
public UserHandle createAndManageUser(ComponentName admin, String name,
ComponentName profileOwner, PersistableBundle adminExtras, int flags) {
Preconditions.checkNotNull(admin, "admin is null");
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 7a96f4cf1bc8..215f1e8e2a9e 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -241,6 +241,25 @@ public class AccountManagerServiceTest extends AndroidTestCase {
}
@SmallTest
+ public void testCheckAddAccountLongName() throws Exception {
+ unlockSystemUser();
+ String longString = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ + "aaaaa";
+ Account a11 = new Account(longString, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
+
+ mAms.addAccountExplicitly(a11, /* password= */ "p11", /* extras= */ null);
+
+ String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
+ when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
+ Account[] accounts = mAms.getAccountsAsUser(null,
+ UserHandle.getCallingUserId(), mContext.getOpPackageName());
+ assertEquals(0, accounts.length);
+ }
+
+
+ @SmallTest
public void testPasswords() throws Exception {
unlockSystemUser();
Account a11 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 68900175cc8f..6f6a260c0b6b 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -70,6 +70,7 @@ import com.google.common.collect.ImmutableMap;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -516,6 +517,7 @@ public class RecoverableKeyStoreManagerTest {
}
}
+ @Ignore("Causing breakages so ignoring to resolve, b/231667368")
@Test
public void initRecoveryService_alwaysUpdatesCertsWhenTestRootCertIsUsed() throws Exception {
int uid = Binder.getCallingUid();
@@ -539,6 +541,7 @@ public class RecoverableKeyStoreManagerTest {
testRootCertAlias)).isEqualTo(TestData.getInsecureCertPathForEndpoint2());
}
+ @Ignore("Causing breakages so ignoring to resolve, b/231667368")
@Test
public void initRecoveryService_updatesCertsIndependentlyForDifferentRoots() throws Exception {
int uid = Binder.getCallingUid();
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
index d1366144d33b..8da7a76f18ce 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -74,6 +74,13 @@ public class UserManagerServiceTest extends AndroidTestCase {
assertEquals(accountName, um.getUserAccount(tempUserId));
}
+ public void testValidateName() {
+ assertNull(UserManagerService.validateName("android"));
+ assertNull(UserManagerService.validateName("com.company.myapp"));
+ assertNotNull(UserManagerService.validateName("/../../data"));
+ assertNotNull(UserManagerService.validateName("/dir"));
+ }
+
private Bundle createBundle() {
Bundle result = new Bundle();
// Tests for 6 allowed types: Integer, Boolean, String, String[], Bundle and Parcelable[]
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 8c3373faa0d4..cca01a07697c 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -1126,6 +1126,21 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
}
@Test
+ public void testA11yCrossUserEventNotSent() throws Exception {
+ final Notification n = new Builder(getContext(), "test")
+ .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
+ int userId = mUser.getIdentifier() + 1;
+ StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
+ mPid, n, UserHandle.of(userId), null, System.currentTimeMillis());
+ NotificationRecord r = new NotificationRecord(getContext(), sbn,
+ new NotificationChannel("test", "test", IMPORTANCE_HIGH));
+
+ mService.buzzBeepBlinkLocked(r);
+
+ verify(mAccessibilityService, never()).sendAccessibilityEvent(any(), anyInt());
+ }
+
+ @Test
public void testLightsScreenOn() {
mService.mScreenOn = true;
NotificationRecord r = getLightsNotification();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index b6137d393e3a..544442e46d58 100644..100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -150,6 +150,8 @@ import com.android.server.notification.NotificationManagerService.NotificationLi
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.wm.WindowManagerInternal;
+import com.google.common.collect.ImmutableList;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -168,6 +170,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
@SmallTest
@@ -1817,7 +1821,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
+ when(mPreferencesHelper.getNotificationChannelGroupWithChannels(
+ eq(PKG), anyInt(), eq(ncg.getId()), anyBoolean()))
.thenReturn(ncg);
reset(mListeners);
mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
@@ -1827,6 +1832,55 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testDeleteChannelGroupChecksForFgses() throws Exception {
+ List<String> associations = new ArrayList<>();
+ associations.add("a");
+ when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
+ CountDownLatch latch = new CountDownLatch(2);
+ mService.createNotificationChannelGroup(
+ PKG, mUid, new NotificationChannelGroup("group", "group"), true, false);
+ new Thread(() -> {
+ NotificationChannel notificationChannel = new NotificationChannel("id", "id",
+ NotificationManager.IMPORTANCE_HIGH);
+ notificationChannel.setGroup("group");
+ ParceledListSlice<NotificationChannel> pls =
+ new ParceledListSlice(ImmutableList.of(notificationChannel));
+ try {
+ mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ latch.countDown();
+ }).start();
+ new Thread(() -> {
+ try {
+ synchronized (this) {
+ wait(5000);
+ }
+ mService.createNotificationChannelGroup(PKG, mUid,
+ new NotificationChannelGroup("new", "new group"), true, false);
+ NotificationChannel notificationChannel =
+ new NotificationChannel("id", "id", NotificationManager.IMPORTANCE_HIGH);
+ notificationChannel.setGroup("new");
+ ParceledListSlice<NotificationChannel> pls =
+ new ParceledListSlice(ImmutableList.of(notificationChannel));
+ try {
+ mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
+ mBinderService.deleteNotificationChannelGroup(PKG, "group");
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ latch.countDown();
+ }).start();
+
+ latch.await();
+ verify(mAmi).hasForegroundServiceNotification(anyString(), anyInt(), anyString());
+ }
+
+ @Test
public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
mService.setPreferencesHelper(mPreferencesHelper);
List<String> associations = new ArrayList<>();
@@ -2047,6 +2101,69 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testSnoozeRunnable_tooManySnoozed_singleNotification() {
+ final NotificationRecord notification = generateNotificationRecord(
+ mTestNotificationChannel, 1, null, true);
+ mService.addNotification(notification);
+
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
+ when(mSnoozeHelper.canSnooze(1)).thenReturn(false);
+
+ NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
+ mService.new SnoozeNotificationRunnable(
+ notification.getKey(), 100, null);
+ snoozeNotificationRunnable.run();
+
+ verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong());
+ assertEquals(1, mService.getNotificationRecordCount());
+ }
+
+ @Test
+ public void testSnoozeRunnable_tooManySnoozed_singleGroupChildNotification() {
+ final NotificationRecord notification = generateNotificationRecord(
+ mTestNotificationChannel, 1, "group", true);
+ final NotificationRecord notificationChild = generateNotificationRecord(
+ mTestNotificationChannel, 1, "group", false);
+ mService.addNotification(notification);
+ mService.addNotification(notificationChild);
+
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
+ when(mSnoozeHelper.canSnooze(2)).thenReturn(false);
+
+ NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
+ mService.new SnoozeNotificationRunnable(
+ notificationChild.getKey(), 100, null);
+ snoozeNotificationRunnable.run();
+
+ verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong());
+ assertEquals(2, mService.getNotificationRecordCount());
+ }
+
+ @Test
+ public void testSnoozeRunnable_tooManySnoozed_summaryNotification() {
+ final NotificationRecord notification = generateNotificationRecord(
+ mTestNotificationChannel, 1, "group", true);
+ final NotificationRecord notificationChild = generateNotificationRecord(
+ mTestNotificationChannel, 12, "group", false);
+ final NotificationRecord notificationChild2 = generateNotificationRecord(
+ mTestNotificationChannel, 13, "group", false);
+ mService.addNotification(notification);
+ mService.addNotification(notificationChild);
+ mService.addNotification(notificationChild2);
+
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
+ when(mSnoozeHelper.canSnooze(3)).thenReturn(false);
+
+ NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
+ mService.new SnoozeNotificationRunnable(
+ notification.getKey(), 100, null);
+ snoozeNotificationRunnable.run();
+
+ verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong());
+ assertEquals(3, mService.getNotificationRecordCount());
+ }
+
+ @Test
public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
final NotificationRecord nonGrouped = generateNotificationRecord(
mTestNotificationChannel, 1, null, false);
@@ -2054,6 +2171,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mTestNotificationChannel, 2, "group", false);
mService.addNotification(grouped);
mService.addNotification(nonGrouped);
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
@@ -2076,6 +2194,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mService.addNotification(parent);
mService.addNotification(child);
mService.addNotification(child2);
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
@@ -2097,6 +2216,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mService.addNotification(parent);
mService.addNotification(child);
mService.addNotification(child2);
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
@@ -2116,6 +2236,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mTestNotificationChannel, 2, "group", false);
mService.addNotification(parent);
mService.addNotification(child);
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
@@ -2131,6 +2252,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
final NotificationRecord child = generateNotificationRecord(
mTestNotificationChannel, 2, "group", false);
mService.addNotification(child);
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
@@ -4983,7 +5105,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
zenPolicy, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
try {
- mBinderService.addAutomaticZenRule(rule);
+ mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
fail("Zen policy only applies to priority only mode");
} catch (IllegalArgumentException e) {
// yay
@@ -4991,11 +5113,48 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
- mBinderService.addAutomaticZenRule(rule);
+ mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
null, NotificationManager.INTERRUPTION_FILTER_NONE, isEnabled);
- mBinderService.addAutomaticZenRule(rule);
+ mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
+ }
+
+ @Test
+ public void testAddAutomaticZenRule_systemCallTakesPackageFromOwner() throws Exception {
+ mService.isSystemUid = true;
+ ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
+ when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
+ .thenReturn(true);
+ mService.setZenHelper(mockZenModeHelper);
+ ComponentName owner = new ComponentName("android", "ProviderName");
+ ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
+ boolean isEnabled = true;
+ AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
+ zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
+ mBinderService.addAutomaticZenRule(rule, "com.android.settings");
+
+ // verify that zen mode helper gets passed in a package name of "android"
+ verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString());
+ }
+
+ @Test
+ public void testAddAutomaticZenRule_nonSystemCallTakesPackageFromArg() throws Exception {
+ mService.isSystemUid = false;
+ ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
+ when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
+ .thenReturn(true);
+ mService.setZenHelper(mockZenModeHelper);
+ ComponentName owner = new ComponentName("android", "ProviderName");
+ ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
+ boolean isEnabled = true;
+ AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
+ zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
+ mBinderService.addAutomaticZenRule(rule, "another.package");
+
+ // verify that zen mode helper gets passed in the package name from the arg, not the owner
+ verify(mockZenModeHelper).addAutomaticZenRule(
+ eq("another.package"), eq(rule), anyString());
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 80439cf66387..2cede07de257 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -2010,6 +2010,19 @@ public class PreferencesHelperTest extends UiServiceTestCase {
}
@Test
+ public void testIsGroupBlocked_appCannotCreateAsBlocked() throws Exception {
+ NotificationChannelGroup group = new NotificationChannelGroup("id", "name");
+ group.setBlocked(true);
+ mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
+ assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId()));
+
+ NotificationChannelGroup group3 = group.clone();
+ group3.setBlocked(false);
+ mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group3, true);
+ assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId()));
+ }
+
+ @Test
public void testIsGroup_appCannotResetBlock() throws Exception {
NotificationChannelGroup group = new NotificationChannelGroup("id", "name");
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
index 2141ecc95bb8..3c389bb35535 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
@@ -15,6 +15,8 @@
*/
package com.android.server.notification;
+import static com.android.server.notification.SnoozeHelper.CONCURRENT_SNOOZE_LIMIT;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -104,6 +106,22 @@ public class SnoozeHelperTest extends UiServiceTestCase {
}
@Test
+ public void testSnoozeLimit() {
+ for (int i = 0; i < CONCURRENT_SNOOZE_LIMIT; i++ ) {
+ NotificationRecord r = getNotificationRecord("pkg", i, i+"", UserHandle.SYSTEM);
+
+ assertTrue("cannot snooze record " + i, mSnoozeHelper.canSnooze(1));
+
+ if (i % 2 == 0) {
+ mSnoozeHelper.snooze(r, 1000);
+ } else {
+ mSnoozeHelper.snooze(r, 9000);
+ }
+ }
+ assertFalse(mSnoozeHelper.canSnooze(1));
+ }
+
+ @Test
public void testCancelByApp() throws Exception {
NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
NotificationRecord r2 = getNotificationRecord("pkg", 2, "two", UserHandle.SYSTEM);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
index 8cd6ef9c132f..bd472485f6ac 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
@@ -158,7 +158,7 @@ public class ZenModeConfigTest extends UiServiceTestCase {
ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
rule.configurationActivity = new ComponentName("a", "a");
- rule.component = new ComponentName("a", "b");
+ rule.component = new ComponentName("b", "b");
rule.conditionId = new Uri.Builder().scheme("hello").build();
rule.condition = new Condition(rule.conditionId, "", Condition.STATE_TRUE);
rule.enabled = true;
@@ -168,6 +168,7 @@ public class ZenModeConfigTest extends UiServiceTestCase {
rule.modified = true;
rule.name = "name";
rule.snoozing = true;
+ rule.pkg = "b";
XmlSerializer out = new FastXmlSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -183,8 +184,7 @@ public class ZenModeConfigTest extends UiServiceTestCase {
new ByteArrayInputStream(baos.toByteArray())), null);
parser.nextTag();
ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
- // read from backing component
- assertEquals("a", fromXml.pkg);
+ assertEquals("b", fromXml.pkg);
// always resets on reboot
assertFalse(fromXml.snoozing);
//should all match original
@@ -200,6 +200,55 @@ public class ZenModeConfigTest extends UiServiceTestCase {
assertEquals(rule.zenMode, fromXml.zenMode);
}
+ @Test
+ public void testRuleXml_pkg_component() throws Exception {
+ String tag = "tag";
+
+ ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
+ rule.configurationActivity = new ComponentName("a", "a");
+ rule.component = new ComponentName("b", "b");
+
+ XmlSerializer out = new FastXmlSerializer();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ out.setOutput(new BufferedOutputStream(baos), "utf-8");
+ out.startDocument(null, true);
+ out.startTag(null, tag);
+ ZenModeConfig.writeRuleXml(rule, out);
+ out.endTag(null, tag);
+ out.endDocument();
+
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new BufferedInputStream(
+ new ByteArrayInputStream(baos.toByteArray())), null);
+ parser.nextTag();
+ ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
+ assertEquals("b", fromXml.pkg);
+ }
+
+ @Test
+ public void testRuleXml_pkg_configActivity() throws Exception {
+ String tag = "tag";
+
+ ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
+ rule.configurationActivity = new ComponentName("a", "a");
+
+ XmlSerializer out = new FastXmlSerializer();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ out.setOutput(new BufferedOutputStream(baos), "utf-8");
+ out.startDocument(null, true);
+ out.startTag(null, tag);
+ ZenModeConfig.writeRuleXml(rule, out);
+ out.endTag(null, tag);
+ out.endDocument();
+
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new BufferedInputStream(
+ new ByteArrayInputStream(baos.toByteArray())), null);
+ parser.nextTag();
+ ZenModeConfig.ZenRule fromXml = ZenModeConfig.readRuleXml(parser);
+ assertNull(fromXml.pkg);
+ }
+
private ZenModeConfig getMutedNotificationsConfig() {
ZenModeConfig config = new ZenModeConfig();
// Allow alarms, media, and system
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 89364500fd80..78edc1c2a4de 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -20,10 +20,13 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
+import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.fail;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.ArgumentMatchers.any;
@@ -48,7 +51,9 @@ import android.app.NotificationManager.Policy;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.media.AudioAttributes;
@@ -77,6 +82,8 @@ import com.android.internal.util.FastXmlSerializer;
import com.android.server.UiServiceTestCase;
import com.android.server.notification.ManagedServices.UserProfiles;
+import com.google.common.collect.ImmutableList;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -102,9 +109,12 @@ public class ZenModeHelperTest extends UiServiceTestCase {
private static final String EVENTS_DEFAULT_RULE_ID = "EVENTS_DEFAULT_RULE";
private static final String SCHEDULE_DEFAULT_RULE_ID = "EVERY_NIGHT_DEFAULT_RULE";
+ private static final String CUSTOM_PKG_NAME = "not.android";
+ private static final int CUSTOM_PKG_UID = 1;
ConditionProviders mConditionProviders;
@Mock NotificationManager mNotificationManager;
+ @Mock PackageManager mPackageManager;
private Resources mResources;
private TestableLooper mTestableLooper;
private ZenModeHelper mZenModeHelperSpy;
@@ -113,7 +123,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
@Mock AppOpsManager mAppOps;
@Before
- public void setUp() {
+ public void setUp() throws PackageManager.NameNotFoundException {
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
@@ -135,6 +145,16 @@ public class ZenModeHelperTest extends UiServiceTestCase {
mConditionProviders.addSystemProvider(new CountdownConditionProvider());
mZenModeHelperSpy = spy(new ZenModeHelper(mContext, mTestableLooper.getLooper(),
mConditionProviders));
+
+ ResolveInfo ri = new ResolveInfo();
+ ri.activityInfo = new ActivityInfo();
+ when(mPackageManager.queryIntentActivitiesAsUser(any(), anyInt(), anyInt())).thenReturn(
+ ImmutableList.of(ri));
+ when(mPackageManager.getPackageUidAsUser(eq(CUSTOM_PKG_NAME), anyInt()))
+ .thenReturn(CUSTOM_PKG_UID);
+ when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(
+ new String[] {getContext().getPackageName()});
+ mZenModeHelperSpy.mPm = mPackageManager;
}
private XmlResourceParser getDefaultConfigParser() throws IOException, XmlPullParserException {
@@ -1333,7 +1353,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {
new ComponentName("android", "ScheduleConditionProvider"),
ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
- String id = mZenModeHelperSpy.addAutomaticZenRule(zenRule, "test");
+ String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
assertTrue(id != null);
ZenModeConfig.ZenRule ruleInConfig = mZenModeHelperSpy.mConfig.automaticRules.get(id);
@@ -1346,6 +1366,96 @@ public class ZenModeHelperTest extends UiServiceTestCase {
assertEquals(zenRule.getName(), ruleInConfig.name);
}
+ @Test
+ public void testAddAutomaticZenRule_beyondSystemLimit() {
+ for (int i = 0; i < RULE_LIMIT_PER_PACKAGE; i++) {
+ ScheduleInfo si = new ScheduleInfo();
+ si.startHour = i;
+ AutomaticZenRule zenRule = new AutomaticZenRule("name" + i,
+ null,
+ new ComponentName("android", "ScheduleConditionProvider"),
+ ZenModeConfig.toScheduleConditionId(si),
+ new ZenPolicy.Builder().build(),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ // We need the package name to be something that's not "android" so there aren't any
+ // existing rules under that package.
+ String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+ assertNotNull(id);
+ }
+ try {
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ null,
+ new ComponentName("android", "ScheduleConditionProvider"),
+ ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+ new ZenPolicy.Builder().build(),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
+ fail("allowed too many rules to be created");
+ } catch (IllegalArgumentException e) {
+ // yay
+ }
+ }
+
+ @Test
+ public void testAddAutomaticZenRule_beyondSystemLimit_differentComponents() {
+ // Make sure the system limit is enforced per-package even with different component provider
+ // names.
+ for (int i = 0; i < RULE_LIMIT_PER_PACKAGE; i++) {
+ ScheduleInfo si = new ScheduleInfo();
+ si.startHour = i;
+ AutomaticZenRule zenRule = new AutomaticZenRule("name" + i,
+ null,
+ new ComponentName("android", "ScheduleConditionProvider" + i),
+ ZenModeConfig.toScheduleConditionId(si),
+ new ZenPolicy.Builder().build(),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+ assertNotNull(id);
+ }
+ try {
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ null,
+ new ComponentName("android", "ScheduleConditionProviderFinal"),
+ ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+ new ZenPolicy.Builder().build(),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+ fail("allowed too many rules to be created");
+ } catch (IllegalArgumentException e) {
+ // yay
+ }
+ }
+
+ @Test
+ public void testAddAutomaticZenRule_claimedSystemOwner() {
+ // Make sure anything that claims to have a "system" owner but not actually part of the
+ // system package still gets limited on number of rules
+ for (int i = 0; i < RULE_LIMIT_PER_PACKAGE; i++) {
+ ScheduleInfo si = new ScheduleInfo();
+ si.startHour = i;
+ AutomaticZenRule zenRule = new AutomaticZenRule("name" + i,
+ new ComponentName("android", "ScheduleConditionProvider" + i),
+ null, // configuration activity
+ ZenModeConfig.toScheduleConditionId(si),
+ new ZenPolicy.Builder().build(),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+ assertNotNull(id);
+ }
+ try {
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ new ComponentName("android", "ScheduleConditionProviderFinal"),
+ null, // configuration activity
+ ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+ new ZenPolicy.Builder().build(),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+ fail("allowed too many rules to be created");
+ } catch (IllegalArgumentException e) {
+ // yay
+ }
+ }
+
private void setupZenConfig() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index e004cd3fb0c4..f25110f549df 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -23,6 +23,9 @@ import static android.graphics.GraphicBuffer.USAGE_SW_READ_RARELY;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import android.app.ActivityManager.TaskSnapshot;
import android.content.ComponentName;
import android.graphics.Canvas;
@@ -32,9 +35,14 @@ import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.UserManager;
+import android.os.UserManagerInternal;
+
+import com.android.server.LocalServices;
import org.junit.After;
+import org.junit.AfterClass;
import org.junit.Before;
+import org.junit.BeforeClass;
import java.io.File;
@@ -50,10 +58,26 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase {
TaskSnapshotLoader mLoader;
int mTestUserId;
+ @BeforeClass
+ public static void setUpOnce() {
+ final UserManagerInternal userManager = mock(UserManagerInternal.class);
+ LocalServices.addService(UserManagerInternal.class, userManager);
+ }
+
+ @AfterClass
+ public static void tearDownOnce() {
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ }
+
@Before
public void setUp() {
final UserManager um = UserManager.get(getInstrumentation().getTargetContext());
mTestUserId = um.getUserHandle();
+
+ final UserManagerInternal userManagerInternal =
+ LocalServices.getService(UserManagerInternal.class);
+ when(userManagerInternal.isUserUnlocked(mTestUserId)).thenReturn(true);
+
mPersister = new TaskSnapshotPersister(mWm, userId -> FILES_DIR);
mLoader = new TaskSnapshotLoader(mPersister);
mPersister.start();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 0b1c07b9ee43..2a743b45bd49 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -979,6 +979,9 @@ public class VoiceInteractionManagerService extends SystemService {
@Override
public ModuleProperties getDspModuleProperties(IVoiceInteractionService service) {
+ // Allow the call if it is granted CAPTURE_AUDIO_HOTWORD.
+ enforceCallingPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD);
+
// Allow the call if this is the current voice interaction service.
synchronized (this) {
enforceIsCurrentVoiceInteractionService(service);
@@ -996,6 +999,9 @@ public class VoiceInteractionManagerService extends SystemService {
public int startRecognition(IVoiceInteractionService service, int keyphraseId,
String bcp47Locale, IRecognitionStatusCallback callback,
RecognitionConfig recognitionConfig) {
+ // Allow the call if it is granted RECORD_AUDIO and CAPTURE_AUDIO_HOTWORD.
+ enforceAlwaysOnHotwordPermissions();
+
// Allow the call if this is the current voice interaction service.
synchronized (this) {
enforceIsCurrentVoiceInteractionService(service);
@@ -1032,6 +1038,9 @@ public class VoiceInteractionManagerService extends SystemService {
@Override
public int stopRecognition(IVoiceInteractionService service, int keyphraseId,
IRecognitionStatusCallback callback) {
+ // Allow the call if it is granted RECORD_AUDIO and CAPTURE_AUDIO_HOTWORD.
+ enforceAlwaysOnHotwordPermissions();
+
// Allow the call if this is the current voice interaction service.
synchronized (this) {
enforceIsCurrentVoiceInteractionService(service);
@@ -1277,6 +1286,11 @@ public class VoiceInteractionManagerService extends SystemService {
}
}
+ private void enforceAlwaysOnHotwordPermissions() {
+ enforceCallingPermission(Manifest.permission.RECORD_AUDIO);
+ enforceCallingPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD);
+ }
+
private void enforceCallingPermission(String permission) {
if (mContext.checkCallingOrSelfPermission(permission)
!= PackageManager.PERMISSION_GRANTED) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 64092034e0b2..f932c5596c7b 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -953,7 +953,7 @@ public class TelecomManager {
try {
if (isServiceConnected()) {
return getTelecomService().getPhoneAccountsSupportingScheme(uriScheme,
- mContext.getOpPackageName());
+ mContext.getOpPackageName()).getList();
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getPhoneAccountsSupportingScheme", e);
@@ -995,7 +995,8 @@ public class TelecomManager {
public List<PhoneAccountHandle> getSelfManagedPhoneAccounts() {
try {
if (isServiceConnected()) {
- return getTelecomService().getSelfManagedPhoneAccounts(mContext.getOpPackageName());
+ return getTelecomService()
+ .getSelfManagedPhoneAccounts(mContext.getOpPackageName()).getList();
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getSelfManagedPhoneAccounts()", e);
@@ -1017,7 +1018,7 @@ public class TelecomManager {
try {
if (isServiceConnected()) {
return getTelecomService().getCallCapablePhoneAccounts(
- includeDisabledAccounts, mContext.getOpPackageName());
+ includeDisabledAccounts, mContext.getOpPackageName()).getList();
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getCallCapablePhoneAccounts(" +
@@ -1037,7 +1038,8 @@ public class TelecomManager {
public List<PhoneAccountHandle> getPhoneAccountsForPackage() {
try {
if (isServiceConnected()) {
- return getTelecomService().getPhoneAccountsForPackage(mContext.getPackageName());
+ return getTelecomService()
+ .getPhoneAccountsForPackage(mContext.getPackageName()).getList();
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getPhoneAccountsForPackage", e);
@@ -1091,7 +1093,7 @@ public class TelecomManager {
public List<PhoneAccount> getAllPhoneAccounts() {
try {
if (isServiceConnected()) {
- return getTelecomService().getAllPhoneAccounts();
+ return getTelecomService().getAllPhoneAccounts().getList();
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getAllPhoneAccounts", e);
@@ -1109,7 +1111,7 @@ public class TelecomManager {
public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
try {
if (isServiceConnected()) {
- return getTelecomService().getAllPhoneAccountHandles();
+ return getTelecomService().getAllPhoneAccountHandles().getList();
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getAllPhoneAccountHandles", e);
@@ -1125,9 +1127,14 @@ public class TelecomManager {
* when placing calls. The user may still need to enable the {@link PhoneAccount} within
* the phone app settings before the account is usable.
* <p>
+ * Note: Each package is limited to 10 {@link PhoneAccount} registrations.
+ * <p>
* A {@link SecurityException} will be thrown if an app tries to register a
* {@link PhoneAccountHandle} where the package name specified within
* {@link PhoneAccountHandle#getComponentName()} does not match the package name of the app.
+ * <p>
+ * A {@link IllegalArgumentException} will be thrown if an app tries to register a
+ * {@link PhoneAccount} when the upper bound limit, 10, has already been reached.
*
* @param account The complete {@link PhoneAccount}.
*/
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 4fcda4d00883..10c49ecce1ea 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -23,6 +23,7 @@ import android.telecom.PhoneAccountHandle;
import android.net.Uri;
import android.os.Bundle;
import android.telecom.PhoneAccount;
+import android.content.pm.ParceledListSlice;
/**
* Interface used to interact with Telecom. Mostly this is used by TelephonyManager for passing
@@ -55,24 +56,24 @@ interface ITelecomService {
/**
* @see TelecomServiceImpl#getCallCapablePhoneAccounts
*/
- List<PhoneAccountHandle> getCallCapablePhoneAccounts(
+ ParceledListSlice getCallCapablePhoneAccounts(
boolean includeDisabledAccounts, String callingPackage);
/**
* @see TelecomServiceImpl#getSelfManagedPhoneAccounts
*/
- List<PhoneAccountHandle> getSelfManagedPhoneAccounts(String callingPackage);
+ ParceledListSlice getSelfManagedPhoneAccounts(String callingPackage);
/**
* @see TelecomManager#getPhoneAccountsSupportingScheme
*/
- List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme,
+ ParceledListSlice getPhoneAccountsSupportingScheme(in String uriScheme,
String callingPackage);
/**
* @see TelecomManager#getPhoneAccountsForPackage
*/
- List<PhoneAccountHandle> getPhoneAccountsForPackage(in String packageName);
+ ParceledListSlice getPhoneAccountsForPackage(in String packageName);
/**
* @see TelecomManager#getPhoneAccount
@@ -87,12 +88,12 @@ interface ITelecomService {
/**
* @see TelecomManager#getAllPhoneAccounts
*/
- List<PhoneAccount> getAllPhoneAccounts();
+ ParceledListSlice getAllPhoneAccounts();
/**
* @see TelecomManager#getAllPhoneAccountHandles
*/
- List<PhoneAccountHandle> getAllPhoneAccountHandles();
+ ParceledListSlice getAllPhoneAccountHandles();
/**
* @see TelecomServiceImpl#getSimCallManager