summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/ContentProvider.java53
-rw-r--r--core/java/android/content/ContentProviderOperation.java16
-rw-r--r--core/java/android/content/Context.java9
-rw-r--r--core/java/com/android/internal/app/AssistUtils.java21
-rw-r--r--libs/hwui/hwui/Bitmap.cpp2
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerConstants.java11
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java40
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java5
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java6
-rw-r--r--services/core/java/com/android/server/notification/ManagedServices.java10
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java14
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotPersister.java3
12 files changed, 152 insertions, 38 deletions
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index cdeaea3ebcae..e2c898d153ee 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -54,6 +54,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Objects;
/**
* Content providers are one of the primary building blocks of Android applications, providing
@@ -208,7 +209,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public Cursor query(String callingPkg, Uri uri, @Nullable String[] projection,
@Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) {
- validateIncomingUri(uri);
+ uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
// The caller has no access to the data, so return an empty cursor with
@@ -247,14 +248,14 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public String getType(Uri uri) {
- validateIncomingUri(uri);
+ uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
return ContentProvider.this.getType(uri);
}
@Override
public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
- validateIncomingUri(uri);
+ uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = maybeGetUriWithoutUserId(uri);
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
@@ -270,7 +271,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) {
- validateIncomingUri(uri);
+ uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
return 0;
@@ -292,11 +293,12 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
for (int i = 0; i < numOperations; i++) {
ContentProviderOperation operation = operations.get(i);
Uri uri = operation.getUri();
- validateIncomingUri(uri);
userIds[i] = getUserIdFromUri(uri);
- if (userIds[i] != UserHandle.USER_CURRENT) {
- // Removing the user id from the uri.
- operation = new ContentProviderOperation(operation, true);
+ uri = validateIncomingUri(uri);
+ uri = maybeGetUriWithoutUserId(uri);
+ // Rebuild operation if we changed the Uri above
+ if (!Objects.equals(operation.getUri(), uri)) {
+ operation = new ContentProviderOperation(operation, uri);
operations.set(i, operation);
}
if (operation.isReadOperation()) {
@@ -331,7 +333,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) {
- validateIncomingUri(uri);
+ uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
return 0;
@@ -347,7 +349,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public int update(String callingPkg, Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
- validateIncomingUri(uri);
+ uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
return 0;
@@ -364,7 +366,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
public ParcelFileDescriptor openFile(
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal,
IBinder callerToken) throws FileNotFoundException {
- validateIncomingUri(uri);
+ uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
enforceFilePermission(callingPkg, uri, mode, callerToken);
final String original = setCallingPackage(callingPkg);
@@ -380,7 +382,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
public AssetFileDescriptor openAssetFile(
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
throws FileNotFoundException {
- validateIncomingUri(uri);
+ uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
enforceFilePermission(callingPkg, uri, mode, null);
final String original = setCallingPackage(callingPkg);
@@ -406,7 +408,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
- validateIncomingUri(uri);
+ uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
return ContentProvider.this.getStreamTypes(uri, mimeTypeFilter);
}
@@ -415,7 +417,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
Bundle.setDefusable(opts, true);
- validateIncomingUri(uri);
+ uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
enforceFilePermission(callingPkg, uri, "r", null);
final String original = setCallingPackage(callingPkg);
@@ -434,7 +436,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public Uri canonicalize(String callingPkg, Uri uri) {
- validateIncomingUri(uri);
+ uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = getUriWithoutUserId(uri);
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
@@ -450,7 +452,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public Uri uncanonicalize(String callingPkg, Uri uri) {
- validateIncomingUri(uri);
+ uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = getUriWithoutUserId(uri);
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
@@ -467,7 +469,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override
public boolean refresh(String callingPkg, Uri uri, Bundle args,
ICancellationSignal cancellationSignal) throws RemoteException {
- validateIncomingUri(uri);
+ uri = validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
return false;
@@ -1901,7 +1903,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
*/
if (mContext == null) {
mContext = context;
- if (context != null) {
+ if (context != null && mTransport != null) {
mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService(
Context.APP_OPS_SERVICE);
}
@@ -2010,7 +2012,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
/** @hide */
- private void validateIncomingUri(Uri uri) throws SecurityException {
+ public Uri validateIncomingUri(Uri uri) throws SecurityException {
String auth = uri.getAuthority();
if (!mSingleUser) {
int userId = getUserIdFromAuthority(auth, UserHandle.USER_CURRENT);
@@ -2029,6 +2031,19 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
throw new SecurityException(message);
}
+
+ // Normalize the path by removing any empty path segments, which can be
+ // a source of security issues.
+ final String encodedPath = uri.getEncodedPath();
+ if (encodedPath != null && encodedPath.indexOf("//") != -1) {
+ final Uri normalized = uri.buildUpon()
+ .encodedPath(encodedPath.replaceAll("//+", "/")).build();
+ Log.w(TAG, "Normalized " + uri + " to " + normalized
+ + " to avoid possible security issues");
+ return normalized;
+ } else {
+ return uri;
+ }
}
/** @hide */
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 8f3a31746266..f3914f2a4e76 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -94,13 +94,9 @@ public class ContentProviderOperation implements Parcelable {
}
/** @hide */
- public ContentProviderOperation(ContentProviderOperation cpo, boolean removeUserIdFromUri) {
+ public ContentProviderOperation(ContentProviderOperation cpo, Uri withUri) {
mType = cpo.mType;
- if (removeUserIdFromUri) {
- mUri = ContentProvider.getUriWithoutUserId(cpo.mUri);
- } else {
- mUri = cpo.mUri;
- }
+ mUri = withUri;
mValues = cpo.mValues;
mSelection = cpo.mSelection;
mSelectionArgs = cpo.mSelectionArgs;
@@ -110,14 +106,6 @@ public class ContentProviderOperation implements Parcelable {
mYieldAllowed = cpo.mYieldAllowed;
}
- /** @hide */
- public ContentProviderOperation getWithoutUserIdInUri() {
- if (ContentProvider.uriHasUserId(mUri)) {
- return new ContentProviderOperation(this, true);
- }
- return this;
- }
-
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mType);
Uri.writeToParcel(dest, mUri);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 90a94ee76085..b53202ef1741 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -326,6 +326,15 @@ public abstract class Context {
public static final int BIND_ADJUST_WITH_ACTIVITY = 0x0080;
/**
+ * Flag for {@link #bindService}: If binding from something better than perceptible,
+ * still set the adjust below perceptible. This would be used for bound services that can
+ * afford to be evicted when under extreme memory pressure, but should be restarted as soon
+ * as possible.
+ * @hide
+ */
+ public static final int BIND_ADJUST_BELOW_PERCEPTIBLE = 0x0100;
+
+ /**
* @hide Flag for {@link #bindService}: allows binding to a service provided
* by an instant app. Note that the caller may not have access to the instant
* app providing the service which is a violation of the instant app sandbox.
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
index 9171959537c8..fed0a89a4d75 100644
--- a/core/java/com/android/internal/app/AssistUtils.java
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -32,6 +32,8 @@ import android.os.ServiceManager;
import android.provider.Settings;
import android.util.Log;
+import com.android.internal.R;
+
/**
* Utility method for dealing with the assistant aspects of
* {@link com.android.internal.app.IVoiceInteractionManagerService IVoiceInteractionManagerService}.
@@ -40,6 +42,14 @@ public class AssistUtils {
private static final String TAG = "AssistUtils";
+ /**
+ * Sentinel value for "no default assistant specified."
+ *
+ * Empty string is already used to represent an explicit setting of No Assistant. null cannot
+ * be used because we can't represent a null value in XML.
+ */
+ private static final String UNSET = "#+UNSET";
+
private final Context mContext;
private final IVoiceInteractionManagerService mVoiceInteractionManagerService;
@@ -152,10 +162,21 @@ public class AssistUtils {
return ComponentName.unflattenFromString(setting);
}
+ final String defaultSetting = mContext.getResources().getString(
+ R.string.config_defaultAssistantComponentName);
+ if (defaultSetting != null && !defaultSetting.equals(UNSET)) {
+ return ComponentName.unflattenFromString(defaultSetting);
+ }
+
// Fallback to keep backward compatible behavior when there is no user setting.
if (activeServiceSupportsAssistGesture()) {
return getActiveServiceComponentName();
}
+
+ if (UNSET.equals(defaultSetting)) {
+ return null;
+ }
+
final SearchManager searchManager =
(SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
if (searchManager == null) {
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 263d249d20e9..c6ef090c1f76 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -223,6 +223,7 @@ Bitmap::~Bitmap() {
break;
case PixelStorageType::Heap:
free(mPixelStorage.heap.address);
+ mallopt(M_PURGE, 0);
break;
case PixelStorageType::Hardware:
auto buffer = mPixelStorage.hardware.buffer;
@@ -230,7 +231,6 @@ Bitmap::~Bitmap() {
mPixelStorage.hardware.buffer = nullptr;
break;
}
-
android::uirenderer::renderthread::RenderProxy::onBitmapDestroyed(getStableID());
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 9bf72fb86cd6..d14c1a1adf77 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -67,6 +67,7 @@ final class ActivityManagerConstants extends ContentObserver {
static final String KEY_BOUND_SERVICE_CRASH_RESTART_DURATION = "service_crash_restart_duration";
static final String KEY_BOUND_SERVICE_CRASH_MAX_RETRY = "service_crash_max_retry";
static final String KEY_PROCESS_START_ASYNC = "process_start_async";
+ static final String KEY_TOP_TO_FGS_GRACE_DURATION = "top_to_fgs_grace_duration";
private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000;
@@ -95,7 +96,7 @@ final class ActivityManagerConstants extends ContentObserver {
private static final long DEFAULT_BOUND_SERVICE_CRASH_RESTART_DURATION = 30*60_000;
private static final int DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY = 16;
private static final boolean DEFAULT_PROCESS_START_ASYNC = true;
-
+ private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000;
// Maximum number of cached processes we will allow.
public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
@@ -207,6 +208,10 @@ final class ActivityManagerConstants extends ContentObserver {
// Indicates if the processes need to be started asynchronously.
public boolean FLAG_PROCESS_START_ASYNC = DEFAULT_PROCESS_START_ASYNC;
+ // Allow app just moving from TOP to FOREGROUND_SERVICE to stay in a higher adj value for
+ // this long.
+ public long TOP_TO_FGS_GRACE_DURATION = DEFAULT_TOP_TO_FGS_GRACE_DURATION;
+
// Indicates whether the activity starts logging is enabled.
// Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED
boolean mFlagActivityStartsLoggingEnabled;
@@ -348,6 +353,8 @@ final class ActivityManagerConstants extends ContentObserver {
DEFAULT_BOUND_SERVICE_CRASH_MAX_RETRY);
FLAG_PROCESS_START_ASYNC = mParser.getBoolean(KEY_PROCESS_START_ASYNC,
DEFAULT_PROCESS_START_ASYNC);
+ TOP_TO_FGS_GRACE_DURATION = mParser.getDurationMillis(KEY_TOP_TO_FGS_GRACE_DURATION,
+ DEFAULT_TOP_TO_FGS_GRACE_DURATION);
updateMaxCachedProcesses();
}
@@ -423,6 +430,8 @@ final class ActivityManagerConstants extends ContentObserver {
pw.println(MAX_SERVICE_INACTIVITY);
pw.print(" "); pw.print(KEY_BG_START_TIMEOUT); pw.print("=");
pw.println(BG_START_TIMEOUT);
+ pw.print(" "); pw.print(KEY_TOP_TO_FGS_GRACE_DURATION); pw.print("=");
+ pw.println(TOP_TO_FGS_GRACE_DURATION);
pw.println();
if (mOverrideMaxCachedProcesses >= 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c5b8b950d456..145c1c964a31 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5889,6 +5889,7 @@ public class ActivityManagerService extends IActivityManager.Stub
private final void handleAppDiedLocked(ProcessRecord app,
boolean restarting, boolean allowRestart) {
int pid = app.pid;
+ final boolean clearLaunchStartTime = !restarting && app.removed && app.foregroundActivities;
boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
false /*replacingPid*/);
if (!kept && !restarting) {
@@ -5929,6 +5930,19 @@ public class ActivityManagerService extends IActivityManager.Stub
} finally {
mWindowManager.continueSurfaceLayout();
}
+
+ // Hack for pi
+ // When an app process is removed, activities from the process may be relaunched. In the
+ // case of forceStopPackageLocked the activities are finished before any window is drawn,
+ // and the launch time is not cleared. This will be incorrectly used to calculate launch
+ // time for the next launched activity launched in the same windowing mode.
+ if (clearLaunchStartTime) {
+ final LaunchTimeTracker.Entry entry = mStackSupervisor
+ .getLaunchTimeTracker().getEntry(mStackSupervisor.getWindowingMode());
+ if (entry != null) {
+ entry.mLaunchStartTime = 0;
+ }
+ }
}
private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
@@ -23376,6 +23390,19 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ // If the app was recently in the foreground and moved to a foreground service status,
+ // allow it to get a higher rank in memory for some time, compared to other foreground
+ // services so that it can finish performing any persistence/processing of in-memory state.
+ if (app.foregroundServices && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
+ && (app.lastTopTime + mConstants.TOP_TO_FGS_GRACE_DURATION > now
+ || app.setProcState <= ActivityManager.PROCESS_STATE_TOP)) {
+ adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
+ app.adjType = "fg-service-act";
+ if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+ reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg: " + app);
+ }
+ }
+
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
|| procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
if (app.forcingToImportant != null) {
@@ -23640,6 +23667,10 @@ public class ActivityManagerService extends IActivityManager.Stub
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
procState = ActivityManager.PROCESS_STATE_PERSISTENT;
}
+ } else if ((cr.flags & Context.BIND_ADJUST_BELOW_PERCEPTIBLE) != 0
+ && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
+ && adj > ProcessList.PERCEPTIBLE_APP_ADJ + 1) {
+ newAdj = ProcessList.PERCEPTIBLE_APP_ADJ + 1;
} else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
&& adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
@@ -24610,6 +24641,8 @@ public class ActivityManagerService extends IActivityManager.Stub
// Must be called before updating setProcState
maybeUpdateUsageStatsLocked(app, nowElapsed);
+ maybeUpdateLastTopTime(app, now);
+
app.setProcState = app.curProcState;
if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
app.notCachedSinceIdle = false;
@@ -24834,6 +24867,13 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ private void maybeUpdateLastTopTime(ProcessRecord app, long nowUptime) {
+ if (app.setProcState <= ActivityManager.PROCESS_STATE_TOP
+ && app.curProcState > ActivityManager.PROCESS_STATE_TOP) {
+ app.lastTopTime = nowUptime;
+ }
+ }
+
private final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) {
if (proc.thread != null) {
if (proc.baseProcessTracker != null) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 784d62e51966..3ac7885eba37 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -104,6 +104,11 @@ public final class ProcessList {
static final int VISIBLE_APP_ADJ = 100;
static final int VISIBLE_APP_LAYER_MAX = PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1;
+ // This is a process that was recently TOP and moved to FGS. Continue to treat it almost
+ // like a foreground app for a while.
+ // @see TOP_TO_FGS_GRACE_PERIOD
+ static final int PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ = 50;
+
// This is the process running the current foreground app. We'd really
// rather not kill it!
static final int FOREGROUND_APP_ADJ = 0;
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 28ebbb87f261..e3e839f63172 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -163,6 +163,7 @@ final class ProcessRecord {
long lastRequestedGc; // When we last asked the app to do a gc
long lastLowMemory; // When we last told the app that memory is low
long lastProviderTime; // The last time someone else was using a provider in this process.
+ long lastTopTime; // The last time the process was in the TOP state or greater.
boolean reportLowMemory; // Set to true when waiting to report low mem
boolean empty; // Is this an empty background process?
boolean cached; // Is this a cached process?
@@ -380,6 +381,11 @@ final class ProcessRecord {
TimeUtils.formatDuration(lastProviderTime, nowUptime, pw);
pw.println();
}
+ if (lastTopTime > 0) {
+ pw.print(prefix); pw.print("lastTopTime=");
+ TimeUtils.formatDuration(lastTopTime, nowUptime, pw);
+ pw.println();
+ }
if (hasStartedServices) {
pw.print(prefix); pw.print("hasStartedServices="); pw.println(hasStartedServices);
}
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index f7becd518861..30fa7fe4ce87 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -175,6 +175,10 @@ abstract public class ManagedServices {
}
}
+ protected int getBindFlags() {
+ return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT;
+ }
+
protected void onServiceRemovedLocked(ManagedServiceInfo removed) { }
private ManagedServiceInfo newServiceInfo(IInterface service,
@@ -1022,9 +1026,9 @@ abstract public class ManagedServices {
}
};
if (!mContext.bindServiceAsUser(intent,
- serviceConnection,
- BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT,
- new UserHandle(userid))) {
+ serviceConnection,
+ getBindFlags(),
+ new UserHandle(userid))) {
mServicesBinding.remove(servicesBindingTag);
Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent);
return;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8304e2691979..f2b7bbe636e5 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -33,6 +33,10 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
+import static android.content.Context.BIND_ADJUST_BELOW_PERCEPTIBLE;
+import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT;
+import static android.content.Context.BIND_AUTO_CREATE;
+import static android.content.Context.BIND_FOREGROUND_SERVICE;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -6521,6 +6525,16 @@ public class NotificationManagerService extends SystemService {
}
@Override
+ protected int getBindFlags() {
+ // Most of the same flags as the base, but also add BIND_ADJUST_BELOW_PERCEPTIBLE
+ // because too many 3P apps could be kept in memory as notification listeners and
+ // cause extreme memory pressure.
+ // TODO: Change the binding lifecycle of NotificationListeners to avoid this situation.
+ return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE
+ | BIND_ADJUST_BELOW_PERCEPTIBLE | BIND_ALLOW_WHITELIST_MANAGEMENT;
+ }
+
+ @Override
protected Config getConfig() {
Config c = new Config();
c.caption = "notification listener";
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index a642e6ab744a..d1c0443c58e1 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -360,6 +360,7 @@ class TaskSnapshotPersister {
// For snapshots with reduced resolution, do not create or save full sized bitmaps
if (mSnapshot.isReducedResolution()) {
+ swBitmap.recycle();
return true;
}
@@ -372,6 +373,8 @@ class TaskSnapshotPersister {
Slog.e(TAG, "Unable to open " + file + " for persisting.", e);
return false;
}
+ reduced.recycle();
+ swBitmap.recycle();
return true;
}
}