Merge "DO NOT MERGE Fix auto-grant of AR runtime permission if device is upgrading from pre-Q" into sc-v2-dev
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index e6cdcc0..0d6a079 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -31,7 +31,6 @@
import com.android.internal.annotations.GuardedBy;
-import java.util.Objects;
import java.util.Set;
/**
@@ -87,12 +86,6 @@
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/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 0ff9f66..e76f89c 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1353,6 +1353,11 @@
}
/** @hide */
+ public void setRemoteTransition(@Nullable RemoteTransition remoteTransition) {
+ mRemoteTransition = remoteTransition;
+ }
+
+ /** @hide */
public static ActivityOptions fromBundle(Bundle bOptions) {
return bOptions != null ? new ActivityOptions(bOptions) : null;
}
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 6553b61..748f874 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -124,8 +124,13 @@
/**
* 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";
@@ -284,17 +289,17 @@
*/
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;
}
@@ -303,18 +308,22 @@
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;
}
@@ -324,8 +333,8 @@
mAllowBubbles = in.readInt();
mImportanceLockedByOEM = in.readBoolean();
mOriginalImportance = in.readInt();
- mParentId = in.readString();
- mConversationId = in.readString();
+ mParentId = getTrimmedString(in.readString());
+ mConversationId = getTrimmedString(in.readString());
mDemoted = in.readBoolean();
mImportantConvo = in.readBoolean();
mDeletedTime = in.readLong();
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index cd6df0b..c194a28 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -43,8 +43,9 @@
/**
* 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";
@@ -90,13 +91,14 @@
*/
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);
+ mName = getTrimmedString(mName.toString());
if (in.readByte() != 0) {
- mDescription = in.readString();
+ mDescription = getTrimmedString(in.readString());
} else {
mDescription = null;
}
@@ -120,7 +122,7 @@
} else {
dest.writeByte((byte) 0);
}
- TextUtils.writeToParcel(mName, dest, flags);
+ TextUtils.writeToParcel(mName.toString(), dest, flags);
if (mDescription != null) {
dest.writeByte((byte) 1);
dest.writeString(mDescription);
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 0000000..2a3da05
--- /dev/null
+++ b/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.os.Parcel;
+import android.test.AndroidTestCase;
+
+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());
+ }
+}
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 0000000..647bfe8
--- /dev/null
+++ b/core/tests/coretests/src/android/app/NotificationChannelTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.getParentChannelId().length());
+ assertEquals(NotificationChannel.MAX_TEXT_LENGTH,
+ fromParcel.getGroup().length());
+ assertEquals(NotificationChannel.MAX_TEXT_LENGTH,
+ fromParcel.getConversationId().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/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
index c346142..f9584a3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
@@ -21,8 +21,6 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
@@ -85,7 +83,6 @@
private static final int DEFAULT_PHOTO_SIZE = 500;
private static final String IMAGES_DIR = "multi_user";
- private static final String PRE_CROP_PICTURE_FILE_NAME = "PreCropEditUserPhoto.jpg";
private static final String CROP_PICTURE_FILE_NAME = "CropEditUserPhoto.jpg";
private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto.jpg";
private static final String NEW_USER_PHOTO_FILE_NAME = "NewUserPhoto.png";
@@ -98,7 +95,6 @@
private final String mFileAuthority;
private final File mImagesDir;
- private final Uri mPreCropPictureUri;
private final Uri mCropPictureUri;
private final Uri mTakePictureUri;
@@ -114,7 +110,6 @@
mImagesDir = new File(activity.getCacheDir(), IMAGES_DIR);
mImagesDir.mkdir();
- mPreCropPictureUri = createTempImageUri(activity, PRE_CROP_PICTURE_FILE_NAME, !waiting);
mCropPictureUri = createTempImageUri(activity, CROP_PICTURE_FILE_NAME, !waiting);
mTakePictureUri = createTempImageUri(activity, TAKE_PICTURE_FILE_NAME, !waiting);
mPhotoSize = getPhotoSize(activity);
@@ -148,7 +143,7 @@
case REQUEST_CODE_CHOOSE_PHOTO:
if (mTakePictureUri.equals(pictureUri)) {
if (PhotoCapabilityUtils.canCropPhoto(mActivity)) {
- cropPhoto(pictureUri);
+ cropPhoto();
} else {
onPhotoNotCropped(pictureUri);
}
@@ -229,7 +224,7 @@
protected Void doInBackground(Void... params) {
final ContentResolver cr = mActivity.getContentResolver();
try (InputStream in = cr.openInputStream(pictureUri);
- OutputStream out = cr.openOutputStream(mPreCropPictureUri)) {
+ OutputStream out = cr.openOutputStream(mTakePictureUri)) {
Streams.copy(in, out);
} catch (IOException e) {
Log.w(TAG, "Failed to copy photo", e);
@@ -240,41 +235,28 @@
@Override
protected void onPostExecute(Void result) {
if (!mActivity.isFinishing() && !mActivity.isDestroyed()) {
- cropPhoto(mPreCropPictureUri);
+ cropPhoto();
}
}
}.execute();
}
- private void cropPhoto(final Uri pictureUri) {
+ private void cropPhoto() {
// TODO: Use a public intent, when there is one.
Intent intent = new Intent("com.android.camera.action.CROP");
- intent.setDataAndType(pictureUri, "image/*");
+ intent.setDataAndType(mTakePictureUri, "image/*");
appendOutputExtra(intent, mCropPictureUri);
appendCropExtras(intent);
- try {
- StrictMode.disableDeathOnFileUriExposure();
- if (startSystemActivityForResult(intent, REQUEST_CODE_CROP_PHOTO)) {
- return;
+ if (intent.resolveActivity(mActivity.getPackageManager()) != null) {
+ try {
+ StrictMode.disableDeathOnFileUriExposure();
+ mActivityStarter.startActivityForResult(intent, REQUEST_CODE_CROP_PHOTO);
+ } finally {
+ StrictMode.enableDeathOnFileUriExposure();
}
- } finally {
- StrictMode.enableDeathOnFileUriExposure();
+ } else {
+ onPhotoNotCropped(mTakePictureUri);
}
-
- onPhotoNotCropped(mTakePictureUri);
-
- }
-
- private boolean startSystemActivityForResult(Intent intent, int code) {
- ActivityInfo info = intent.resolveActivityInfo(mActivity.getPackageManager(),
- PackageManager.MATCH_SYSTEM_ONLY);
- if (info == null) {
- Log.w(TAG, "No system package activity could be found for code " + code);
- return false;
- }
- intent.setPackage(info.packageName);
- mActivityStarter.startActivityForResult(intent, code);
- return true;
}
private void appendOutputExtra(Intent intent, Uri pictureUri) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 9f44060..46671e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -333,6 +333,13 @@
};
/**
+ * Recalculate sensitiveness without animation; called when waking up while keyguard occluded.
+ */
+ public void updateSensitivenessForOccludedWakeup() {
+ mView.updateSensitiveness(false, mLockscreenUserManager.isAnyProfilePublicMode());
+ }
+
+ /**
* Set the overexpansion of the panel to be applied to the view.
*/
public void setOverExpansion(float overExpansion) {
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 a6fb317..8e47690 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -3594,6 +3594,17 @@
mWakeUpCoordinator.setFullyAwake(true);
mBypassHeadsUpNotifier.setFullyAwake(true);
mWakeUpCoordinator.setWakingUp(false);
+ if (isOccluded() && !mDozeParameters.canControlUnlockedScreenOff()) {
+ // When the keyguard is occluded we don't use the KEYGUARD state which would
+ // normally cause these redaction updates. If AOD is on, the KEYGUARD state is used
+ // to show the doze, AND UnlockedScreenOffAnimationController.onFinishedWakingUp()
+ // would force a KEYGUARD state that would take care of recalculating redaction.
+ // So if AOD is off or unsupported we need to trigger these updates at screen on
+ // when the keyguard is occluded.
+ mLockscreenUserManager.updatePublicMode();
+ mNotificationPanelViewController.getNotificationStackScrollLayoutController()
+ .updateSensitivenessForOccludedWakeup();
+ }
if (mLaunchCameraWhenFinishedWaking) {
mNotificationPanelViewController.launchCamera(
false /* animate */, mLastCameraLaunchSource);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 400b084..ae2f934 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1819,6 +1819,14 @@
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);
@@ -2064,6 +2072,10 @@
+ ", 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(
diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
index 9a19031..6759d79 100644
--- a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
+++ b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
@@ -32,6 +32,7 @@
import android.os.PowerWhitelistManager;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.EventLog;
import android.util.Log;
import android.view.KeyEvent;
@@ -117,6 +118,12 @@
int componentType = getComponentType(pendingIntent);
ComponentName componentName = getComponentName(pendingIntent, componentType);
if (componentName != null) {
+ if (!TextUtils.equals(componentName.getPackageName(), sessionPackageName)) {
+ EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging
+ throw new IllegalArgumentException("ComponentName does not belong to "
+ + "sessionPackageName. sessionPackageName = " + sessionPackageName
+ + ", ComponentName pkg = " + componentName.getPackageName());
+ }
return new MediaButtonReceiverHolder(userId, pendingIntent, componentName,
componentType);
}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 4822d6a..ca5e97c 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -53,6 +53,7 @@
import android.os.ResultReceiver;
import android.os.SystemClock;
import android.text.TextUtils;
+import android.util.EventLog;
import android.util.Log;
import android.view.KeyEvent;
@@ -934,6 +935,14 @@
@Override
public void setMediaButtonReceiver(PendingIntent pi, String sessionPackageName)
throws RemoteException {
+ //mPackageName has been verified in MediaSessionService.enforcePackageName().
+ if (!TextUtils.equals(sessionPackageName, mPackageName)) {
+ EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging
+ throw new IllegalArgumentException("sessionPackageName name does not match "
+ + "package name provided to MediaSessionRecord. sessionPackageName = "
+ + sessionPackageName + ", pkg = "
+ + mPackageName);
+ }
final long token = Binder.clearCallingIdentity();
try {
if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER)
@@ -952,6 +961,15 @@
public void setMediaButtonBroadcastReceiver(ComponentName receiver) throws RemoteException {
final long token = Binder.clearCallingIdentity();
try {
+ //mPackageName has been verified in MediaSessionService.enforcePackageName().
+ if (receiver != null && !TextUtils.equals(
+ mPackageName, receiver.getPackageName())) {
+ EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging
+ throw new IllegalArgumentException("receiver does not belong to "
+ + "package name provided to MediaSessionRecord. Pkg = " + mPackageName
+ + ", Receiver Pkg = " + receiver.getPackageName());
+ }
+
if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER)
!= 0) {
return;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 03544ef..eb28a32 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7387,7 +7387,8 @@
&& (record.getSuppressedVisualEffects() & SUPPRESSED_EFFECT_STATUS_BAR) != 0;
if (!record.isUpdate
&& record.getImportance() > IMPORTANCE_MIN
- && !suppressedByDnd) {
+ && !suppressedByDnd
+ && isNotificationForCurrentUser(record)) {
sendAccessibilityEvent(record);
sentAccessibilityEvent = true;
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index c11116c..9fd4801 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -310,7 +310,7 @@
public String addAutomaticZenRule(String pkg, AutomaticZenRule automaticZenRule,
String reason) {
- if (!isSystemRule(automaticZenRule)) {
+ if (!ZenModeConfig.SYSTEM_AUTHORITY.equals(pkg)) {
PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
if (component == null) {
component = getActivityInfo(automaticZenRule.getConfigurationActivity());
@@ -326,7 +326,8 @@
int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner())
+ getCurrentInstanceCount(automaticZenRule.getConfigurationActivity())
+ 1;
- if (newRuleInstanceCount > RULE_LIMIT_PER_PACKAGE
+ int newPackageRuleCount = getPackageRuleCount(pkg) + 1;
+ if (newPackageRuleCount > RULE_LIMIT_PER_PACKAGE
|| (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount)) {
throw new IllegalArgumentException("Rule instance limit exceeded");
}
@@ -507,6 +508,23 @@
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.getPkg())) {
+ count++;
+ }
+ }
+ }
+ return count;
+ }
+
public boolean canManageAutomaticZenRule(ZenRule rule) {
final int callingUid = Binder.getCallingUid();
if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
@@ -548,11 +566,6 @@
}
}
- 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);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6db8bc6..4c47ffd 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -21657,7 +21657,8 @@
return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
}
- if (isSystemApp(uninstalledPs)) {
+ if (isSystemApp(uninstalledPs)
+ && (deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0) {
UserInfo userInfo = mUserManager.getUserInfo(userId);
if (userInfo == null || !userInfo.isAdmin()) {
Slog.w(TAG, "Not removing package " + packageName
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 09c6b50..92abc486 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -88,6 +88,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
+import android.util.EventLog;
import android.util.IndentingPrintWriter;
import android.util.IntArray;
import android.util.Slog;
@@ -4499,6 +4500,13 @@
public void setApplicationRestrictions(String packageName, Bundle restrictions,
@UserIdInt 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);
}
@@ -4525,6 +4533,39 @@
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) {
final long ident = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 0e6d1c6..637cda1 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4640,8 +4640,12 @@
ActivityOptions takeOptions() {
if (DEBUG_TRANSITION) Slog.i(TAG, "Taking options for " + this + " callers="
+ Debug.getCallers(6));
+ if (mPendingOptions == null) return null;
final ActivityOptions opts = mPendingOptions;
mPendingOptions = null;
+ // Strip sensitive information from options before sending it to app.
+ opts.setRemoteTransition(null);
+ opts.setRemoteAnimationAdapter(null);
return opts;
}
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 2690948..4916262 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -36,6 +36,7 @@
import android.accounts.IAccountManagerResponse;
import android.app.AppOpsManager;
import android.app.INotificationManager;
+import android.app.PropertyInvalidatedCache;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.BroadcastReceiver;
@@ -132,6 +133,8 @@
protected void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ PropertyInvalidatedCache.disableForTestMode();
+
when(mMockPackageManager.checkSignatures(anyInt(), anyInt()))
.thenReturn(PackageManager.SIGNATURE_MATCH);
final UserInfo ui = new UserInfo(UserHandle.USER_SYSTEM, "user0", 0);
@@ -248,6 +251,26 @@
}
@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, /* callerPackage= */ 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/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index d593e80..c1bbad1 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -1300,6 +1300,21 @@
}
@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/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index e03cf1c..5c2730f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -1618,7 +1618,9 @@
ZenModeConfig.toScheduleConditionId(si),
new ZenPolicy.Builder().build(),
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
- String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
+ // 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 {
@@ -1628,12 +1630,71 @@
ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
new ZenPolicy.Builder().build(),
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
- String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
+ String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", 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
+ }
}
@Test
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 4cdeb0b..b31b1f7 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1257,7 +1257,7 @@
if (service != null) {
try {
return service.getPhoneAccountsSupportingScheme(uriScheme,
- mContext.getOpPackageName());
+ mContext.getOpPackageName()).getList();
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getPhoneAccountsSupportingScheme", e);
}
@@ -1299,7 +1299,7 @@
if (service != null) {
try {
return service.getSelfManagedPhoneAccounts(mContext.getOpPackageName(),
- mContext.getAttributionTag());
+ mContext.getAttributionTag()).getList();
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getSelfManagedPhoneAccounts()", e);
}
@@ -1325,7 +1325,7 @@
if (service != null) {
try {
return service.getCallCapablePhoneAccounts(includeDisabledAccounts,
- mContext.getOpPackageName(), mContext.getAttributionTag());
+ mContext.getOpPackageName(), mContext.getAttributionTag()).getList();
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getCallCapablePhoneAccounts("
+ includeDisabledAccounts + ")", e);
@@ -1349,7 +1349,7 @@
ITelecomService service = getTelecomService();
if (service != null) {
try {
- return service.getPhoneAccountsForPackage(mContext.getPackageName());
+ return service.getPhoneAccountsForPackage(mContext.getPackageName()).getList();
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getPhoneAccountsForPackage", e);
}
@@ -1409,7 +1409,7 @@
ITelecomService service = getTelecomService();
if (service != null) {
try {
- return service.getAllPhoneAccounts();
+ return service.getAllPhoneAccounts().getList();
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getAllPhoneAccounts", e);
}
@@ -1428,7 +1428,7 @@
ITelecomService service = getTelecomService();
if (service != null) {
try {
- return service.getAllPhoneAccountHandles();
+ return service.getAllPhoneAccountHandles().getList();
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getAllPhoneAccountHandles", e);
}
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 6f286d9..8f409c0 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.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
@@ -56,25 +57,25 @@
/**
* @see TelecomServiceImpl#getCallCapablePhoneAccounts
*/
- List<PhoneAccountHandle> getCallCapablePhoneAccounts(
+ ParceledListSlice<PhoneAccountHandle> getCallCapablePhoneAccounts(
boolean includeDisabledAccounts, String callingPackage, String callingFeatureId);
/**
* @see TelecomServiceImpl#getSelfManagedPhoneAccounts
*/
- List<PhoneAccountHandle> getSelfManagedPhoneAccounts(String callingPackage,
+ ParceledListSlice<PhoneAccountHandle> getSelfManagedPhoneAccounts(String callingPackage,
String callingFeatureId);
/**
* @see TelecomManager#getPhoneAccountsSupportingScheme
*/
- List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme,
+ ParceledListSlice<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme,
String callingPackage);
/**
* @see TelecomManager#getPhoneAccountsForPackage
*/
- List<PhoneAccountHandle> getPhoneAccountsForPackage(in String packageName);
+ ParceledListSlice<PhoneAccountHandle> getPhoneAccountsForPackage(in String packageName);
/**
* @see TelecomManager#getPhoneAccount
@@ -89,12 +90,12 @@
/**
* @see TelecomManager#getAllPhoneAccounts
*/
- List<PhoneAccount> getAllPhoneAccounts();
+ ParceledListSlice<PhoneAccount> getAllPhoneAccounts();
/**
* @see TelecomManager#getAllPhoneAccountHandles
*/
- List<PhoneAccountHandle> getAllPhoneAccountHandles();
+ ParceledListSlice<PhoneAccountHandle> getAllPhoneAccountHandles();
/**
* @see TelecomServiceImpl#getSimCallManager