summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/IntentFilter.java41
-rw-r--r--core/java/android/view/SurfaceControlViewHost.java16
-rw-r--r--core/java/android/view/SurfaceView.java19
-rw-r--r--packages/SystemUI/Android.bp4
-rw-r--r--packages/SystemUI/shared/Android.bp1
-rw-r--r--packages/SystemUI/src/com/android/systemui/Interpolators.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java79
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt56
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java110
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt62
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java7
-rw-r--r--services/core/java/com/android/server/attention/AttentionManagerService.java7
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java19
-rw-r--r--services/core/java/com/android/server/pm/AppsFilter.java87
-rw-r--r--services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java103
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java135
-rw-r--r--services/incremental/IncrementalService.cpp32
-rw-r--r--services/incremental/IncrementalService.h4
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java129
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java2
39 files changed, 702 insertions, 413 deletions
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index f951d2b89958..745add174582 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -17,6 +17,7 @@
package android.content;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
@@ -40,6 +41,7 @@ import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -766,16 +768,30 @@ public class IntentFilter implements Parcelable {
* @return True if the action is listed in the filter.
*/
public final boolean matchAction(String action) {
- return matchAction(action, false);
+ return matchAction(action, false /*wildcardSupported*/, null /*ignoreActions*/);
}
/**
* Variant of {@link #matchAction(String)} that allows a wildcard for the provided action.
* @param wildcardSupported if true, will allow action to use wildcards
- */
- private boolean matchAction(String action, boolean wildcardSupported) {
- if (wildcardSupported && !mActions.isEmpty() && WILDCARD.equals(action)) {
- return true;
+ * @param ignoreActions if not null, the set of actions to should not be considered valid while
+ * calculating the match
+ */
+ private boolean matchAction(String action, boolean wildcardSupported,
+ @Nullable Collection<String> ignoreActions) {
+ if (wildcardSupported && WILDCARD.equals(action)) {
+ if (ignoreActions == null) {
+ return !mActions.isEmpty();
+ }
+ for (int i = mActions.size() - 1; i >= 0; i--) {
+ if (!ignoreActions.contains(mActions.get(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+ if (ignoreActions != null && ignoreActions.contains(action)) {
+ return false;
}
return hasAction(action);
}
@@ -1779,17 +1795,24 @@ public class IntentFilter implements Parcelable {
*/
public final int match(String action, String type, String scheme,
Uri data, Set<String> categories, String logTag) {
- return match(action, type, scheme, data, categories, logTag, false /*supportWildcards*/);
+ return match(action, type, scheme, data, categories, logTag, false /*supportWildcards*/,
+ null /*ignoreActions*/);
}
/**
* Variant of {@link #match(ContentResolver, Intent, boolean, String)} that supports wildcards
* in the action, type, scheme, host and path.
- * @hide if true, will allow supported parameters to use wildcards to match this filter
+ * @param supportWildcards if true, will allow supported parameters to use wildcards to match
+ * this filter
+ * @param ignoreActions a collection of actions that, if not null should be ignored and not used
+ * if provided as the matching action or the set of actions defined by this
+ * filter
+ * @hide
*/
public final int match(String action, String type, String scheme,
- Uri data, Set<String> categories, String logTag, boolean supportWildcards) {
- if (action != null && !matchAction(action, supportWildcards)) {
+ Uri data, Set<String> categories, String logTag, boolean supportWildcards,
+ @Nullable Collection<String> ignoreActions) {
+ if (action != null && !matchAction(action, supportWildcards, ignoreActions)) {
if (false) Log.v(
logTag, "No matching action " + action + " for " + this);
return NO_MATCH_ACTION;
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 174165c5ba59..cfceb031539f 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -50,6 +50,22 @@ public class SurfaceControlViewHost {
* elements. It's expected to get this object from
* {@link SurfaceControlViewHost#getSurfacePackage} afterwards it can be embedded within
* a SurfaceView by calling {@link SurfaceView#setChildSurfacePackage}.
+ *
+ * Note that each {@link SurfacePackage} must be released by calling
+ * {@link SurfacePackage#release}. However, if you use the recommended flow,
+ * the framework will automatically handle the lifetime for you.
+ *
+ * 1. When sending the package to the remote process, return it from an AIDL method
+ * or manually use FLAG_WRITE_RETURN_VALUE in writeToParcel. This will automatically
+ * release the package in the local process.
+ * 2. In the remote process, consume the package using SurfaceView. This way the
+ * SurfaceView will take over the lifetime and call {@link SurfacePackage#release}
+ * for the user.
+ *
+ * One final note: The {@link SurfacePackage} lifetime is totally de-coupled
+ * from the lifetime of the underlying {@link SurfaceControlViewHost}. Regardless
+ * of the lifetime of the package the user should still call
+ * {@link SurfaceControlViewHost#release} when finished.
*/
public static final class SurfacePackage implements Parcelable {
private SurfaceControl mSurfaceControl;
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index b677ccd9a618..9880ea096cf2 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1650,11 +1650,24 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
/**
* Display the view-hierarchy embedded within a {@link SurfaceControlViewHost.SurfacePackage}
- * within this SurfaceView. If this SurfaceView is above it's host Surface (see
+ * within this SurfaceView.
+ *
+ * This can be called independently of the SurfaceView lifetime callbacks. SurfaceView
+ * will internally manage reparenting the package to our Surface as it is created
+ * and destroyed.
+ *
+ * If this SurfaceView is above its host Surface (see
* {@link #setZOrderOnTop} then the embedded Surface hierarchy will be able to receive
- * input. This will take ownership of the SurfaceControl contained inside the SurfacePackage
+ * input.
+ *
+ * This will take ownership of the SurfaceControl contained inside the SurfacePackage
* and free the caller of the obligation to call
- * {@link SurfaceControlViewHost.SurfacePackage#release}.
+ * {@link SurfaceControlViewHost.SurfacePackage#release}. However, note that
+ * {@link SurfaceControlViewHost.SurfacePackage#release} and
+ * {@link SurfaceControlViewHost#release} are not the same. While the ownership
+ * of this particular {@link SurfaceControlViewHost.SurfacePackage} will be taken by the
+ * SurfaceView the underlying {@link SurfaceControlViewHost} remains managed by it's original
+ * remote-owner.
*
* @param p The SurfacePackage to embed.
*/
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 0eadcc741747..f63365bcd369 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -45,6 +45,7 @@ android_library {
"WindowManager-Shell",
"SystemUIPluginLib",
"SystemUISharedLib",
+ "SystemUI-statsd",
"SettingsLib",
"androidx.viewpager2_viewpager2",
"androidx.legacy_legacy-support-v4",
@@ -81,6 +82,8 @@ filegroup {
"tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java",
"tests/src/com/android/systemui/statusbar/RankingBuilder.java",
"tests/src/com/android/systemui/statusbar/SbnBuilder.java",
+ "tests/src/com/android/systemui/util/concurrency/FakeExecutor.java",
+ "tests/src/com/android/systemui/util/time/FakeSystemClock.java",
],
path: "tests/src",
}
@@ -106,6 +109,7 @@ android_library {
static_libs: [
"SystemUIPluginLib",
"SystemUISharedLib",
+ "SystemUI-statsd",
"SettingsLib",
"androidx.viewpager2_viewpager2",
"androidx.legacy_legacy-support-v4",
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index fe6e44b5de0a..592f6c2a0dff 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -36,7 +36,6 @@ android_library {
static_libs: [
"PluginCoreLib",
- "SystemUI-statsd",
],
// Enforce that the library is built against java 7 so that there are
diff --git a/packages/SystemUI/src/com/android/systemui/Interpolators.java b/packages/SystemUI/src/com/android/systemui/Interpolators.java
index 13d6a9bef266..6923079dd5c4 100644
--- a/packages/SystemUI/src/com/android/systemui/Interpolators.java
+++ b/packages/SystemUI/src/com/android/systemui/Interpolators.java
@@ -49,8 +49,6 @@ public class Interpolators {
public static final Interpolator CUSTOM_40_40 = new PathInterpolator(0.4f, 0f, 0.6f, 1f);
public static final Interpolator HEADS_UP_APPEAR = new HeadsUpAppearInterpolator();
public static final Interpolator ICON_OVERSHOT = new PathInterpolator(0.4f, 0f, 0.2f, 1.4f);
- public static final Interpolator SHADE_ANIMATION =
- new PathInterpolator(0.6f, 0.02f, 0.4f, 0.98f);
public static final Interpolator ICON_OVERSHOT_LESS
= new PathInterpolator(0.4f, 0f, 0.2f, 1.1f);
public static final Interpolator PANEL_CLOSE_ACCELERATED
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 3f095dc0510e..4db5374cd566 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -1638,7 +1638,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private static final int MESSAGE_REFRESH = 1;
private static final int MESSAGE_SHOW = 2;
private static final int DIALOG_DISMISS_DELAY = 300; // ms
- private static final int DIALOG_PRESS_DELAY = 500; // ms
+ private static final int DIALOG_PRESS_DELAY = 850; // ms
@VisibleForTesting void setZeroDialogPressDelayForTesting() {
mDialogPressDelay = 0; // ms
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index bc1c1e12203e..2f582727c766 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -38,6 +38,7 @@ import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.statusbar.policy.LocationController;
import java.text.DateFormat;
import java.time.LocalTime;
@@ -60,12 +61,14 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> implements
private static final String PATTERN_HOUR_NINUTE_24 = "HH:mm";
private final ColorDisplayManager mManager;
+ private final LocationController mLocationController;
private NightDisplayListener mListener;
private boolean mIsListening;
@Inject
- public NightDisplayTile(QSHost host) {
+ public NightDisplayTile(QSHost host, LocationController locationController) {
super(host);
+ mLocationController = locationController;
mManager = mContext.getSystemService(ColorDisplayManager.class);
mListener = new NightDisplayListener(mContext, new Handler(Looper.myLooper()));
}
@@ -132,6 +135,7 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> implements
private String getSecondaryLabel(boolean isNightLightActivated) {
switch (mManager.getNightDisplayAutoMode()) {
case ColorDisplayManager.AUTO_MODE_TWILIGHT:
+ if (!mLocationController.isLocationEnabled()) return null;
// Auto mode related to sunrise & sunset. If the light is on, it's guaranteed to be
// turned off at sunrise. If it's off, it's guaranteed to be turned on at sunset.
return isNightLightActivated
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
index b90ca01df481..7b83c20d4b86 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
@@ -31,6 +31,7 @@ import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.LocationController;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
@@ -51,13 +52,15 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements
com.android.internal.R.drawable.ic_qs_ui_mode_night);
private final UiModeManager mUiModeManager;
private final BatteryController mBatteryController;
+ private final LocationController mLocationController;
@Inject
public UiModeNightTile(QSHost host, ConfigurationController configurationController,
- BatteryController batteryController) {
+ BatteryController batteryController, LocationController locationController) {
super(host);
mBatteryController = batteryController;
mUiModeManager = mContext.getSystemService(UiModeManager.class);
+ mLocationController = locationController;
configurationController.observe(getLifecycle(), this);
batteryController.observe(getLifecycle(), this);
}
@@ -97,7 +100,8 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements
if (powerSave) {
state.secondaryLabel = mContext.getResources().getString(
R.string.quick_settings_dark_mode_secondary_label_battery_saver);
- } else if (uiMode == UiModeManager.MODE_NIGHT_AUTO) {
+ } else if (uiMode == UiModeManager.MODE_NIGHT_AUTO
+ && mLocationController.isLocationEnabled()) {
state.secondaryLabel = mContext.getResources().getString(nightMode
? R.string.quick_settings_dark_mode_secondary_label_until_sunrise
: R.string.quick_settings_dark_mode_secondary_label_on_at_sunset);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 729f934937da..0d7715958995 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -21,7 +21,6 @@ import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.app.WallpaperManager
import android.util.Log
-import android.util.MathUtils
import android.view.Choreographer
import android.view.View
import androidx.annotation.VisibleForTesting
@@ -252,10 +251,7 @@ class NotificationShadeDepthController @Inject constructor(
var newBlur = 0
val state = statusBarStateController.state
if (state == StatusBarState.SHADE || state == StatusBarState.SHADE_LOCKED) {
- val animatedBlur =
- Interpolators.SHADE_ANIMATION.getInterpolation(
- MathUtils.constrain(shadeExpansion / 0.15f, 0f, 1f))
- newBlur = blurUtils.blurRadiusOfRatio(0.35f * animatedBlur + 0.65f * shadeExpansion)
+ newBlur = blurUtils.blurRadiusOfRatio(shadeExpansion)
}
shadeSpring.animateTo(newBlur)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 9324b14bf211..d37e16b17620 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -88,14 +88,11 @@ import dagger.Lazy;
* @see #getActiveNotificationUnfiltered(String) to check if a key exists
* @see #getPendingNotificationsIterator() for an iterator over the pending notifications
* @see #getPendingOrActiveNotif(String) to find a notification exists for that key in any list
- * @see #getPendingAndActiveNotifications() to get the entire set of Notifications that we're
- * aware of
* @see #getActiveNotificationsForCurrentUser() to see every notification that the current user owns
*/
public class NotificationEntryManager implements
CommonNotifCollection,
Dumpable,
- InflationCallback,
VisualStabilityManager.Callback {
private static final String TAG = "NotificationEntryMgr";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -309,12 +306,7 @@ public class NotificationEntryManager implements
*
* WARNING: this will call back into us. Don't hold any locks.
*/
- @Override
- public void handleInflationException(NotificationEntry n, Exception e) {
- handleInflationException(n.getSbn(), e);
- }
-
- public void handleInflationException(StatusBarNotification n, Exception e) {
+ private void handleInflationException(StatusBarNotification n, Exception e) {
removeNotificationInternal(
n.getKey(), null, null, true /* forceRemove */, false /* removedByUser */,
REASON_ERROR);
@@ -323,30 +315,37 @@ public class NotificationEntryManager implements
}
}
- @Override
- public void onAsyncInflationFinished(NotificationEntry entry) {
- mPendingNotifications.remove(entry.getKey());
- // If there was an async task started after the removal, we don't want to add it back to
- // the list, otherwise we might get leaks.
- if (!entry.isRowRemoved()) {
- boolean isNew = getActiveNotificationUnfiltered(entry.getKey()) == null;
- mLogger.logNotifInflated(entry.getKey(), isNew);
- if (isNew) {
- for (NotificationEntryListener listener : mNotificationEntryListeners) {
- listener.onEntryInflated(entry);
- }
- addActiveNotification(entry);
- updateNotifications("onAsyncInflationFinished");
- for (NotificationEntryListener listener : mNotificationEntryListeners) {
- listener.onNotificationAdded(entry);
- }
- } else {
- for (NotificationEntryListener listener : mNotificationEntryListeners) {
- listener.onEntryReinflated(entry);
+ private final InflationCallback mInflationCallback = new InflationCallback() {
+ @Override
+ public void handleInflationException(NotificationEntry entry, Exception e) {
+ NotificationEntryManager.this.handleInflationException(entry.getSbn(), e);
+ }
+
+ @Override
+ public void onAsyncInflationFinished(NotificationEntry entry) {
+ mPendingNotifications.remove(entry.getKey());
+ // If there was an async task started after the removal, we don't want to add it back to
+ // the list, otherwise we might get leaks.
+ if (!entry.isRowRemoved()) {
+ boolean isNew = getActiveNotificationUnfiltered(entry.getKey()) == null;
+ mLogger.logNotifInflated(entry.getKey(), isNew);
+ if (isNew) {
+ for (NotificationEntryListener listener : mNotificationEntryListeners) {
+ listener.onEntryInflated(entry);
+ }
+ addActiveNotification(entry);
+ updateNotifications("onAsyncInflationFinished");
+ for (NotificationEntryListener listener : mNotificationEntryListeners) {
+ listener.onNotificationAdded(entry);
+ }
+ } else {
+ for (NotificationEntryListener listener : mNotificationEntryListeners) {
+ listener.onEntryReinflated(entry);
+ }
}
}
}
- }
+ };
private final NotificationHandler mNotifListener = new NotificationHandler() {
@Override
@@ -558,6 +557,10 @@ public class NotificationEntryManager implements
ranking,
mFgsFeatureController.isForegroundServiceDismissalEnabled(),
SystemClock.uptimeMillis());
+ for (NotifCollectionListener listener : mNotifCollectionListeners) {
+ listener.onEntryBind(entry, notification);
+ }
+ mAllNotifications.add(entry);
mLeakDetector.trackInstance(entry);
@@ -568,8 +571,10 @@ public class NotificationEntryManager implements
// Construct the expanded view.
if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
mNotificationRowBinderLazy.get()
- .inflateViews(entry, () -> performRemoveNotification(notification,
- REASON_CANCEL));
+ .inflateViews(
+ entry,
+ () -> performRemoveNotification(notification, REASON_CANCEL),
+ mInflationCallback);
}
abortExistingInflation(key, "addNotification");
@@ -612,7 +617,9 @@ public class NotificationEntryManager implements
updateRankingAndSort(ranking, "updateNotificationInternal");
StatusBarNotification oldSbn = entry.getSbn();
entry.setSbn(notification);
- mGroupManager.onEntryUpdated(entry, oldSbn);
+ for (NotifCollectionListener listener : mNotifCollectionListeners) {
+ listener.onEntryBind(entry, notification);
+ } mGroupManager.onEntryUpdated(entry, oldSbn);
mLogger.logNotifUpdated(entry.getKey());
for (NotificationEntryListener listener : mNotificationEntryListeners) {
@@ -624,8 +631,10 @@ public class NotificationEntryManager implements
if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
mNotificationRowBinderLazy.get()
- .inflateViews(entry, () -> performRemoveNotification(notification,
- REASON_CANCEL));
+ .inflateViews(
+ entry,
+ () -> performRemoveNotification(notification, REASON_CANCEL),
+ mInflationCallback);
}
updateNotifications("updateNotificationInternal");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 365862bef871..a3621b6cabf6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -65,6 +65,7 @@ import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.notification.collection.coalescer.CoalescedEvent;
import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer.BatchableNotificationHandler;
+import com.android.systemui.statusbar.notification.collection.notifcollection.BindEntryEvent;
import com.android.systemui.statusbar.notification.collection.notifcollection.CleanUpEntryEvent;
import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
@@ -389,6 +390,7 @@ public class NotifCollection implements Dumpable {
if (entry == null) {
// A new notification!
entry = new NotificationEntry(sbn, ranking, SystemClock.uptimeMillis());
+ mEventQueue.add(new BindEntryEvent(entry, sbn));
mNotificationSet.put(sbn.getKey(), entry);
mLogger.logNotifPosted(sbn.getKey());
@@ -409,6 +411,7 @@ public class NotifCollection implements Dumpable {
entry.mCancellationReason = REASON_NOT_CANCELED;
entry.setSbn(sbn);
+ mEventQueue.add(new BindEntryEvent(entry, sbn));
mLogger.logNotifUpdated(sbn.getKey());
mEventQueue.add(new EntryUpdatedEvent(entry));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
index 1f6413b525cb..d081e114855e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
@@ -47,7 +47,6 @@ public class NotifInflaterImpl implements NotifInflater {
private final NotifPipeline mNotifPipeline;
private NotificationRowBinderImpl mNotificationRowBinder;
- private InflationCallback mExternalInflationCallback;
@Inject
public NotifInflaterImpl(
@@ -66,17 +65,11 @@ public class NotifInflaterImpl implements NotifInflater {
*/
public void setRowBinder(NotificationRowBinderImpl rowBinder) {
mNotificationRowBinder = rowBinder;
- mNotificationRowBinder.setInflationCallback(mInflationCallback);
}
@Override
- public void setInflationCallback(InflationCallback callback) {
- mExternalInflationCallback = callback;
- }
-
- @Override
- public void rebindViews(NotificationEntry entry) {
- inflateViews(entry);
+ public void rebindViews(NotificationEntry entry, InflationCallback callback) {
+ inflateViews(entry, callback);
}
/**
@@ -84,11 +77,14 @@ public class NotifInflaterImpl implements NotifInflater {
* views are bound.
*/
@Override
- public void inflateViews(NotificationEntry entry) {
+ public void inflateViews(NotificationEntry entry, InflationCallback callback) {
try {
- requireBinder().inflateViews(entry, getDismissCallback(entry));
+ requireBinder().inflateViews(
+ entry,
+ getDismissCallback(entry),
+ wrapInflationCallback(callback));
} catch (InflationException e) {
- // logged in mInflationCallback.handleInflationException
+ mNotifErrorManager.setInflationError(entry, e);
}
}
@@ -121,6 +117,26 @@ public class NotifInflaterImpl implements NotifInflater {
};
}
+ private NotificationContentInflater.InflationCallback wrapInflationCallback(
+ InflationCallback callback) {
+ return new NotificationContentInflater.InflationCallback() {
+ @Override
+ public void handleInflationException(
+ NotificationEntry entry,
+ Exception e) {
+ mNotifErrorManager.setInflationError(entry, e);
+ }
+
+ @Override
+ public void onAsyncInflationFinished(NotificationEntry entry) {
+ mNotifErrorManager.clearInflationError(entry);
+ if (callback != null) {
+ callback.onInflationFinished(entry);
+ }
+ }
+ };
+ }
+
private NotificationRowBinderImpl requireBinder() {
if (mNotificationRowBinder == null) {
throw new RuntimeException("NotificationRowBinder must be attached before using "
@@ -128,22 +144,4 @@ public class NotifInflaterImpl implements NotifInflater {
}
return mNotificationRowBinder;
}
-
- private final NotificationContentInflater.InflationCallback mInflationCallback =
- new NotificationContentInflater.InflationCallback() {
- @Override
- public void handleInflationException(
- NotificationEntry entry,
- Exception e) {
- mNotifErrorManager.setInflationError(entry, e);
- }
-
- @Override
- public void onAsyncInflationFinished(NotificationEntry entry) {
- mNotifErrorManager.clearInflationError(entry);
- if (mExternalInflationCallback != null) {
- mExternalInflationCallback.onInflationFinished(entry);
- }
- }
- };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 68ec34e90760..749c3e4c9d0d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -408,15 +408,6 @@ public final class NotificationEntry extends ListEntry {
return wasBubble != isBubble();
}
- /**
- * Resets the notification entry to be re-used.
- */
- public void reset() {
- if (row != null) {
- row.reset();
- }
- }
-
@NotificationSectionsManager.PriorityBucket
public int getBucket() {
return mBucket;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt
new file mode 100644
index 000000000000..1c1b2bb087f0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection
+
+import android.content.Context
+import android.content.pm.PackageManager
+import android.service.notification.StatusBarNotification
+import android.util.Log
+import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import com.android.systemui.statusbar.phone.StatusBar
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class TargetSdkResolver @Inject constructor(
+ private val context: Context,
+ private val collection: CommonNotifCollection
+) {
+ init {
+ collection.addCollectionListener(object : NotifCollectionListener {
+ override fun onEntryBind(entry: NotificationEntry, sbn: StatusBarNotification) {
+ entry.targetSdk = resolveNotificationSdk(sbn)
+ }
+ })
+ }
+
+ private fun resolveNotificationSdk(sbn: StatusBarNotification): Int {
+ val pmUser = StatusBar.getPackageManagerForUser(context, sbn.user.identifier)
+ var targetSdk = 0
+ // Extract target SDK version.
+ try {
+ val info = pmUser.getApplicationInfo(sbn.packageName, 0)
+ targetSdk = info.targetSdkVersion
+ } catch (ex: PackageManager.NameNotFoundException) {
+ Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.packageName, ex)
+ }
+ return targetSdk
+ }
+
+ private val TAG = "TargetSdkResolver"
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
index 9973ef9ae14e..0e8dd5e24e91 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
@@ -72,7 +72,6 @@ public class PreparationCoordinator implements Coordinator {
) {
mLogger = logger;
mNotifInflater = notifInflater;
- mNotifInflater.setInflationCallback(mInflationCallback);
mNotifErrorManager = errorManager;
mNotifErrorManager.addInflationErrorListener(mInflationErrorListener);
mViewBarn = viewBarn;
@@ -218,11 +217,11 @@ public class PreparationCoordinator implements Coordinator {
private void inflateEntry(NotificationEntry entry, String reason) {
abortInflation(entry, reason);
- mNotifInflater.inflateViews(entry);
+ mNotifInflater.inflateViews(entry, mInflationCallback);
}
private void rebind(NotificationEntry entry, String reason) {
- mNotifInflater.rebindViews(entry);
+ mNotifInflater.rebindViews(entry, mInflationCallback);
}
private void abortInflation(NotificationEntry entry, String reason) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.java
index ea0ece444a67..e3d76113d537 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.java
@@ -24,22 +24,20 @@ import com.android.systemui.statusbar.notification.collection.coordinator.Prepar
* main thread. When the inflation is finished, NotifInflater will trigger its InflationCallback.
*/
public interface NotifInflater {
-
- /**
- * Callback used when inflation is finished.
- */
- void setInflationCallback(InflationCallback callback);
-
/**
* Called to rebind the entry's views.
+ *
+ * @param callback callback called after inflation finishes
*/
- void rebindViews(NotificationEntry entry);
+ void rebindViews(NotificationEntry entry, InflationCallback callback);
/**
* Called to inflate the views of an entry. Views are not considered inflated until all of its
* views are bound. Once all views are inflated, the InflationCallback is triggered.
+ *
+ * @param callback callback called after inflation finishes
*/
- void inflateViews(NotificationEntry entry);
+ void inflateViews(NotificationEntry entry, InflationCallback callback);
/**
* Request to stop the inflation of an entry. For example, called when a notification is
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
index 3f500644b184..f4c4924b4b9a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
@@ -22,6 +22,7 @@ import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder;
/**
* Used by the {@link NotificationEntryManager}. When notifications are added or updated, the binder
@@ -37,7 +38,8 @@ public interface NotificationRowBinder {
*/
void inflateViews(
NotificationEntry entry,
- Runnable onDismissRunnable)
+ Runnable onDismissRunnable,
+ NotificationRowContentBinder.InflationCallback callback)
throws InflationException;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index 32f1822804f8..73f12f86e52e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -16,13 +16,11 @@
package com.android.systemui.statusbar.notification.collection.inflation;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.Nullable;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
import android.os.Build;
-import android.service.notification.StatusBarNotification;
-import android.util.Log;
import android.view.ViewGroup;
import com.android.internal.util.NotificationMessagingUtil;
@@ -44,9 +42,6 @@ import com.android.systemui.statusbar.notification.row.RowContentBindStage;
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.phone.StatusBar;
-
-import java.util.Objects;
import javax.inject.Inject;
import javax.inject.Provider;
@@ -72,7 +67,6 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
private NotificationPresenter mPresenter;
private NotificationListContainer mListContainer;
- private NotificationRowContentBinder.InflationCallback mInflationCallback;
private BindRowCallback mBindRowCallback;
private NotificationClicker mNotificationClicker;
@@ -113,10 +107,6 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
mIconManager.attach();
}
- public void setInflationCallback(NotificationRowContentBinder.InflationCallback callback) {
- mInflationCallback = callback;
- }
-
public void setNotificationClicker(NotificationClicker clicker) {
mNotificationClicker = clicker;
}
@@ -125,17 +115,19 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
* Inflates the views for the given entry (possibly asynchronously).
*/
@Override
- public void inflateViews(NotificationEntry entry, Runnable onDismissRunnable)
+ public void inflateViews(
+ NotificationEntry entry,
+ Runnable onDismissRunnable,
+ NotificationRowContentBinder.InflationCallback callback)
throws InflationException {
ViewGroup parent = mListContainer.getViewParentForNotification(entry);
- PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
- entry.getSbn().getUser().getIdentifier());
- final StatusBarNotification sbn = entry.getSbn();
if (entry.rowExists()) {
mIconManager.updateIcons(entry);
- entry.reset();
- updateNotification(entry, pmUser, sbn, entry.getRow());
+ ExpandableNotificationRow row = entry.getRow();
+ row.reset();
+ updateRow(entry, row);
+ inflateContentViews(entry, row, callback);
entry.getRowController().setOnDismissRunnable(onDismissRunnable);
} else {
mIconManager.createIcons(entry);
@@ -147,7 +139,6 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
.expandableNotificationRow(row)
.notificationEntry(entry)
.onDismissRunnable(onDismissRunnable)
- .inflationCallback(mInflationCallback)
.rowContentBindStage(mRowContentBindStage)
.onExpandClickListener(mPresenter)
.build();
@@ -155,26 +146,34 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
component.getExpandableNotificationRowController();
rowController.init();
entry.setRowController(rowController);
- bindRow(entry, pmUser, sbn, row);
- updateNotification(entry, pmUser, sbn, row);
+ bindRow(entry, row);
+ updateRow(entry, row);
+ inflateContentViews(entry, row, callback);
});
}
}
- //TODO: This method associates a row with an entry, but eventually needs to not do that
- private void bindRow(NotificationEntry entry, PackageManager pmUser,
- StatusBarNotification sbn, ExpandableNotificationRow row) {
+ /**
+ * Bind row to various controllers and managers. This is only called when the row is first
+ * created.
+ *
+ * TODO: This method associates a row with an entry, but eventually needs to not do that
+ */
+ private void bindRow(NotificationEntry entry, ExpandableNotificationRow row) {
mListContainer.bindRow(row);
mNotificationRemoteInputManager.bindRow(row);
+ row.setOnActivatedListener(mPresenter);
entry.setRow(row);
row.setEntry(entry);
mNotifBindPipeline.manageRow(entry, row);
- mBindRowCallback.onBindRow(entry, pmUser, sbn, row);
+ mBindRowCallback.onBindRow(row);
}
/**
* Updates the views bound to an entry when the entry's ranking changes, either in-place or by
* reinflating them.
+ *
+ * TODO: Should this method be in this class?
*/
@Override
public void onNotificationRankingUpdated(
@@ -184,11 +183,10 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
NotificationUiAdjustment newAdjustment) {
if (NotificationUiAdjustment.needReinflate(oldAdjustment, newAdjustment)) {
if (entry.rowExists()) {
- entry.reset();
- PackageManager pmUser = StatusBar.getPackageManagerForUser(
- mContext,
- entry.getSbn().getUser().getIdentifier());
- updateNotification(entry, pmUser, entry.getSbn(), entry.getRow());
+ ExpandableNotificationRow row = entry.getRow();
+ row.reset();
+ updateRow(entry, row);
+ inflateContentViews(entry, row, null /* callback */);
} else {
// Once the RowInflaterTask is done, it will pick up the updated entry, so
// no-op here.
@@ -202,59 +200,53 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
}
}
- private void updateNotification(
+ /**
+ * Update row after the notification has updated.
+ *
+ * @param entry notification that has updated
+ */
+ private void updateRow(
NotificationEntry entry,
- PackageManager pmUser,
- StatusBarNotification sbn,
ExpandableNotificationRow row) {
-
- // Extract target SDK version.
- try {
- ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
- entry.targetSdk = info.targetSdkVersion;
- } catch (PackageManager.NameNotFoundException ex) {
- Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
- }
row.setLegacy(entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
&& entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
- // TODO: should this be happening somewhere else?
- mIconManager.updateIconTags(entry, entry.targetSdk);
-
- row.setOnActivatedListener(mPresenter);
+ // bind the click event to the content area
+ requireNonNull(mNotificationClicker).register(row, entry.getSbn());
+ }
+ /**
+ * Inflate the row's basic content views.
+ */
+ private void inflateContentViews(
+ NotificationEntry entry,
+ ExpandableNotificationRow row,
+ NotificationRowContentBinder.InflationCallback inflationCallback) {
final boolean useIncreasedCollapsedHeight =
- mMessagingUtil.isImportantMessaging(sbn, entry.getImportance());
+ mMessagingUtil.isImportantMessaging(entry.getSbn(), entry.getImportance());
final boolean isLowPriority = entry.isAmbient();
RowContentBindParams params = mRowContentBindStage.getStageParams(entry);
params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
params.setUseLowPriority(entry.isAmbient());
- //TODO: Replace this API with RowContentBindParams directly
+ // TODO: Replace this API with RowContentBindParams directly. Also move to a separate
+ // redaction controller.
row.setNeedsRedaction(mNotificationLockscreenUserManager.needsRedaction(entry));
+
params.rebindAllContentViews();
mRowContentBindStage.requestRebind(entry, en -> {
row.setUsesIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
row.setIsLowPriority(isLowPriority);
- mInflationCallback.onAsyncInflationFinished(en);
+ inflationCallback.onAsyncInflationFinished(en);
});
-
- // bind the click event to the content area
- Objects.requireNonNull(mNotificationClicker).register(row, sbn);
}
/** Callback for when a row is bound to an entry. */
public interface BindRowCallback {
/**
- * Called when a new notification and row is created.
- *
- * @param entry entry for the notification
- * @param pmUser package manager for user
- * @param sbn notification
- * @param row row for the notification
+ * Called when a new row is created and bound to a notification.
*/
- void onBindRow(NotificationEntry entry, PackageManager pmUser,
- StatusBarNotification sbn, ExpandableNotificationRow row);
+ void onBindRow(ExpandableNotificationRow row);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
index 41ca52d5a626..59f119e987b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.collection.notifcollection;
import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -25,6 +26,15 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
* Listener interface for {@link NotificationEntry} events.
*/
public interface NotifCollectionListener {
+
+ /**
+ * Called when the entry is having a new status bar notification bound to it. This should
+ * be used to initialize any derivative state on the entry that needs to update when the
+ * notification is updated.
+ */
+ default void onEntryBind(NotificationEntry entry, StatusBarNotification sbn) {
+ }
+
/**
* Called whenever a new {@link NotificationEntry} is initialized. This should be used for
* initializing any decorated state tied to the notification.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt
index 2ef0368061ba..2810b891373f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.collection.notifcollection
import android.service.notification.NotificationListenerService.RankingMap
+import android.service.notification.StatusBarNotification
import com.android.systemui.statusbar.notification.collection.NotifCollection
import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -37,6 +38,15 @@ sealed class NotifEvent {
abstract fun dispatchToListener(listener: NotifCollectionListener)
}
+data class BindEntryEvent(
+ val entry: NotificationEntry,
+ val sbn: StatusBarNotification
+) : NotifEvent() {
+ override fun dispatchToListener(listener: NotifCollectionListener) {
+ listener.onEntryBind(entry, sbn)
+ }
+}
+
data class InitEntryEvent(
val entry: NotificationEntry
) : NotifEvent() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
index da8ad2da5c87..08be4f872415 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
@@ -172,18 +172,6 @@ class IconManager @Inject constructor(
}
}
- /**
- * Updates tags on the icon views to match the posting app's target SDK level
- *
- * Note that this method MUST be called after both [createIcons] and [updateIcons].
- */
- fun updateIconTags(entry: NotificationEntry, targetSdk: Int) {
- setTagOnIconViews(
- entry.icons,
- R.id.icon_is_pre_L,
- targetSdk < Build.VERSION_CODES.LOLLIPOP)
- }
-
private fun updateIconsSafe(entry: NotificationEntry) {
try {
updateIcons(entry)
@@ -259,6 +247,7 @@ class IconManager @Inject constructor(
iconView: StatusBarIconView
) {
iconView.setShowsConversation(showsConversation(entry, iconView, iconDescriptor))
+ iconView.setTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP)
if (!iconView.set(iconDescriptor)) {
throw InflationException("Couldn't create icon $iconDescriptor")
}
@@ -326,20 +315,13 @@ class IconManager @Inject constructor(
val usedInSensitiveContext =
iconView === entry.icons.shelfIcon || iconView === entry.icons.aodIcon
val isSmallIcon = iconDescriptor.icon.equals(entry.sbn.notification.smallIcon)
- return isImportantConversation(entry) && !isSmallIcon
- && (!usedInSensitiveContext || !entry.isSensitive)
+ return isImportantConversation(entry) && !isSmallIcon &&
+ (!usedInSensitiveContext || !entry.isSensitive)
}
private fun isImportantConversation(entry: NotificationEntry): Boolean {
return entry.ranking.channel != null && entry.ranking.channel.isImportantConversation
}
-
- private fun setTagOnIconViews(icons: IconPack, key: Int, tag: Any) {
- icons.statusBarIcon?.setTag(key, tag)
- icons.shelfIcon?.setTag(key, tag)
- icons.aodIcon?.setTag(key, tag)
- icons.centeredIcon?.setTag(key, tag)
- }
}
private const val TAG = "IconManager" \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index d1cceaeb6dd5..5fac5b1cf159 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -108,8 +108,6 @@ class NotificationsControllerImpl @Inject constructor(
if (featureFlags.isNewNotifPipelineRenderingEnabled) {
// TODO
} else {
- notificationRowBinder.setInflationCallback(entryManager)
-
remoteInputUriController.attach(entryManager)
groupAlertTransferHelper.bind(entryManager, groupManager)
headsUpManager.addListener(groupManager)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index 8b3d06b97882..f8d9c4648ac9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -60,7 +60,6 @@ public class ExpandableNotificationRowController {
private final HeadsUpManager mHeadsUpManager;
private final ExpandableNotificationRow.OnExpandClickListener mOnExpandClickListener;
private final StatusBarStateController mStatusBarStateController;
- private final NotificationRowContentBinder.InflationCallback mInflationCallback;
private final ExpandableNotificationRow.ExpansionLogger mExpansionLogger =
this::logNotificationExpansion;
@@ -82,7 +81,6 @@ public class ExpandableNotificationRowController {
NotificationLogger notificationLogger, HeadsUpManager headsUpManager,
ExpandableNotificationRow.OnExpandClickListener onExpandClickListener,
StatusBarStateController statusBarStateController,
- NotificationRowContentBinder.InflationCallback inflationCallback,
NotificationGutsManager notificationGutsManager,
@Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
@DismissRunnable Runnable onDismissRunnable, FalsingManager falsingManager,
@@ -101,7 +99,6 @@ public class ExpandableNotificationRowController {
mHeadsUpManager = headsUpManager;
mOnExpandClickListener = onExpandClickListener;
mStatusBarStateController = statusBarStateController;
- mInflationCallback = inflationCallback;
mNotificationGutsManager = notificationGutsManager;
mOnDismissRunnable = onDismissRunnable;
mOnAppOpsClickListener = mNotificationGutsManager::openGuts;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java
index 6d6d3e446f53..9846f2dcd170 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java
@@ -25,7 +25,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
-import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder;
import com.android.systemui.statusbar.notification.row.RowContentBindStage;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -60,8 +59,6 @@ public interface ExpandableNotificationRowComponent {
@BindsInstance
Builder rowContentBindStage(RowContentBindStage rowContentBindStage);
@BindsInstance
- Builder inflationCallback(NotificationRowContentBinder.InflationCallback inflationCallback);
- @BindsInstance
Builder onExpandClickListener(ExpandableNotificationRow.OnExpandClickListener presenter);
ExpandableNotificationRowComponent build();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 79cea91b8612..aecbb9097c7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -22,7 +22,6 @@ import static com.android.systemui.statusbar.phone.StatusBar.SPEW;
import android.annotation.Nullable;
import android.app.KeyguardManager;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.service.notification.StatusBarNotification;
@@ -355,8 +354,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
}
@Override
- public void onBindRow(NotificationEntry entry, PackageManager pmUser,
- StatusBarNotification sbn, ExpandableNotificationRow row) {
+ public void onBindRow(ExpandableNotificationRow row) {
row.setAboveShelfChangedListener(mAboveShelfObserver);
row.setSecureStateProvider(mKeyguardStateController::canDismissLockScreen);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt
deleted file mode 100644
index d522f903c83a..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification
-
-import com.android.systemui.statusbar.FeatureFlags
-import com.android.systemui.statusbar.NotificationPresenter
-import com.android.systemui.statusbar.NotificationRemoteInputManager
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.NotificationRankingManager
-import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder
-import com.android.systemui.statusbar.phone.NotificationGroupManager
-import com.android.systemui.util.leak.LeakDetector
-import java.util.concurrent.CountDownLatch
-
-/**
- * Enable some test capabilities for NEM without making everything public on the base class
- */
-class TestableNotificationEntryManager(
- logger: NotificationEntryManagerLogger,
- gm: NotificationGroupManager,
- rm: NotificationRankingManager,
- ke: KeyguardEnvironment,
- ff: FeatureFlags,
- rb: dagger.Lazy<NotificationRowBinder>,
- notificationRemoteInputManagerLazy: dagger.Lazy<NotificationRemoteInputManager>,
- leakDetector: LeakDetector,
- fgsFeatureController: ForegroundServiceDismissalFeatureController
-) : NotificationEntryManager(logger, gm, rm, ke, ff, rb,
- notificationRemoteInputManagerLazy, leakDetector, fgsFeatureController) {
-
- public var countDownLatch: CountDownLatch = CountDownLatch(1)
-
- override fun onAsyncInflationFinished(entry: NotificationEntry) {
- super.onAsyncInflationFinished(entry)
- countDownLatch.countDown()
- }
-
- fun setUpForTest(
- presenter: NotificationPresenter?
- ) {
- super.setUpWithPresenter(presenter)
- }
-
- fun setActiveNotificationList(activeList: List<NotificationEntry>) {
- mSortedAndFiltered.clear()
- mSortedAndFiltered.addAll(activeList)
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
index 6b9e43bcb290..35b31c01fd9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -62,7 +63,6 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
private OnBeforeFinalizeFilterListener mBeforeFilterListener;
private NotifFilter mUninflatedFilter;
private NotifFilter mInflationErrorFilter;
- private NotifInflaterImpl.InflationCallback mCallback;
private NotifInflationErrorManager mErrorManager;
private NotificationEntry mEntry;
private Exception mInflationError;
@@ -104,9 +104,6 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
mBeforeFilterListenerCaptor.capture());
mBeforeFilterListener = mBeforeFilterListenerCaptor.getValue();
- verify(mNotifInflater).setInflationCallback(mCallbackCaptor.capture());
- mCallback = mCallbackCaptor.getValue();
-
mCollectionListener.onEntryInit(mEntry);
}
@@ -142,7 +139,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry));
// THEN we inflate it
- verify(mNotifInflater).inflateViews(mEntry);
+ verify(mNotifInflater).inflateViews(eq(mEntry), any());
// THEN we filter it out until it's done inflating.
assertTrue(mUninflatedFilter.shouldFilterOut(mEntry, 0));
@@ -151,14 +148,17 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
@Test
public void testRebindsInflatedNotificationsOnUpdate() {
// GIVEN an inflated notification
- mCallback.onInflationFinished(mEntry);
+ mCollectionListener.onEntryAdded(mEntry);
+ mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry));
+ verify(mNotifInflater).inflateViews(eq(mEntry), mCallbackCaptor.capture());
+ mCallbackCaptor.getValue().onInflationFinished(mEntry);
// WHEN notification is updated
mCollectionListener.onEntryUpdated(mEntry);
mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry));
// THEN we rebind it
- verify(mNotifInflater).rebindViews(mEntry);
+ verify(mNotifInflater).rebindViews(eq(mEntry), any());
// THEN we do not filter it because it's not the first inflation.
assertFalse(mUninflatedFilter.shouldFilterOut(mEntry, 0));
@@ -166,8 +166,11 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
@Test
public void testDoesntFilterInflatedNotifs() {
- // WHEN a notification is inflated
- mCallback.onInflationFinished(mEntry);
+ // GIVEN an inflated notification
+ mCollectionListener.onEntryAdded(mEntry);
+ mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry));
+ verify(mNotifInflater).inflateViews(eq(mEntry), mCallbackCaptor.capture());
+ mCallbackCaptor.getValue().onInflationFinished(mEntry);
// THEN it isn't filtered from shade list
assertFalse(mUninflatedFilter.shouldFilterOut(mEntry, 0));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index 1c6e5a36bd8a..855f524db3f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -23,7 +23,6 @@ import static com.android.systemui.statusbar.notification.row.NotificationRowCon
import static junit.framework.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -216,9 +215,6 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
.onDismissRunnable(any()))
.thenReturn(mExpandableNotificationRowComponentBuilder);
when(mExpandableNotificationRowComponentBuilder
- .inflationCallback(any()))
- .thenReturn(mExpandableNotificationRowComponentBuilder);
- when(mExpandableNotificationRowComponentBuilder
.rowContentBindStage(any()))
.thenReturn(mExpandableNotificationRowComponentBuilder);
when(mExpandableNotificationRowComponentBuilder
@@ -243,7 +239,6 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
mHeadsUpManager,
mPresenter,
mStatusBarStateController,
- mEntryManager,
mGutsManager,
true,
null,
@@ -275,7 +270,6 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
mEntryManager.addNotificationEntryListener(mEntryListener);
mRowBinder.setUpWithPresenter(mPresenter, mListContainer, mBindCallback);
- mRowBinder.setInflationCallback(mEntryManager);
mRowBinder.setNotificationClicker(mock(NotificationClicker.class));
Ranking ranking = new Ranking();
@@ -330,7 +324,7 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
assertNotNull(entry.getRow().getPrivateLayout().getContractedChild());
// THEN inflation callbacks are called
- verify(mBindCallback).onBindRow(eq(entry), any(), eq(mSbn), any());
+ verify(mBindCallback).onBindRow(entry.getRow());
verify(mEntryListener, never()).onInflationError(any(), any());
verify(mEntryListener).onEntryInflated(entry);
verify(mEntryListener).onNotificationAdded(entry);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index ef2071ef090e..657bc8d614cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -69,7 +69,6 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
-import com.android.systemui.statusbar.notification.TestableNotificationEntryManager;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -138,7 +137,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private FeatureFlags mFeatureFlags;
private UserChangedListener mUserChangedListener;
- private TestableNotificationEntryManager mEntryManager;
+ private NotificationEntryManager mEntryManager;
private int mOriginalInterruptionModelSetting;
private UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake();
@@ -167,7 +166,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
ArgumentCaptor<UserChangedListener> userChangedCaptor = ArgumentCaptor
.forClass(UserChangedListener.class);
- mEntryManager = new TestableNotificationEntryManager(
+ mEntryManager = new NotificationEntryManager(
mock(NotificationEntryManagerLogger.class),
mock(NotificationGroupManager.class),
new NotificationRankingManager(
@@ -187,7 +186,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
mock(LeakDetector.class),
mock(ForegroundServiceDismissalFeatureController.class)
);
- mEntryManager.setUpForTest(mock(NotificationPresenter.class));
+ mEntryManager.setUpWithPresenter(mock(NotificationPresenter.class));
when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
NotificationShelf notificationShelf = mock(NotificationShelf.class);
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 50ec0400a729..e8acbd493180 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -165,7 +165,7 @@ public class AttentionManagerService extends SystemService {
* Returns {@code true} if attention service is supported on this device.
*/
private boolean isAttentionServiceSupported() {
- return isServiceEnabled() && isServiceAvailable();
+ return isServiceEnabled() && isServiceConfigured(mContext);
}
@VisibleForTesting
@@ -210,6 +210,11 @@ public class AttentionManagerService extends SystemService {
return false;
}
+ if (!isServiceAvailable()) {
+ Slog.w(LOG_TAG, "Service is not available at this moment.");
+ return false;
+ }
+
// don't allow attention check in screen off state
if (!mPowerManager.isInteractive()) {
return false;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 173dfc244fe5..ec941c8aea59 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -800,7 +800,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
enableFirewallChainUL(FIREWALL_CHAIN_STANDBY, true);
- setRestrictBackgroundUL(mLoadedRestrictBackground);
+ setRestrictBackgroundUL(mLoadedRestrictBackground, "init_service");
updateRulesForGlobalChangeAL(false);
updateNotificationsNL();
}
@@ -2877,10 +2877,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setRestrictBackground");
try {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+ final int callingUid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
synchronized (mUidRulesFirstLock) {
- setRestrictBackgroundUL(restrictBackground);
+ setRestrictBackgroundUL(restrictBackground, "uid:" + callingUid);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -2891,7 +2892,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@GuardedBy("mUidRulesFirstLock")
- private void setRestrictBackgroundUL(boolean restrictBackground) {
+ private void setRestrictBackgroundUL(boolean restrictBackground, String reason) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setRestrictBackgroundUL");
try {
if (restrictBackground == mRestrictBackground) {
@@ -2899,7 +2900,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
Slog.w(TAG, "setRestrictBackgroundUL: already " + restrictBackground);
return;
}
- Slog.d(TAG, "setRestrictBackgroundUL(): " + restrictBackground);
+ Slog.d(TAG, "setRestrictBackgroundUL(): " + restrictBackground + "; reason: " + reason);
final boolean oldRestrictBackground = mRestrictBackground;
mRestrictBackground = restrictBackground;
// Must whitelist foreground apps before turning data saver mode on.
@@ -3425,7 +3426,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
fout.print("Restrict background: "); fout.println(mRestrictBackground);
fout.print("Restrict power: "); fout.println(mRestrictPower);
fout.print("Device idle: "); fout.println(mDeviceIdleMode);
- fout.print("Metered ifaces: "); fout.println(String.valueOf(mMeteredIfaces));
+ fout.print("Metered ifaces: "); fout.println(mMeteredIfaces);
+
+ fout.println();
+ fout.print("mRestrictBackgroundLowPowerMode: " + mRestrictBackgroundLowPowerMode);
+ fout.print("mRestrictBackgroundBeforeBsm: " + mRestrictBackgroundBeforeBsm);
+ fout.print("mLoadedRestrictBackground: " + mLoadedRestrictBackground);
+ fout.print("mRestrictBackgroundChangedInBsm: " + mRestrictBackgroundChangedInBsm);
fout.println();
fout.println("Network policies:");
@@ -5020,7 +5027,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
if (shouldInvokeRestrictBackground) {
- setRestrictBackgroundUL(restrictBackground);
+ setRestrictBackgroundUL(restrictBackground, "low_power");
}
// Change it at last so setRestrictBackground() won't affect this variable
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 09b782d768d2..7c47cf0450d4 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -113,6 +113,7 @@ public class AppsFilter {
private final OverlayReferenceMapper mOverlayReferenceMapper;
private PackageParser.SigningDetails mSystemSigningDetails;
+ private Set<String> mProtectedBroadcasts = new ArraySet<>();
AppsFilter(FeatureConfig featureConfig, String[] forceQueryableWhitelist,
boolean systemAppsQueryable,
@@ -298,10 +299,10 @@ public class AppsFilter {
/** Returns true if the querying package may query for the potential target package */
private static boolean canQueryViaComponents(AndroidPackage querying,
- AndroidPackage potentialTarget) {
+ AndroidPackage potentialTarget, Set<String> protectedBroadcasts) {
if (!querying.getQueriesIntents().isEmpty()) {
for (Intent intent : querying.getQueriesIntents()) {
- if (matchesIntentFilters(intent, potentialTarget)) {
+ if (matchesIntentFilters(intent, potentialTarget, protectedBroadcasts)) {
return true;
}
}
@@ -353,13 +354,14 @@ public class AppsFilter {
return false;
}
- private static boolean matchesIntentFilters(Intent intent, AndroidPackage potentialTarget) {
+ private static boolean matchesIntentFilters(Intent intent, AndroidPackage potentialTarget,
+ Set<String> protectedBroadcasts) {
for (int s = ArrayUtils.size(potentialTarget.getServices()) - 1; s >= 0; s--) {
ParsedService service = potentialTarget.getServices().get(s);
if (!service.isExported()) {
continue;
}
- if (matchesAnyFilter(intent, service)) {
+ if (matchesAnyFilter(intent, service, null /*protectedBroadcasts*/)) {
return true;
}
}
@@ -368,7 +370,8 @@ public class AppsFilter {
if (!activity.isExported()) {
continue;
}
- if (matchesAnyFilter(intent, activity)) {
+
+ if (matchesAnyFilter(intent, activity, null /*protectedBroadcasts*/)) {
return true;
}
}
@@ -377,25 +380,32 @@ public class AppsFilter {
if (!receiver.isExported()) {
continue;
}
- if (matchesAnyFilter(intent, receiver)) {
+ if (matchesAnyFilter(intent, receiver, protectedBroadcasts)) {
return true;
}
}
return false;
}
- private static boolean matchesAnyFilter(Intent intent, ParsedComponent component) {
+ private static boolean matchesAnyFilter(Intent intent, ParsedComponent component,
+ Set<String> protectedBroadcasts) {
List<ParsedIntentInfo> intents = component.getIntents();
for (int i = ArrayUtils.size(intents) - 1; i >= 0; i--) {
IntentFilter intentFilter = intents.get(i);
- if (intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(),
- intent.getData(), intent.getCategories(), "AppsFilter", true) > 0) {
+ if (matchesIntentFilter(intent, intentFilter, protectedBroadcasts)) {
return true;
}
}
return false;
}
+ private static boolean matchesIntentFilter(Intent intent, IntentFilter intentFilter,
+ @Nullable Set<String> protectedBroadcasts) {
+ return intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(),
+ intent.getData(), intent.getCategories(), "AppsFilter", true, protectedBroadcasts)
+ > 0;
+ }
+
/**
* Grants access based on an interaction between a calling and target package, granting
* visibility of the caller from the target.
@@ -434,6 +444,12 @@ public class AppsFilter {
}
}
}
+
+ if (!newPkgSetting.pkg.getProtectedBroadcasts().isEmpty()) {
+ mProtectedBroadcasts.addAll(newPkgSetting.pkg.getProtectedBroadcasts());
+ recomputeComponentVisibility(existingSettings, newPkgSetting.pkg.getPackageName());
+ }
+
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
try {
final AndroidPackage newPkg = newPkgSetting.pkg;
@@ -464,7 +480,7 @@ public class AppsFilter {
final AndroidPackage existingPkg = existingSetting.pkg;
// let's evaluate the ability of already added packages to see this new package
if (!newIsForceQueryable) {
- if (canQueryViaComponents(existingPkg, newPkg)) {
+ if (canQueryViaComponents(existingPkg, newPkg, mProtectedBroadcasts)) {
mQueriesViaComponent.add(existingSetting.appId, newPkgSetting.appId);
}
if (canQueryViaPackage(existingPkg, newPkg)
@@ -474,7 +490,7 @@ public class AppsFilter {
}
// now we'll evaluate our new package's ability to see existing packages
if (!mForceQueryable.contains(existingSetting.appId)) {
- if (canQueryViaComponents(newPkg, existingPkg)) {
+ if (canQueryViaComponents(newPkg, existingPkg, mProtectedBroadcasts)) {
mQueriesViaComponent.add(newPkgSetting.appId, existingSetting.appId);
}
if (canQueryViaPackage(newPkg, existingPkg)
@@ -511,10 +527,47 @@ public class AppsFilter {
&& pkgSetting.signatures.mSigningDetails.signaturesMatchExactly(sysSigningDetails);
}
- private static void sort(int[] uids, int nextUidIndex) {
- Arrays.sort(uids, 0, nextUidIndex);
+ private ArraySet<String> collectProtectedBroadcasts(
+ ArrayMap<String, PackageSetting> existingSettings, @Nullable String excludePackage) {
+ ArraySet<String> ret = new ArraySet<>();
+ for (int i = existingSettings.size() - 1; i >= 0; i--) {
+ PackageSetting setting = existingSettings.valueAt(i);
+ if (setting.pkg == null || setting.pkg.getPackageName().equals(excludePackage)) {
+ continue;
+ }
+ final List<String> protectedBroadcasts = setting.pkg.getProtectedBroadcasts();
+ if (!protectedBroadcasts.isEmpty()) {
+ ret.addAll(protectedBroadcasts);
+ }
+ }
+ return ret;
}
+ private void recomputeComponentVisibility(ArrayMap<String, PackageSetting> existingSettings,
+ @Nullable String excludePackage) {
+ mQueriesViaComponent.clear();
+ for (int i = existingSettings.size() - 1; i >= 0; i--) {
+ PackageSetting setting = existingSettings.valueAt(i);
+ if (setting.pkg == null
+ || setting.pkg.getPackageName().equals(excludePackage)
+ || mForceQueryable.contains(setting.appId)) {
+ continue;
+ }
+ for (int j = existingSettings.size() - 1; j >= 0; j--) {
+ if (i == j) {
+ continue;
+ }
+ final PackageSetting otherSetting = existingSettings.valueAt(j);
+ if (otherSetting.pkg == null
+ || otherSetting.pkg.getPackageName().equals(excludePackage)) {
+ continue;
+ }
+ if (canQueryViaComponents(setting.pkg, otherSetting.pkg, mProtectedBroadcasts)) {
+ mQueriesViaComponent.add(setting.appId, otherSetting.appId);
+ }
+ }
+ }
+ }
/**
* Fetches all app Ids that a given setting is currently visible to, per provided user. This
* only includes UIDs >= {@link Process#FIRST_APPLICATION_UID} as all other UIDs can already see
@@ -608,6 +661,14 @@ public class AppsFilter {
}
}
+ if (!setting.pkg.getProtectedBroadcasts().isEmpty()) {
+ final String removingPackageName = setting.pkg.getPackageName();
+ mProtectedBroadcasts.clear();
+ mProtectedBroadcasts.addAll(
+ collectProtectedBroadcasts(existingSettings, removingPackageName));
+ recomputeComponentVisibility(existingSettings, removingPackageName);
+ }
+
mOverlayReferenceMapper.removePkg(setting.name);
mFeatureConfig.updatePackageState(setting, true /*removed*/);
}
diff --git a/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java b/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java
index 976ce1f3dde0..1c4568095ce3 100644
--- a/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java
+++ b/services/core/java/com/android/server/pm/permission/OneTimePermissionUserManager.java
@@ -21,9 +21,14 @@ import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHE
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.AlarmManager;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.os.Handler;
import android.permission.PermissionControllerManager;
+import android.provider.DeviceConfig;
import android.util.Log;
import android.util.SparseArray;
@@ -36,7 +41,10 @@ public class OneTimePermissionUserManager {
private static final String LOG_TAG = OneTimePermissionUserManager.class.getSimpleName();
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
+ private static final long DEFAULT_KILLED_DELAY_MILLIS = 5000;
+ public static final String PROPERTY_KILLED_DELAY_CONFIG_KEY =
+ "one_time_permissions_killed_delay_millis";
private final @NonNull Context mContext;
private final @NonNull ActivityManager mActivityManager;
@@ -45,15 +53,37 @@ public class OneTimePermissionUserManager {
private final Object mLock = new Object();
+ private final BroadcastReceiver mUninstallListener = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_UID_REMOVED.equals(intent.getAction())) {
+ int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+ PackageInactivityListener listener = mListeners.get(uid);
+ if (listener != null) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Removing the inactivity listener for " + uid);
+ }
+ listener.cancel();
+ mListeners.remove(uid);
+ }
+ }
+ }
+ };
+
/** Maps the uid to the PackageInactivityListener */
@GuardedBy("mLock")
private final SparseArray<PackageInactivityListener> mListeners = new SparseArray<>();
+ private final Handler mHandler;
OneTimePermissionUserManager(@NonNull Context context) {
mContext = context;
mActivityManager = context.getSystemService(ActivityManager.class);
mAlarmManager = context.getSystemService(AlarmManager.class);
mPermissionControllerManager = context.getSystemService(PermissionControllerManager.class);
+ mHandler = context.getMainThreadHandler();
+
+ // Listen for tracked uid being uninstalled
+ context.registerReceiver(mUninstallListener, new IntentFilter(Intent.ACTION_UID_REMOVED));
}
/**
@@ -132,6 +162,15 @@ public class OneTimePermissionUserManager {
}
/**
+ * The delay to wait before revoking on the event an app is terminated. Recommended to be long
+ * enough so that apps don't lose permission on an immediate restart
+ */
+ private static long getKilledDelayMillis() {
+ return DeviceConfig.getLong(DeviceConfig.NAMESPACE_PERMISSIONS,
+ PROPERTY_KILLED_DELAY_CONFIG_KEY, DEFAULT_KILLED_DELAY_MILLIS);
+ }
+
+ /**
* A class which watches a package for inactivity and notifies the permission controller when
* the package becomes inactive
*/
@@ -155,16 +194,15 @@ public class OneTimePermissionUserManager {
private final ActivityManager.OnUidImportanceListener mGoneListener;
private final Object mInnerLock = new Object();
+ private final Object mToken = new Object();
private PackageInactivityListener(int uid, @NonNull String packageName, long timeout,
int importanceToResetTimer, int importanceToKeepSessionAlive) {
- if (DEBUG) {
- Log.d(LOG_TAG,
- "Start tracking " + packageName + ". uid=" + uid + " timeout=" + timeout
- + " importanceToResetTimer=" + importanceToResetTimer
- + " importanceToKeepSessionAlive=" + importanceToKeepSessionAlive);
- }
+ Log.i(LOG_TAG,
+ "Start tracking " + packageName + ". uid=" + uid + " timeout=" + timeout
+ + " importanceToResetTimer=" + importanceToResetTimer
+ + " importanceToKeepSessionAlive=" + importanceToKeepSessionAlive);
mUid = uid;
mPackageName = packageName;
@@ -193,18 +231,34 @@ public class OneTimePermissionUserManager {
return;
}
-
- if (DEBUG) {
- Log.d(LOG_TAG, "Importance changed for " + mPackageName + " (" + mUid + ")."
- + " importance=" + importance);
- }
+ Log.v(LOG_TAG, "Importance changed for " + mPackageName + " (" + mUid + ")."
+ + " importance=" + importance);
synchronized (mInnerLock) {
+ // Remove any pending inactivity callback
+ mHandler.removeCallbacksAndMessages(mToken);
+
if (importance > IMPORTANCE_CACHED) {
- onPackageInactiveLocked();
+ // Delay revocation in case app is restarting
+ mHandler.postDelayed(() -> {
+ int imp = mActivityManager.getUidImportance(mUid);
+ if (imp > IMPORTANCE_CACHED) {
+ onPackageInactiveLocked();
+ } else {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "No longer gone after delayed revocation. "
+ + "Rechecking for " + mPackageName + " (" + mUid + ").");
+ }
+ onImportanceChanged(mUid, imp);
+ }
+ }, mToken, getKilledDelayMillis());
return;
}
if (importance > mImportanceToResetTimer) {
if (mTimerStart == TIMER_INACTIVE) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Start the timer for "
+ + mPackageName + " (" + mUid + ").");
+ }
mTimerStart = System.currentTimeMillis();
}
} else {
@@ -240,10 +294,13 @@ public class OneTimePermissionUserManager {
return;
}
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Scheduling alarm for " + mPackageName + " (" + mUid + ").");
+ }
long revokeTime = mTimerStart + mTimeout;
if (revokeTime > System.currentTimeMillis()) {
mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, revokeTime, LOG_TAG, this,
- mContext.getMainThreadHandler());
+ mHandler);
mIsAlarmSet = true;
} else {
mIsAlarmSet = true;
@@ -257,6 +314,9 @@ public class OneTimePermissionUserManager {
@GuardedBy("mInnerLock")
private void cancelAlarmLocked() {
if (mIsAlarmSet) {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Canceling alarm for " + mPackageName + " (" + mUid + ").");
+ }
mAlarmManager.cancel(this);
mIsAlarmSet = false;
}
@@ -270,14 +330,16 @@ public class OneTimePermissionUserManager {
if (mIsFinished) {
return;
}
+ if (DEBUG) {
+ Log.d(LOG_TAG, "onPackageInactiveLocked stack trace for "
+ + mPackageName + " (" + mUid + ").", new RuntimeException());
+ }
mIsFinished = true;
cancelAlarmLocked();
- mContext.getMainThreadHandler().post(
+ mHandler.post(
() -> {
- if (DEBUG) {
- Log.d(LOG_TAG, "One time session expired for "
- + mPackageName + " (" + mUid + ").");
- }
+ Log.i(LOG_TAG, "One time session expired for "
+ + mPackageName + " (" + mUid + ").");
mPermissionControllerManager.notifyOneTimePermissionSessionTimeout(
mPackageName);
@@ -292,6 +354,9 @@ public class OneTimePermissionUserManager {
@Override
public void onAlarm() {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Alarm received for " + mPackageName + " (" + mUid + ").");
+ }
synchronized (mInnerLock) {
if (!mIsAlarmSet) {
return;
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 b7c9ecb604f8..ccc749232dc3 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -2519,7 +2519,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M;
String upgradedActivityRecognitionPermission = null;
- if (DEBUG_INSTALL) {
+ if (DEBUG_INSTALL && bp != null) {
Log.i(TAG, "Package " + pkg.getPackageName()
+ " checking " + permName + ": " + bp);
}
@@ -3881,8 +3881,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
*/
private void updatePermissions(@NonNull String packageName, @Nullable AndroidPackage pkg,
@NonNull PermissionCallback callback) {
+ // If the package is being deleted, update the permissions of all the apps
final int flags =
- (pkg != null ? UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG : 0);
+ (pkg == null ? UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG
+ : UPDATE_PERMISSIONS_REPLACE_PKG);
updatePermissions(
packageName, pkg, getVolumeUuidForPackage(pkg), flags, callback);
}
@@ -4007,6 +4009,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (permissionTreesSourcePackageChanged | permissionSourcePackageChanged) {
// Permission ownership has changed. This e.g. changes which packages can get signature
// permissions
+ Slog.i(TAG, "Permission ownership changed. Updating all permissions.");
flags |= UPDATE_PERMISSIONS_ALL;
}
@@ -4057,8 +4060,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private boolean updatePermissionSourcePackage(@Nullable String packageName,
@Nullable AndroidPackage pkg,
final @Nullable PermissionCallback callback) {
- boolean changed = false;
+ // Always need update if packageName is null
+ if (packageName == null) {
+ return true;
+ }
+ boolean changed = false;
Set<BasePermission> needsUpdate = null;
synchronized (mLock) {
final Iterator<BasePermission> it = mSettings.mPermissions.values().iterator();
@@ -4067,54 +4074,29 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (bp.isDynamic()) {
bp.updateDynamicPermission(mSettings.mPermissionTrees.values());
}
- if (bp.getSourcePackageSetting() != null) {
- if (packageName != null && packageName.equals(bp.getSourcePackageName())
- && (pkg == null || !hasPermission(pkg, bp.getName()))) {
- Slog.i(TAG, "Removing permission " + bp.getName()
- + " that used to be declared by " + bp.getSourcePackageName());
- if (bp.isRuntime()) {
- final int[] userIds = mUserManagerInt.getUserIds();
- final int numUserIds = userIds.length;
- for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
- final int userId = userIds[userIdNum];
-
- mPackageManagerInt.forEachPackage((AndroidPackage p) -> {
- final String pName = p.getPackageName();
- final ApplicationInfo appInfo =
- mPackageManagerInt.getApplicationInfo(pName, 0,
- Process.SYSTEM_UID, UserHandle.USER_SYSTEM);
- if (appInfo != null
- && appInfo.targetSdkVersion < Build.VERSION_CODES.M) {
- return;
- }
-
- final String permissionName = bp.getName();
- if (checkPermissionImpl(permissionName, pName, userId)
- == PackageManager.PERMISSION_GRANTED) {
- try {
- revokeRuntimePermissionInternal(
- permissionName,
- pName,
- false,
- Process.SYSTEM_UID,
- userId,
- callback);
- } catch (IllegalArgumentException e) {
- Slog.e(TAG,
- "Failed to revoke "
- + permissionName
- + " from "
- + pName,
- e);
- }
- }
- });
- }
+ if (bp.getSourcePackageSetting() == null
+ || !packageName.equals(bp.getSourcePackageName())) {
+ continue;
+ }
+ // The target package is the source of the current permission
+ // Set to changed for either install or uninstall
+ changed = true;
+ // If the target package is being uninstalled, we need to revoke this permission
+ // From all other packages
+ if (pkg == null || !hasPermission(pkg, bp.getName())) {
+ Slog.i(TAG, "Removing permission " + bp.getName()
+ + " that used to be declared by " + bp.getSourcePackageName());
+ if (bp.isRuntime()) {
+ final int[] userIds = mUserManagerInt.getUserIds();
+ final int numUserIds = userIds.length;
+ for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
+ final int userId = userIds[userIdNum];
+ mPackageManagerInt.forEachPackage((AndroidPackage p) ->
+ revokePermissionFromPackageForUser(p.getPackageName(),
+ bp.getName(), userId, callback));
}
- changed = true;
- it.remove();
}
- continue;
+ it.remove();
}
if (needsUpdate == null) {
needsUpdate = new ArraySet<>(mSettings.mPermissions.size());
@@ -4146,6 +4128,39 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
/**
+ * Revoke a runtime permission from a package for a given user ID.
+ */
+ private void revokePermissionFromPackageForUser(@NonNull String pName,
+ @NonNull String permissionName, int userId, @Nullable PermissionCallback callback) {
+ final ApplicationInfo appInfo =
+ mPackageManagerInt.getApplicationInfo(pName, 0,
+ Process.SYSTEM_UID, UserHandle.USER_SYSTEM);
+ if (appInfo != null
+ && appInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+ return;
+ }
+
+ if (checkPermissionImpl(permissionName, pName, userId)
+ == PackageManager.PERMISSION_GRANTED) {
+ try {
+ revokeRuntimePermissionInternal(
+ permissionName,
+ pName,
+ false,
+ Process.SYSTEM_UID,
+ userId,
+ callback);
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG,
+ "Failed to revoke "
+ + permissionName
+ + " from "
+ + pName,
+ e);
+ }
+ }
+ }
+ /**
* Update which app owns a permission trees.
*
* <p>Possible parameter combinations
@@ -4164,6 +4179,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
*/
private boolean updatePermissionTreeSourcePackage(@Nullable String packageName,
@Nullable AndroidPackage pkg) {
+ // Always need update if packageName is null
+ if (packageName == null) {
+ return true;
+ }
boolean changed = false;
Set<BasePermission> needsUpdate = null;
@@ -4171,16 +4190,18 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
while (it.hasNext()) {
final BasePermission bp = it.next();
- if (bp.getSourcePackageSetting() != null) {
- if (packageName != null && packageName.equals(bp.getSourcePackageName())
- && (pkg == null || !hasPermission(pkg, bp.getName()))) {
- Slog.i(TAG, "Removing permission tree " + bp.getName()
- + " that used to be declared by " + bp.getSourcePackageName());
- changed = true;
- it.remove();
- }
+ if (bp.getSourcePackageSetting() == null
+ || !packageName.equals(bp.getSourcePackageName())) {
continue;
}
+ // The target package is the source of the current permission tree
+ // Set to changed for either install or uninstall
+ changed = true;
+ if (pkg == null || !hasPermission(pkg, bp.getName())) {
+ Slog.i(TAG, "Removing permission tree " + bp.getName()
+ + " that used to be declared by " + bp.getSourcePackageName());
+ it.remove();
+ }
if (needsUpdate == null) {
needsUpdate = new ArraySet<>(mSettings.mPermissionTrees.size());
}
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 695b68bf71cb..149dfa6be6c4 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -1279,7 +1279,7 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
{
std::lock_guard lock(mJobMutex);
if (mRunning) {
- auto& existingJobs = mJobQueue[storage];
+ auto& existingJobs = mJobQueue[ifs->mountId];
if (existingJobs.empty()) {
existingJobs = std::move(jobQueue);
} else {
@@ -1369,12 +1369,32 @@ void IncrementalService::extractZipFile(const IfsMountPtr& ifs, ZipArchiveHandle
}
bool IncrementalService::waitForNativeBinariesExtraction(StorageId storage) {
+ struct WaitPrinter {
+ const Clock::time_point startTs = Clock::now();
+ ~WaitPrinter() noexcept {
+ if (sEnablePerfLogging) {
+ const auto endTs = Clock::now();
+ LOG(INFO) << "incfs: waitForNativeBinariesExtraction() complete in "
+ << elapsedMcs(startTs, endTs) << "mcs";
+ }
+ }
+ } waitPrinter;
+
+ MountId mount;
+ {
+ auto ifs = getIfs(storage);
+ if (!ifs) {
+ return true;
+ }
+ mount = ifs->mountId;
+ }
+
std::unique_lock lock(mJobMutex);
- mJobCondition.wait(lock, [this, storage] {
+ mJobCondition.wait(lock, [this, mount] {
return !mRunning ||
- (mPendingJobsStorage != storage && mJobQueue.find(storage) == mJobQueue.end());
+ (mPendingJobsMount != mount && mJobQueue.find(mount) == mJobQueue.end());
});
- return mPendingJobsStorage != storage && mJobQueue.find(storage) == mJobQueue.end();
+ return mRunning;
}
void IncrementalService::runJobProcessing() {
@@ -1386,7 +1406,7 @@ void IncrementalService::runJobProcessing() {
}
auto it = mJobQueue.begin();
- mPendingJobsStorage = it->first;
+ mPendingJobsMount = it->first;
auto queue = std::move(it->second);
mJobQueue.erase(it);
lock.unlock();
@@ -1396,7 +1416,7 @@ void IncrementalService::runJobProcessing() {
}
lock.lock();
- mPendingJobsStorage = kInvalidStorageId;
+ mPendingJobsMount = kInvalidStorageId;
lock.unlock();
mJobCondition.notify_all();
}
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index e7705df633d1..c016bab067be 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -308,8 +308,8 @@ private:
StorageId mNextId = 0;
using Job = std::function<void()>;
- std::unordered_map<StorageId, std::vector<Job>> mJobQueue;
- StorageId mPendingJobsStorage = kInvalidStorageId;
+ std::unordered_map<MountId, std::vector<Job>> mJobQueue;
+ MountId mPendingJobsMount = kInvalidStorageId;
std::condition_variable mJobCondition;
std::mutex mJobMutex;
std::thread mJobProcessor;
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index b60e99363706..f205fde88c0d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -117,6 +117,16 @@ public class AppsFilterTest {
}
private static ParsingPackage pkg(String packageName, IntentFilter... filters) {
+ ParsedActivity activity = createActivity(packageName, filters);
+ return pkg(packageName).addActivity(activity);
+ }
+
+ private static ParsingPackage pkgWithReceiver(String packageName, IntentFilter... filters) {
+ ParsedActivity receiver = createActivity(packageName, filters);
+ return pkg(packageName).addReceiver(receiver);
+ }
+
+ private static ParsedActivity createActivity(String packageName, IntentFilter[] filters) {
ParsedActivity activity = new ParsedActivity();
activity.setPackageName(packageName);
for (IntentFilter filter : filters) {
@@ -136,9 +146,7 @@ public class AppsFilterTest {
activity.addIntent(info);
activity.setExported(true);
}
-
- return pkg(packageName)
- .addActivity(activity);
+ return activity;
}
private static ParsingPackage pkgWithInstrumentation(
@@ -176,9 +184,10 @@ public class AppsFilterTest {
}
@Test
- public void testQueriesAction_FilterMatches() {
+ public void testQueriesAction_FilterMatches() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -190,9 +199,46 @@ public class AppsFilterTest {
}
@Test
- public void testQueriesProvider_FilterMatches() {
+ public void testQueriesProtectedAction_FilterDoesNotMatch() throws Exception {
+ final AppsFilter appsFilter =
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ final Signature frameworkSignature = Mockito.mock(Signature.class);
+ final PackageParser.SigningDetails frameworkSigningDetails =
+ new PackageParser.SigningDetails(new Signature[]{frameworkSignature}, 1);
+ final ParsingPackage android = pkg("android");
+ android.addProtectedBroadcast("TEST_ACTION");
+ simulateAddPackage(appsFilter, android, 1000,
+ b -> b.setSigningDetails(frameworkSigningDetails));
+ appsFilter.onSystemReady();
+
+ final int activityUid = DUMMY_TARGET_UID;
+ PackageSetting targetActivity = simulateAddPackage(appsFilter,
+ pkg("com.target.activity", new IntentFilter("TEST_ACTION")), activityUid);
+ final int receiverUid = DUMMY_TARGET_UID + 1;
+ PackageSetting targetReceiver = simulateAddPackage(appsFilter,
+ pkgWithReceiver("com.target.receiver", new IntentFilter("TEST_ACTION")),
+ receiverUid);
+ final int callingUid = DUMMY_CALLING_UID;
+ PackageSetting calling = simulateAddPackage(appsFilter,
+ pkg("com.calling.action", new Intent("TEST_ACTION")), callingUid);
+ final int wildcardUid = DUMMY_CALLING_UID + 1;
+ PackageSetting callingWildCard = simulateAddPackage(appsFilter,
+ pkg("com.calling.wildcard", new Intent("*")), wildcardUid);
+
+ assertFalse(appsFilter.shouldFilterApplication(callingUid, calling, targetActivity, 0));
+ assertTrue(appsFilter.shouldFilterApplication(callingUid, calling, targetReceiver, 0));
+
+ assertFalse(appsFilter.shouldFilterApplication(
+ wildcardUid, callingWildCard, targetActivity, 0));
+ assertTrue(appsFilter.shouldFilterApplication(
+ wildcardUid, callingWildCard, targetReceiver, 0));
+ }
+
+ @Test
+ public void testQueriesProvider_FilterMatches() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -205,9 +251,10 @@ public class AppsFilterTest {
}
@Test
- public void testQueriesDifferentProvider_Filters() {
+ public void testQueriesDifferentProvider_Filters() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -220,9 +267,10 @@ public class AppsFilterTest {
}
@Test
- public void testQueriesProviderWithSemiColon_FilterMatches() {
+ public void testQueriesProviderWithSemiColon_FilterMatches() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -236,9 +284,10 @@ public class AppsFilterTest {
}
@Test
- public void testQueriesAction_NoMatchingAction_Filters() {
+ public void testQueriesAction_NoMatchingAction_Filters() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -250,9 +299,10 @@ public class AppsFilterTest {
}
@Test
- public void testQueriesAction_NoMatchingActionFilterLowSdk_DoesntFilter() {
+ public void testQueriesAction_NoMatchingActionFilterLowSdk_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -269,9 +319,10 @@ public class AppsFilterTest {
}
@Test
- public void testNoQueries_Filters() {
+ public void testNoQueries_Filters() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -283,9 +334,10 @@ public class AppsFilterTest {
}
@Test
- public void testForceQueryable_DoesntFilter() {
+ public void testForceQueryable_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -297,9 +349,10 @@ public class AppsFilterTest {
}
@Test
- public void testForceQueryableByDevice_SystemCaller_DoesntFilter() {
+ public void testForceQueryableByDevice_SystemCaller_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{"com.some.package"}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -340,9 +393,10 @@ public class AppsFilterTest {
}
@Test
- public void testForceQueryableByDevice_NonSystemCaller_Filters() {
+ public void testForceQueryableByDevice_NonSystemCaller_Filters() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{"com.some.package"}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -355,10 +409,11 @@ public class AppsFilterTest {
@Test
- public void testSystemQueryable_DoesntFilter() {
+ public void testSystemQueryable_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{},
true /* system force queryable */, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -371,9 +426,10 @@ public class AppsFilterTest {
}
@Test
- public void testQueriesPackage_DoesntFilter() {
+ public void testQueriesPackage_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -385,11 +441,12 @@ public class AppsFilterTest {
}
@Test
- public void testNoQueries_FeatureOff_DoesntFilter() {
+ public void testNoQueries_FeatureOff_DoesntFilter() throws Exception {
when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class)))
.thenReturn(false);
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(
@@ -401,9 +458,10 @@ public class AppsFilterTest {
}
@Test
- public void testSystemUid_DoesntFilter() {
+ public void testSystemUid_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -415,9 +473,10 @@ public class AppsFilterTest {
}
@Test
- public void testNonSystemUid_NoCallingSetting_Filters() {
+ public void testNonSystemUid_NoCallingSetting_Filters() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
@@ -427,9 +486,10 @@ public class AppsFilterTest {
}
@Test
- public void testNoTargetPackage_filters() {
+ public void testNoTargetPackage_filters() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = new PackageSettingBuilder()
@@ -445,7 +505,7 @@ public class AppsFilterTest {
}
@Test
- public void testActsOnTargetOfOverlay() {
+ public void testActsOnTargetOfOverlay() throws Exception {
final String actorName = "overlay://test/actorName";
ParsingPackage target = pkg("com.some.package.target")
@@ -481,6 +541,7 @@ public class AppsFilterTest {
return Collections.emptyMap();
}
});
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting targetSetting = simulateAddPackage(appsFilter, target, DUMMY_TARGET_UID);
@@ -507,7 +568,7 @@ public class AppsFilterTest {
}
@Test
- public void testActsOnTargetOfOverlayThroughSharedUser() {
+ public void testActsOnTargetOfOverlayThroughSharedUser() throws Exception {
final String actorName = "overlay://test/actorName";
ParsingPackage target = pkg("com.some.package.target")
@@ -545,6 +606,7 @@ public class AppsFilterTest {
return Collections.emptyMap();
}
});
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting targetSetting = simulateAddPackage(appsFilter, target, DUMMY_TARGET_UID);
@@ -566,9 +628,10 @@ public class AppsFilterTest {
}
@Test
- public void testInitiatingApp_DoesntFilter() {
+ public void testInitiatingApp_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
@@ -580,9 +643,10 @@ public class AppsFilterTest {
}
@Test
- public void testUninstalledInitiatingApp_Filters() {
+ public void testUninstalledInitiatingApp_Filters() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
@@ -594,9 +658,10 @@ public class AppsFilterTest {
}
@Test
- public void testOriginatingApp_Filters() {
+ public void testOriginatingApp_Filters() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
@@ -608,9 +673,10 @@ public class AppsFilterTest {
}
@Test
- public void testInstallingApp_DoesntFilter() {
+ public void testInstallingApp_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
@@ -622,9 +688,10 @@ public class AppsFilterTest {
}
@Test
- public void testInstrumentation_DoesntFilter() {
+ public void testInstrumentation_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -644,6 +711,7 @@ public class AppsFilterTest {
public void testWhoCanSee() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
final int systemAppId = Process.FIRST_APPLICATION_UID - 1;
@@ -700,6 +768,15 @@ public class AppsFilterTest {
PackageSettingBuilder withBuilder(PackageSettingBuilder builder);
}
+ private void simulateAddBasicAndroid(AppsFilter appsFilter) throws Exception {
+ final Signature frameworkSignature = Mockito.mock(Signature.class);
+ final PackageParser.SigningDetails frameworkSigningDetails =
+ new PackageParser.SigningDetails(new Signature[]{frameworkSignature}, 1);
+ final ParsingPackage android = pkg("android");
+ simulateAddPackage(appsFilter, android, 1000,
+ b -> b.setSigningDetails(frameworkSigningDetails));
+ }
+
private PackageSetting simulateAddPackage(AppsFilter filter,
ParsingPackage newPkgBuilder, int appId) {
return simulateAddPackage(filter, newPkgBuilder, appId, null);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
index b8de3ca4ea1c..ee210b6eeaee 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static org.mockito.ArgumentMatchers.any;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -49,6 +50,7 @@ public class WindowContainerThumbnailTest extends WindowTestsBase {
GraphicBuffer.USAGE_SW_READ_RARELY | GraphicBuffer.USAGE_SW_WRITE_NEVER);
final ActivityRecord mockAr = mock(ActivityRecord.class);
when(mockAr.getPendingTransaction()).thenReturn(new StubTransaction());
+ when(mockAr.makeChildSurface(any())).thenReturn(new MockSurfaceControlBuilder());
when(mockAr.makeSurface()).thenReturn(new MockSurfaceControlBuilder());
return new WindowContainerThumbnail(new StubTransaction(), mockAr,
buffer, false, mock(Surface.class), mock(SurfaceAnimator.class));