Merge "Require permission to unlock keyguard" into sc-qpr1-dev
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index ae35775..15e755e 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2811,11 +2811,6 @@
}
}
- final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON);
- if (person != null) {
- visitor.accept(person.getIconUri());
- }
-
final RemoteInputHistoryItem[] history = getParcelableArrayFromBundle(extras,
Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS, RemoteInputHistoryItem.class);
if (history != null) {
@@ -2826,9 +2821,14 @@
}
}
}
- }
- if (isStyle(MessagingStyle.class) && extras != null) {
+ // Extras for MessagingStyle. We visit them even if not isStyle(MessagingStyle), since
+ // Notification Listeners might use directly (without the isStyle check).
+ final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON);
+ if (person != null) {
+ visitor.accept(person.getIconUri());
+ }
+
final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES);
if (!ArrayUtils.isEmpty(messages)) {
for (MessagingStyle.Message message : MessagingStyle.Message
@@ -2856,9 +2856,8 @@
}
visitIconUri(visitor, extras.getParcelable(EXTRA_CONVERSATION_ICON));
- }
- if (isStyle(CallStyle.class) & extras != null) {
+ // Extras for CallStyle (same reason for visiting without checking isStyle).
Person callPerson = extras.getParcelable(EXTRA_CALL_PERSON);
if (callPerson != null) {
visitor.accept(callPerson.getIconUri());
diff --git a/core/java/android/hardware/usb/OWNERS b/core/java/android/hardware/usb/OWNERS
index 8f5c2a0..a753f96 100644
--- a/core/java/android/hardware/usb/OWNERS
+++ b/core/java/android/hardware/usb/OWNERS
@@ -1,3 +1,7 @@
# Bug component: 175220
+aprasath@google.com
+kumarashishg@google.com
+sarup@google.com
+anothermark@google.com
badhri@google.com
diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java
index 66269cb..b25f47b 100644
--- a/core/java/android/hardware/usb/UsbConfiguration.java
+++ b/core/java/android/hardware/usb/UsbConfiguration.java
@@ -172,7 +172,8 @@
String name = in.readString();
int attributes = in.readInt();
int maxPower = in.readInt();
- Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader());
+ Parcelable[] interfaces = in.readParcelableArray(
+ UsbInterface.class.getClassLoader(), UsbInterface.class);
UsbConfiguration configuration = new UsbConfiguration(id, name, attributes, maxPower);
configuration.setInterfaces(interfaces);
return configuration;
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index e5e9b5f..9718b52 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.ArrayMap;
+import android.util.Slog;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
@@ -46,6 +47,8 @@
*/
public final class PersistableBundle extends BaseBundle implements Cloneable, Parcelable,
XmlUtils.WriteMapCallback {
+ private static final String TAG = "PersistableBundle";
+
private static final String TAG_PERSISTABLEMAP = "pbundle_as_map";
/** An unmodifiable {@code PersistableBundle} that is always {@link #isEmpty() empty}. */
@@ -110,7 +113,11 @@
* @hide
*/
public PersistableBundle(Bundle b) {
- this(b.getMap());
+ this(b, true);
+ }
+
+ private PersistableBundle(Bundle b, boolean throwException) {
+ this(b.getMap(), throwException);
}
/**
@@ -119,7 +126,7 @@
* @param map a Map containing only those items that can be persisted.
* @throws IllegalArgumentException if any element of #map cannot be persisted.
*/
- private PersistableBundle(ArrayMap<String, Object> map) {
+ private PersistableBundle(ArrayMap<String, Object> map, boolean throwException) {
super();
mFlags = FLAG_DEFUSABLE;
@@ -128,16 +135,23 @@
// Now verify each item throwing an exception if there is a violation.
final int N = mMap.size();
- for (int i=0; i<N; i++) {
+ for (int i = N - 1; i >= 0; --i) {
Object value = mMap.valueAt(i);
if (value instanceof ArrayMap) {
// Fix up any Maps by replacing them with PersistableBundles.
- mMap.setValueAt(i, new PersistableBundle((ArrayMap<String, Object>) value));
+ mMap.setValueAt(i,
+ new PersistableBundle((ArrayMap<String, Object>) value, throwException));
} else if (value instanceof Bundle) {
- mMap.setValueAt(i, new PersistableBundle(((Bundle) value)));
+ mMap.setValueAt(i, new PersistableBundle((Bundle) value, throwException));
} else if (!isValidType(value)) {
- throw new IllegalArgumentException("Bad value in PersistableBundle key="
- + mMap.keyAt(i) + " value=" + value);
+ final String errorMsg = "Bad value in PersistableBundle key="
+ + mMap.keyAt(i) + " value=" + value;
+ if (throwException) {
+ throw new IllegalArgumentException(errorMsg);
+ } else {
+ Slog.wtfStack(TAG, errorMsg);
+ mMap.removeAt(i);
+ }
}
}
}
@@ -257,6 +271,15 @@
/** @hide */
public void saveToXml(TypedXmlSerializer out) throws IOException, XmlPullParserException {
unparcel();
+ // Explicitly drop invalid types an attacker may have added before persisting.
+ for (int i = mMap.size() - 1; i >= 0; --i) {
+ final Object value = mMap.valueAt(i);
+ if (!isValidType(value)) {
+ Slog.e(TAG, "Dropping bad data before persisting: "
+ + mMap.keyAt(i) + "=" + value);
+ mMap.removeAt(i);
+ }
+ }
XmlUtils.writeMapXml(mMap, out, this);
}
@@ -311,9 +334,12 @@
while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
(event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
if (event == XmlPullParser.START_TAG) {
+ // Don't throw an exception when restoring from XML since an attacker could try to
+ // input invalid data in the persisted file.
return new PersistableBundle((ArrayMap<String, Object>)
XmlUtils.readThisArrayMapXml(in, startTag, tagName,
- new MyReadMapCallback()));
+ new MyReadMapCallback()),
+ /* throwException */ false);
}
}
return EMPTY;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
index a4b866aa..b23b431 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
@@ -182,6 +182,21 @@
return null;
}
+ /**
+ * Returns the source hint rect if it is valid (if provided and is contained by the current
+ * task bounds and not too small).
+ */
+ public static Rect getValidSourceHintRect(PictureInPictureParams params, Rect sourceBounds,
+ @NonNull Rect destinationBounds) {
+ final Rect sourceHintRect = getValidSourceHintRect(params, sourceBounds);
+ if (sourceHintRect != null
+ && sourceHintRect.width() > destinationBounds.width()
+ && sourceHintRect.height() > destinationBounds.height()) {
+ return sourceHintRect;
+ }
+ return null;
+ }
+
public float getDefaultAspectRatio() {
return mDefaultAspectRatio;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index f2bad6c..e0f542a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -564,7 +564,7 @@
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
mPipMenuController.attach(mLeash);
final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
- info.pictureInPictureParams, currentBounds);
+ info.pictureInPictureParams, currentBounds, destinationBounds);
scheduleAnimateResizePip(currentBounds, destinationBounds, 0 /* startingAngle */,
sourceHintRect, TRANSITION_DIRECTION_TO_PIP, mEnterAnimationDuration,
null /* updateBoundsCallback */);
@@ -590,9 +590,9 @@
return;
}
final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
- final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
- mPictureInPictureParams, currentBounds);
final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
+ final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
+ mPictureInPictureParams, currentBounds, destinationBounds);
animateResizePip(currentBounds, destinationBounds, sourceHintRect,
TRANSITION_DIRECTION_TO_PIP, mEnterAnimationDuration, 0 /* startingAngle */);
mState = State.ENTERING_PIP;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 4759550..8674d69 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -110,7 +110,7 @@
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
final Rect sourceHintRect =
PipBoundsAlgorithm.getValidSourceHintRect(
- taskInfo.pictureInPictureParams, currentBounds);
+ taskInfo.pictureInPictureParams, currentBounds, destinationBounds);
animator = mPipAnimationController.getAnimator(taskInfo, leash, currentBounds,
currentBounds, destinationBounds, sourceHintRect, TRANSITION_DIRECTION_TO_PIP,
0 /* startingAngle */, Surface.ROTATION_0);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index db301f6..a1d1f21 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1886,6 +1886,9 @@
cacheName = Settings.System.ALARM_ALERT_CACHE;
}
if (cacheName != null) {
+ if (!isValidAudioUri(name, value)) {
+ return false;
+ }
final File cacheFile = new File(
getRingtoneCacheDir(owningUserId), cacheName);
cacheFile.delete();
@@ -1918,6 +1921,34 @@
}
}
+ private boolean isValidAudioUri(String name, String uri) {
+ if (uri != null) {
+ Uri audioUri = Uri.parse(uri);
+ if (Settings.AUTHORITY.equals(
+ ContentProvider.getAuthorityWithoutUserId(audioUri.getAuthority()))) {
+ // Don't accept setting the default uri to self-referential URIs like
+ // Settings.System.DEFAULT_RINGTONE_URI, which is an alias to the value of this
+ // setting.
+ return false;
+ }
+ final String mimeType = getContext().getContentResolver().getType(audioUri);
+ if (mimeType == null) {
+ Slog.e(LOG_TAG,
+ "mutateSystemSetting for setting: " + name + " URI: " + audioUri
+ + " ignored: failure to find mimeType (no access from this context?)");
+ return false;
+ }
+ if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg")
+ || mimeType.equals("application/x-flac"))) {
+ Slog.e(LOG_TAG,
+ "mutateSystemSetting for setting: " + name + " URI: " + audioUri
+ + " ignored: associated mimeType: " + mimeType + " is not an audio type");
+ return false;
+ }
+ }
+ return true;
+ }
+
private boolean hasWriteSecureSettingsPermission() {
// Write secure settings is a more protected permission. If caller has it we are good.
return getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
@@ -3055,6 +3086,15 @@
return settingsState.getSettingLocked(name);
}
+ private boolean shouldExcludeSettingFromReset(Setting setting, String prefix) {
+ // If a prefix was specified, exclude settings whose names don't start with it.
+ if (prefix != null && !setting.getName().startsWith(prefix)) {
+ return true;
+ }
+ // Never reset SECURE_FRP_MODE, as it could be abused to bypass FRP via RescueParty.
+ return Secure.SECURE_FRP_MODE.equals(setting.getName());
+ }
+
public void resetSettingsLocked(int type, int userId, String packageName, int mode,
String tag) {
resetSettingsLocked(type, userId, packageName, mode, tag, /*prefix=*/
@@ -3077,7 +3117,7 @@
Setting setting = settingsState.getSettingLocked(name);
if (packageName.equals(setting.getPackageName())) {
if ((tag != null && !tag.equals(setting.getTag()))
- || (prefix != null && !setting.getName().startsWith(prefix))) {
+ || shouldExcludeSettingFromReset(setting, prefix)) {
continue;
}
if (settingsState.resetSettingLocked(name)) {
@@ -3097,7 +3137,7 @@
Setting setting = settingsState.getSettingLocked(name);
if (!SettingsState.isSystemPackage(getContext(),
setting.getPackageName())) {
- if (prefix != null && !setting.getName().startsWith(prefix)) {
+ if (shouldExcludeSettingFromReset(setting, prefix)) {
continue;
}
if (settingsState.resetSettingLocked(name)) {
@@ -3117,7 +3157,7 @@
Setting setting = settingsState.getSettingLocked(name);
if (!SettingsState.isSystemPackage(getContext(),
setting.getPackageName())) {
- if (prefix != null && !setting.getName().startsWith(prefix)) {
+ if (shouldExcludeSettingFromReset(setting, prefix)) {
continue;
}
if (setting.isDefaultFromSystem()) {
@@ -3140,7 +3180,7 @@
for (String name : settingsState.getSettingNamesLocked()) {
Setting setting = settingsState.getSettingLocked(name);
boolean someSettingChanged = false;
- if (prefix != null && !setting.getName().startsWith(prefix)) {
+ if (shouldExcludeSettingFromReset(setting, prefix)) {
continue;
}
if (setting.isDefaultFromSystem()) {
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
index f49e209..74a6127 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java
@@ -466,6 +466,31 @@
}
}
+ // To prevent FRP bypasses, the SECURE_FRP_MODE setting should not be reset when all other
+ // settings are reset. But it should still be possible to explicitly set its value.
+ @Test
+ public void testSecureFrpModeSettingCannotBeReset() throws Exception {
+ final String name = Settings.Secure.SECURE_FRP_MODE;
+ final String origValue = getSetting(SETTING_TYPE_GLOBAL, name);
+ setSettingViaShell(SETTING_TYPE_GLOBAL, name, "1", false);
+ try {
+ assertEquals("1", getSetting(SETTING_TYPE_GLOBAL, name));
+ for (int type : new int[] { SETTING_TYPE_GLOBAL, SETTING_TYPE_SECURE }) {
+ resetSettingsViaShell(type, Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
+ resetSettingsViaShell(type, Settings.RESET_MODE_UNTRUSTED_CHANGES);
+ resetSettingsViaShell(type, Settings.RESET_MODE_TRUSTED_DEFAULTS);
+ }
+ // The value should still be "1". It should not have been reset to null.
+ assertEquals("1", getSetting(SETTING_TYPE_GLOBAL, name));
+ // It should still be possible to explicitly set the value to "0".
+ setSettingViaShell(SETTING_TYPE_GLOBAL, name, "0", false);
+ assertEquals("0", getSetting(SETTING_TYPE_GLOBAL, name));
+ } finally {
+ setSettingViaShell(SETTING_TYPE_GLOBAL, name, origValue, false);
+ assertEquals(origValue, getSetting(SETTING_TYPE_GLOBAL, name));
+ }
+ }
+
private void doTestQueryStringInBracketsViaProviderApiForType(int type) {
// Make sure we have a clean slate.
deleteStringViaProviderApi(type, FAKE_SETTING_NAME);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 9a3a6ab..b2aec6b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -51,6 +51,7 @@
import com.android.systemui.Gefingerpoken;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ViewController;
@@ -196,6 +197,7 @@
mSecurityViewFlipperController.reloadColors();
}
};
+ private final DeviceProvisionedController mDeviceProvisionedController;
private KeyguardSecurityContainerController(KeyguardSecurityContainer view,
AdminSecondaryLockScreenController.Factory adminSecondaryLockScreenControllerFactory,
@@ -207,7 +209,9 @@
KeyguardStateController keyguardStateController,
SecurityCallback securityCallback,
KeyguardSecurityViewFlipperController securityViewFlipperController,
- ConfigurationController configurationController) {
+ ConfigurationController configurationController,
+ DeviceProvisionedController deviceProvisionedController
+ ) {
super(view);
mLockPatternUtils = lockPatternUtils;
mUpdateMonitor = keyguardUpdateMonitor;
@@ -221,6 +225,7 @@
mKeyguardSecurityCallback);
mConfigurationController = configurationController;
mLastOrientation = getResources().getConfiguration().orientation;
+ mDeviceProvisionedController = deviceProvisionedController;
}
@Override
@@ -391,8 +396,11 @@
case SimPuk:
// Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
- if (securityMode == SecurityMode.None || mLockPatternUtils.isLockScreenDisabled(
- KeyguardUpdateMonitor.getCurrentUser())) {
+ boolean isLockscreenDisabled = mLockPatternUtils.isLockScreenDisabled(
+ KeyguardUpdateMonitor.getCurrentUser())
+ || !mDeviceProvisionedController.isUserSetup(targetUserId);
+
+ if (securityMode == SecurityMode.None && isLockscreenDisabled) {
finish = true;
eventSubtype = BOUNCER_DISMISS_SIM;
uiEvent = BouncerUiEvent.BOUNCER_DISMISS_SIM;
@@ -552,6 +560,7 @@
private final KeyguardStateController mKeyguardStateController;
private final KeyguardSecurityViewFlipperController mSecurityViewFlipperController;
private final ConfigurationController mConfigurationController;
+ private final DeviceProvisionedController mDeviceProvisionedController;
@Inject
Factory(KeyguardSecurityContainer view,
@@ -564,7 +573,8 @@
UiEventLogger uiEventLogger,
KeyguardStateController keyguardStateController,
KeyguardSecurityViewFlipperController securityViewFlipperController,
- ConfigurationController configurationController) {
+ ConfigurationController configurationController,
+ DeviceProvisionedController deviceProvisionedController) {
mView = view;
mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory;
mLockPatternUtils = lockPatternUtils;
@@ -575,6 +585,7 @@
mKeyguardStateController = keyguardStateController;
mSecurityViewFlipperController = securityViewFlipperController;
mConfigurationController = configurationController;
+ mDeviceProvisionedController = deviceProvisionedController;
}
public KeyguardSecurityContainerController create(
@@ -583,7 +594,7 @@
mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
mKeyguardStateController, securityCallback, mSecurityViewFlipperController,
- mConfigurationController);
+ mConfigurationController, mDeviceProvisionedController);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index 6964838..b9db5b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -21,6 +21,7 @@
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutManager;
import android.os.Handler;
+import android.os.UserManager;
import android.view.accessibility.AccessibilityManager;
import com.android.internal.logging.UiEventLogger;
@@ -133,6 +134,7 @@
HighPriorityProvider highPriorityProvider,
INotificationManager notificationManager,
NotificationEntryManager notificationEntryManager,
+ UserManager userManager,
PeopleSpaceWidgetManager peopleSpaceWidgetManager,
LauncherApps launcherApps,
ShortcutManager shortcutManager,
@@ -152,6 +154,7 @@
highPriorityProvider,
notificationManager,
notificationEntryManager,
+ userManager,
peopleSpaceWidgetManager,
launcherApps,
shortcutManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
index 134f24e..d817244 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
@@ -48,6 +48,7 @@
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.UserManager;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.transition.ChangeBounds;
@@ -118,6 +119,8 @@
private NotificationGuts mGutsContainer;
private OnConversationSettingsClickListener mOnConversationSettingsClickListener;
+ private UserManager mUm;
+
@VisibleForTesting
boolean mSkipPost = false;
private int mActualHeight;
@@ -155,7 +158,9 @@
// People Tile add request.
if (mSelectedAction == ACTION_FAVORITE && getPriority() != mSelectedAction) {
mShadeController.animateCollapsePanels();
- mPeopleSpaceWidgetManager.requestPinAppWidget(mShortcutInfo, new Bundle());
+ if (mUm.isSameProfileGroup(UserHandle.USER_SYSTEM, mSbn.getNormalizedUserId())) {
+ mPeopleSpaceWidgetManager.requestPinAppWidget(mShortcutInfo, new Bundle());
+ }
}
mGutsContainer.closeControls(v, true);
};
@@ -189,6 +194,7 @@
@Action int selectedAction,
ShortcutManager shortcutManager,
PackageManager pm,
+ UserManager um,
PeopleSpaceWidgetManager peopleSpaceWidgetManager,
INotificationManager iNotificationManager,
OnUserInteractionCallback onUserInteractionCallback,
@@ -214,6 +220,7 @@
mEntry = entry;
mSbn = entry.getSbn();
mPm = pm;
+ mUm = um;
mAppName = mPackageName;
mOnSettingsClickListener = onSettingsClick;
mNotificationChannel = notificationChannel;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 4319e29..17f1fc4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -31,6 +31,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
@@ -124,6 +125,9 @@
private final INotificationManager mNotificationManager;
private final NotificationEntryManager mNotificationEntryManager;
private final PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
+
+ private final UserManager mUserManager;
+
private final LauncherApps mLauncherApps;
private final ShortcutManager mShortcutManager;
private final UserContextProvider mContextTracker;
@@ -142,6 +146,7 @@
HighPriorityProvider highPriorityProvider,
INotificationManager notificationManager,
NotificationEntryManager notificationEntryManager,
+ UserManager userManager,
PeopleSpaceWidgetManager peopleSpaceWidgetManager,
LauncherApps launcherApps,
ShortcutManager shortcutManager,
@@ -160,6 +165,7 @@
mHighPriorityProvider = highPriorityProvider;
mNotificationManager = notificationManager;
mNotificationEntryManager = notificationEntryManager;
+ mUserManager = userManager;
mPeopleSpaceWidgetManager = peopleSpaceWidgetManager;
mLauncherApps = launcherApps;
mShortcutManager = shortcutManager;
@@ -482,6 +488,7 @@
notificationInfoView.getSelectedAction(),
mShortcutManager,
pmUser,
+ mUserManager,
mPeopleSpaceWidgetManager,
mNotificationManager,
mOnUserInteractionCallback,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index 917a6f3..70825ef 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -47,6 +47,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
@@ -135,7 +136,7 @@
mView, mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
mKeyguardStateController, mKeyguardSecurityViewFlipperController,
- mConfigurationController)
+ mConfigurationController, mock(DeviceProvisionedController.class))
.create(mSecurityCallback);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
index dc6d744..f76a40f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
@@ -62,6 +62,7 @@
import android.graphics.drawable.Icon;
import android.os.Handler;
import android.os.UserHandle;
+import android.os.UserManager;
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
@@ -132,6 +133,8 @@
@Mock
private PackageManager mMockPackageManager;
@Mock
+ private UserManager mUserManager;
+ @Mock
private OnUserInteractionCallback mOnUserInteractionCallback;
@Mock
private BubblesManager mBubblesManager;
@@ -239,6 +242,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -264,6 +268,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -317,6 +322,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -343,6 +349,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -368,6 +375,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -404,6 +412,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -430,6 +439,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -460,6 +470,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -485,6 +496,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -514,6 +526,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -543,6 +556,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -575,6 +589,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -613,6 +628,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -642,6 +658,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -678,6 +695,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -707,6 +725,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -752,6 +771,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -796,6 +816,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -841,6 +862,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -879,6 +901,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -916,6 +939,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -957,6 +981,7 @@
-1, // no action selected by default
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -988,6 +1013,7 @@
NotificationConversationInfo.ACTION_FAVORITE, // "Favorite" selected by default
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -1018,6 +1044,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -1055,6 +1082,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -1092,6 +1120,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -1128,6 +1157,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -1163,6 +1193,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -1189,6 +1220,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -1210,12 +1242,14 @@
@Test
public void testSelectPriorityRequestsPinPeopleTile() {
+ when(mUserManager.isSameProfileGroup(anyInt(), anyInt())).thenReturn(true);
//WHEN channel is default importance
mNotificationChannel.setImportantConversation(false);
mNotificationInfo.bindNotification(
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -1242,11 +1276,47 @@
}
@Test
+ public void testSelectPriorityRequestsPinPeopleTile_noMultiuser() {
+ when(mUserManager.isSameProfileGroup(anyInt(), anyInt())).thenReturn(false);
+ //WHEN channel is default importance
+ mNotificationChannel.setImportantConversation(false);
+ mNotificationInfo.bindNotification(
+ -1,
+ mShortcutManager,
+ mMockPackageManager,
+ mUserManager,
+ mPeopleSpaceWidgetManager,
+ mMockINotificationManager,
+ mOnUserInteractionCallback,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ mEntry,
+ mBubbleMetadata,
+ null,
+ mIconFactory,
+ mContext,
+ true,
+ mTestHandler,
+ mTestHandler, null, Optional.of(mBubblesManager),
+ mShadeController);
+
+ // WHEN user clicks "priority"
+ mNotificationInfo.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE);
+
+ // and then done
+ mNotificationInfo.findViewById(R.id.done).performClick();
+
+ // No widget prompt; on a secondary user
+ verify(mPeopleSpaceWidgetManager, never()).requestPinAppWidget(any(), any());
+ }
+
+ @Test
public void testSelectDefaultDoesNotRequestPinPeopleTile() {
mNotificationInfo.bindNotification(
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
@@ -1282,6 +1352,7 @@
-1,
mShortcutManager,
mMockPackageManager,
+ mUserManager,
mPeopleSpaceWidgetManager,
mMockINotificationManager,
mOnUserInteractionCallback,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 9f537f5..d052a1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -54,6 +54,7 @@
import android.graphics.Color;
import android.os.Binder;
import android.os.Handler;
+import android.os.UserManager;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
@@ -141,6 +142,8 @@
@Mock private PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
@Mock private AssistantFeedbackController mAssistantFeedbackController;
+ @Mock private UserManager mUserManager;
+
@Before
public void setUp() {
mTestableLooper = TestableLooper.get(this);
@@ -158,7 +161,8 @@
mGutsManager = new NotificationGutsManager(mContext,
() -> mStatusBar, mHandler, mHandler, mAccessibilityManager, mHighPriorityProvider,
- mINotificationManager, mNotificationEntryManager, mPeopleSpaceWidgetManager,
+ mINotificationManager, mNotificationEntryManager, mUserManager,
+ mPeopleSpaceWidgetManager,
mLauncherApps, mShortcutManager, mChannelEditorDialogController, mContextTracker,
mAssistantFeedbackController, Optional.of(mBubblesManager),
new UiEventLoggerFake(), mOnUserInteractionCallback, mShadeController);
diff --git a/services/core/java/com/android/server/PendingIntentUtils.java b/services/core/java/com/android/server/PendingIntentUtils.java
index 1600101..a72a4d25 100644
--- a/services/core/java/com/android/server/PendingIntentUtils.java
+++ b/services/core/java/com/android/server/PendingIntentUtils.java
@@ -34,6 +34,7 @@
public static Bundle createDontSendToRestrictedAppsBundle(@Nullable Bundle bundle) {
final BroadcastOptions options = BroadcastOptions.makeBasic();
options.setDontSendToRestrictedApps(true);
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
if (bundle == null) {
return options.toBundle();
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bb919e7..7e629fb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2781,6 +2781,22 @@
}
}
+ /**
+ * Enforces that the uid of the caller matches the uid of the package.
+ *
+ * @param packageName the name of the package to match uid against.
+ * @param callingUid the uid of the caller.
+ * @throws SecurityException if the calling uid doesn't match uid of the package.
+ */
+ private void enforceCallingPackage(String packageName, int callingUid) {
+ final int userId = UserHandle.getUserId(callingUid);
+ final int packageUid = getPackageManagerInternal().getPackageUid(packageName,
+ /*flags=*/ 0, userId);
+ if (packageUid != callingUid) {
+ throw new SecurityException(packageName + " does not belong to uid " + callingUid);
+ }
+ }
+
@Override
public void setPackageScreenCompatMode(String packageName, int mode) {
mActivityTaskManager.setPackageScreenCompatMode(packageName, mode);
@@ -12226,13 +12242,16 @@
// A backup agent has just come up
@Override
public void backupAgentCreated(String agentPackageName, IBinder agent, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ enforceCallingPackage(agentPackageName, callingUid);
+
// Resolve the target user id and enforce permissions.
- userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid,
userId, /* allowAll */ false, ALLOW_FULL_ONLY, "backupAgentCreated", null);
if (DEBUG_BACKUP) {
Slog.v(TAG_BACKUP, "backupAgentCreated: " + agentPackageName + " = " + agent
+ " callingUserId = " + UserHandle.getCallingUserId() + " userId = " + userId
- + " callingUid = " + Binder.getCallingUid() + " uid = " + Process.myUid());
+ + " callingUid = " + callingUid + " uid = " + Process.myUid());
}
synchronized(this) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 940eb34..ee63f3b 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -34,6 +34,7 @@
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentProvider;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -1900,11 +1901,32 @@
}
if (shortcut.getIcon() != null) {
ShortcutInfo.validateIcon(shortcut.getIcon());
+ validateIconURI(shortcut);
}
shortcut.replaceFlags(shortcut.getFlags() & ShortcutInfo.FLAG_LONG_LIVED);
}
+ // Validates the calling process has permission to access shortcut icon's image uri
+ private void validateIconURI(@NonNull final ShortcutInfo si) {
+ final int callingUid = injectBinderCallingUid();
+ final Icon icon = si.getIcon();
+ if (icon == null) {
+ // There's no icon in this shortcut, nothing to validate here.
+ return;
+ }
+ int iconType = icon.getType();
+ if (iconType != Icon.TYPE_URI && iconType != Icon.TYPE_URI_ADAPTIVE_BITMAP) {
+ // The icon is not URI-based, nothing to validate.
+ return;
+ }
+ final Uri uri = icon.getUri();
+ mUriGrantsManagerInternal.checkGrantUriPermission(callingUid, si.getPackage(),
+ ContentProvider.getUriWithoutUserId(uri),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(callingUid)));
+ }
+
private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut, boolean forUpdate) {
fixUpIncomingShortcutInfo(shortcut, forUpdate, /*forPinRequest=*/ false);
}
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 de1e072..4568def 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -4620,6 +4620,49 @@
}
@Test
+ public void testVisitUris_styleExtrasWithoutStyle() {
+ Notification notification = new Notification.Builder(mContext, "a")
+ .setSmallIcon(android.R.drawable.sym_def_app_icon)
+ .build();
+
+ Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle(
+ personWithIcon("content://user"))
+ .addHistoricMessage(new Notification.MessagingStyle.Message("Heyhey!",
+ System.currentTimeMillis(),
+ personWithIcon("content://historicalMessenger")))
+ .addMessage(new Notification.MessagingStyle.Message("Are you there",
+ System.currentTimeMillis(),
+ personWithIcon("content://messenger")))
+ .setShortcutIcon(
+ Icon.createWithContentUri("content://conversationShortcut"));
+ messagingStyle.addExtras(notification.extras); // Instead of Builder.setStyle(style).
+
+ Notification.CallStyle callStyle = Notification.CallStyle.forOngoingCall(
+ personWithIcon("content://caller"),
+ PendingIntent.getActivity(mContext, 0, new Intent(),
+ PendingIntent.FLAG_IMMUTABLE))
+ .setVerificationIcon(Icon.createWithContentUri("content://callVerification"));
+ callStyle.addExtras(notification.extras); // Same.
+
+ Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
+ notification.visitUris(visitor);
+
+ verify(visitor).accept(eq(Uri.parse("content://user")));
+ verify(visitor).accept(eq(Uri.parse("content://historicalMessenger")));
+ verify(visitor).accept(eq(Uri.parse("content://messenger")));
+ verify(visitor).accept(eq(Uri.parse("content://conversationShortcut")));
+ verify(visitor).accept(eq(Uri.parse("content://caller")));
+ verify(visitor).accept(eq(Uri.parse("content://callVerification")));
+ }
+
+ private static Person personWithIcon(String iconUri) {
+ return new Person.Builder()
+ .setName("Mr " + iconUri)
+ .setIcon(Icon.createWithContentUri(iconUri))
+ .build();
+ }
+
+ @Test
public void testVisitUris_wearableExtender() {
Icon actionIcon = Icon.createWithContentUri("content://media/action");
Icon wearActionIcon = Icon.createWithContentUri("content://media/wearAction");
diff --git a/services/usb/OWNERS b/services/usb/OWNERS
index 60172a3..d35dbb56 100644
--- a/services/usb/OWNERS
+++ b/services/usb/OWNERS
@@ -1,3 +1,7 @@
+aprasath@google.com
+kumarashishg@google.com
+sarup@google.com
+anothermark@google.com
badhri@google.com
elaurent@google.com
albertccwang@google.com