Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b12e1354 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Maybe fix issue #7211766: bindService() to User u0 While u10 is...

...Forground Sometimes Doesn't Take

The main change here is a one-liner in ActiveServices to check the
uid when deciding whether to remove an item from mPendingServices.
This could cause the problem being seen -- if the same service for
two users is starting at the same time, the second one would blow
away the pending start of the first one.  Unfortunately I have had
trouble reproducing the bug, so I don't know if this is actually
fixing it.  It's a bug, anyway.

The reason so much has changed here is because I spread around
logging and printing of the user ID associated with operations and
objects to make it easier to debug these kind of multi-user things.

Also includes some tweaks to the oom manager to allow more background
processes (I have seen many times in logs where we thrash through
processes because the LRU list is too short), plus to compensate an
additional time-based metric for when to get rid of background processes,
plus some new logic to try to help things like Chrome keep around
their service processes.

Change-Id: Icda77fb2a1dd349969e3ff2c8fff0f19b40b31d3
parent 2fd6cb04
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -804,8 +804,9 @@ public class Am {
        ParcelFileDescriptor fd = null;
        ParcelFileDescriptor fd = null;


        try {
        try {
            fd = ParcelFileDescriptor.open(
            File file = new File(heapFile);
                    new File(heapFile),
            file.delete();
            fd = ParcelFileDescriptor.open(file,
                    ParcelFileDescriptor.MODE_CREATE |
                    ParcelFileDescriptor.MODE_CREATE |
                    ParcelFileDescriptor.MODE_TRUNCATE |
                    ParcelFileDescriptor.MODE_TRUNCATE |
                    ParcelFileDescriptor.MODE_READ_WRITE);
                    ParcelFileDescriptor.MODE_READ_WRITE);
+1 −1
Original line number Original line Diff line number Diff line
@@ -1509,9 +1509,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
        case DUMP_HEAP_TRANSACTION: {
        case DUMP_HEAP_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            data.enforceInterface(IActivityManager.descriptor);
            String process = data.readString();
            String process = data.readString();
            int userId = data.readInt();
            boolean managed = data.readInt() != 0;
            boolean managed = data.readInt() != 0;
            String path = data.readString();
            String path = data.readString();
            int userId = data.readInt();
            ParcelFileDescriptor fd = data.readInt() != 0
            ParcelFileDescriptor fd = data.readInt() != 0
                    ? data.readFileDescriptor() : null;
                    ? data.readFileDescriptor() : null;
            boolean res = dumpHeap(process, userId, managed, path, fd);
            boolean res = dumpHeap(process, userId, managed, path, fd);
+4 −3
Original line number Original line Diff line number Diff line
@@ -2711,7 +2711,7 @@ public final class ActivityThread {
                r.activity.performResume();
                r.activity.performResume();


                EventLog.writeEvent(LOG_ON_RESUME_CALLED,
                EventLog.writeEvent(LOG_ON_RESUME_CALLED,
                        r.activity.getComponentName().getClassName());
                        UserHandle.myUserId(), r.activity.getComponentName().getClassName());


                r.paused = false;
                r.paused = false;
                r.stopped = false;
                r.stopped = false;
@@ -2979,7 +2979,8 @@ public final class ActivityThread {
            // Now we are idle.
            // Now we are idle.
            r.activity.mCalled = false;
            r.activity.mCalled = false;
            mInstrumentation.callActivityOnPause(r.activity);
            mInstrumentation.callActivityOnPause(r.activity);
            EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName());
            EventLog.writeEvent(LOG_ON_PAUSE_CALLED, UserHandle.myUserId(),
                    r.activity.getComponentName().getClassName());
            if (!r.activity.mCalled) {
            if (!r.activity.mCalled) {
                throw new SuperNotCalledException(
                throw new SuperNotCalledException(
                    "Activity " + r.intent.getComponent().toShortString() +
                    "Activity " + r.intent.getComponent().toShortString() +
@@ -3364,7 +3365,7 @@ public final class ActivityThread {
                try {
                try {
                    r.activity.mCalled = false;
                    r.activity.mCalled = false;
                    mInstrumentation.callActivityOnPause(r.activity);
                    mInstrumentation.callActivityOnPause(r.activity);
                    EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
                    EventLog.writeEvent(LOG_ON_PAUSE_CALLED, UserHandle.myUserId(),
                            r.activity.getComponentName().getClassName());
                            r.activity.getComponentName().getClassName());
                    if (!r.activity.mCalled) {
                    if (!r.activity.mCalled) {
                        throw new SuperNotCalledException(
                        throw new SuperNotCalledException(
+14 −1
Original line number Original line Diff line number Diff line
@@ -178,7 +178,7 @@ public abstract class Context {
     * Flag for {@link #bindService}: indicates that the client application
     * Flag for {@link #bindService}: indicates that the client application
     * binding to this service considers the service to be more important than
     * binding to this service considers the service to be more important than
     * the app itself.  When set, the platform will try to have the out of
     * the app itself.  When set, the platform will try to have the out of
     * memory kill the app before it kills the service it is bound to, though
     * memory killer kill the app before it kills the service it is bound to, though
     * this is not guaranteed to be the case.
     * this is not guaranteed to be the case.
     */
     */
    public static final int BIND_ABOVE_CLIENT = 0x0008;
    public static final int BIND_ABOVE_CLIENT = 0x0008;
@@ -218,6 +218,19 @@ public abstract class Context {
     */
     */
    public static final int BIND_ADJUST_WITH_ACTIVITY = 0x0080;
    public static final int BIND_ADJUST_WITH_ACTIVITY = 0x0080;


    /**
     * @hide An idea that is not yet implemented.
     * Flag for {@link #bindService}: If binding from an activity, consider
     * this service to be visible like the binding activity is.  That is,
     * it will be treated as something more important to keep around than
     * invisible background activities.  This will impact the number of
     * recent activities the user can switch between without having them
     * restart.  There is no guarantee this will be respected, as the system
     * tries to balance such requests from one app vs. the importantance of
     * keeping other apps around.
     */
    public static final int BIND_VISIBLE = 0x0100;

    /**
    /**
     * Flag for {@link #bindService}: Don't consider the bound service to be
     * Flag for {@link #bindService}: Don't consider the bound service to be
     * visible, even if the caller is visible.
     * visible, even if the caller is visible.
+8 −8
Original line number Original line Diff line number Diff line
@@ -44,7 +44,6 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.Binder;
import android.os.IBinder;
import android.os.IBinder;
import android.os.Message;
import android.os.Message;
@@ -391,7 +390,7 @@ public class ActiveServices {
                    if (r.isForeground) {
                    if (r.isForeground) {
                        r.isForeground = false;
                        r.isForeground = false;
                        if (r.app != null) {
                        if (r.app != null) {
                            mAm.updateLruProcessLocked(r.app, false, true);
                            mAm.updateLruProcessLocked(r.app, false);
                            updateServiceForegroundLocked(r.app, true);
                            updateServiceForegroundLocked(r.app, true);
                        }
                        }
                    }
                    }
@@ -760,7 +759,8 @@ public class ActiveServices {
                    int N = mPendingServices.size();
                    int N = mPendingServices.size();
                    for (int i=0; i<N; i++) {
                    for (int i=0; i<N; i++) {
                        ServiceRecord pr = mPendingServices.get(i);
                        ServiceRecord pr = mPendingServices.get(i);
                        if (pr.name.equals(name)) {
                        if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
                                && pr.name.equals(name)) {
                            mPendingServices.remove(i);
                            mPendingServices.remove(i);
                            i--;
                            i--;
                            N--;
                            N--;
@@ -942,7 +942,7 @@ public class ActiveServices {
        Slog.w(TAG, "Scheduling restart of crashed service "
        Slog.w(TAG, "Scheduling restart of crashed service "
                + r.shortName + " in " + r.restartDelay + "ms");
                + r.shortName + " in " + r.restartDelay + "ms");
        EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
        EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
                r.shortName, r.restartDelay);
                r.userId, r.shortName, r.restartDelay);


        return canceled;
        return canceled;
    }
    }
@@ -1083,14 +1083,14 @@ public class ActiveServices {


        app.services.add(r);
        app.services.add(r);
        bumpServiceExecutingLocked(r, "create");
        bumpServiceExecutingLocked(r, "create");
        mAm.updateLruProcessLocked(app, true, true);
        mAm.updateLruProcessLocked(app, true);


        boolean created = false;
        boolean created = false;
        try {
        try {
            mAm.mStringBuilder.setLength(0);
            mAm.mStringBuilder.setLength(0);
            r.intent.getIntent().toShortString(mAm.mStringBuilder, true, false, true, false);
            r.intent.getIntent().toShortString(mAm.mStringBuilder, true, false, true, false);
            EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
            EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
                    System.identityHashCode(r), r.shortName,
                    r.userId, System.identityHashCode(r), r.shortName,
                    mAm.mStringBuilder.toString(), r.app.pid);
                    mAm.mStringBuilder.toString(), r.app.pid);
            synchronized (r.stats.getBatteryStats()) {
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startLaunchedLocked();
                r.stats.startLaunchedLocked();
@@ -1240,7 +1240,7 @@ public class ActiveServices {


        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
        EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
        EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
                System.identityHashCode(r), r.shortName,
                r.userId, System.identityHashCode(r), r.shortName,
                (r.app != null) ? r.app.pid : -1);
                (r.app != null) ? r.app.pid : -1);


        mServiceMap.removeServiceByName(r.name, r.userId);
        mServiceMap.removeServiceByName(r.name, r.userId);
@@ -1664,7 +1664,7 @@ public class ActiveServices {
                    Slog.w(TAG, "Service crashed " + sr.crashCount
                    Slog.w(TAG, "Service crashed " + sr.crashCount
                            + " times, stopping: " + sr);
                            + " times, stopping: " + sr);
                    EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
                    EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
                            sr.crashCount, sr.shortName, app.pid);
                            sr.userId, sr.crashCount, sr.shortName, app.pid);
                    bringDownServiceLocked(sr, true);
                    bringDownServiceLocked(sr, true);
                } else if (!allowRestart) {
                } else if (!allowRestart) {
                    bringDownServiceLocked(sr, true);
                    bringDownServiceLocked(sr, true);
Loading