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

Commit d58617b4 authored by Wale Ogunwale's avatar Wale Ogunwale Committed by Android (Google) Code Review
Browse files

Merge "Protect against NPE for ActivityRecords without a stack."

parents ab48bc16 7d701174
Loading
Loading
Loading
Loading
+26 −22
Original line number Diff line number Diff line
@@ -1757,7 +1757,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            }
            case ENTER_ANIMATION_COMPLETE_MSG: {
                synchronized (ActivityManagerService.this) {
                    ActivityRecord r = ActivityRecord.forToken((IBinder) msg.obj);
                    ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj);
                    if (r != null && r.app != null && r.app.thread != null) {
                        try {
                            r.app.thread.scheduleEnterAnimationComplete(r.appToken);
@@ -3955,11 +3955,10 @@ public final class ActivityManagerService extends ActivityManagerNative
                return;
            }
            ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
                    mHeavyWeightProcess.activities);
            ArrayList<ActivityRecord> activities = new ArrayList<>(mHeavyWeightProcess.activities);
            for (int i = 0; i < activities.size(); i++) {
                ActivityRecord r = activities.get(i);
                if (!r.finishing) {
                if (!r.finishing && r.isInStackLocked()) {
                    r.task.stack.finishActivityLocked(r, Activity.RESULT_CANCELED,
                            null, "finish-heavy", true);
                }
@@ -4086,7 +4085,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            final long origId = Binder.clearCallingIdentity();
            try {
                ActivityRecord r = ActivityRecord.isInStackLocked(token);
                if (r.task == null || r.task.stack == null) {
                if (r == null) {
                    return false;
                }
                return r.task.stack.safelyDestroyActivityLocked(r, "app-req");
@@ -7797,20 +7796,19 @@ public final class ActivityManagerService extends ActivityManagerNative
                    android.Manifest.permission.GET_DETAILED_TASKS)
                    == PackageManager.PERMISSION_GRANTED;
            final int N = mRecentTasks.size();
            ArrayList<ActivityManager.RecentTaskInfo> res
                    = new ArrayList<ActivityManager.RecentTaskInfo>(
                            maxNum < N ? maxNum : N);
            final int recentsCount = mRecentTasks.size();
            ArrayList<ActivityManager.RecentTaskInfo> res =
                    new ArrayList<>(maxNum < recentsCount ? maxNum : recentsCount);
            final Set<Integer> includedUsers;
            if (includeProfiles) {
                includedUsers = getProfileIdsLocked(userId);
            } else {
                includedUsers = new HashSet<Integer>();
                includedUsers = new HashSet<>();
            }
            includedUsers.add(Integer.valueOf(userId));
            for (int i=0; i<N && maxNum > 0; i++) {
            for (int i = 0; i < recentsCount && maxNum > 0; i++) {
                TaskRecord tr = mRecentTasks.get(i);
                // Only add calling user or related users recent tasks
                if (!includedUsers.contains(Integer.valueOf(tr.userId))) {
@@ -8292,7 +8290,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            if (parentActivityToken == null) {
                throw new IllegalArgumentException("parent token must not be null");
            }
            ActivityRecord r = ActivityRecord.forToken(parentActivityToken);
            ActivityRecord r = ActivityRecord.forTokenLocked(parentActivityToken);
            if (r == null) {
                return null;
            }
@@ -8494,7 +8492,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        long ident = Binder.clearCallingIdentity();
        try {
            synchronized (this) {
                final ActivityRecord r = ActivityRecord.forToken(token);
                final ActivityRecord r = ActivityRecord.forTokenLocked(token);
                if (r == null) {
                    return;
                }
@@ -16573,8 +16571,8 @@ public final class ActivityManagerService extends ActivityManagerNative
    @Override
    public boolean shouldUpRecreateTask(IBinder token, String destAffinity) {
        synchronized (this) {
            ActivityRecord srec = ActivityRecord.forToken(token);
            if (srec.task != null && srec.task.stack != null) {
            ActivityRecord srec = ActivityRecord.forTokenLocked(token);
            if (srec != null) {
                return srec.task.stack.shouldUpRecreateTaskLocked(srec, destAffinity);
            }
        }
@@ -16585,16 +16583,19 @@ public final class ActivityManagerService extends ActivityManagerNative
            Intent resultData) {
        synchronized (this) {
            final ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
                return stack.navigateUpToLocked(token, destIntent, resultCode, resultData);
            final ActivityRecord r = ActivityRecord.forTokenLocked(token);
            if (r != null) {
                return r.task.stack.navigateUpToLocked(r, destIntent, resultCode, resultData);
            }
            return false;
        }
    }
    public int getLaunchedFromUid(IBinder activityToken) {
        ActivityRecord srec = ActivityRecord.forToken(activityToken);
        ActivityRecord srec;
        synchronized (this) {
            srec = ActivityRecord.forTokenLocked(activityToken);
        }
        if (srec == null) {
            return -1;
        }
@@ -16602,7 +16603,10 @@ public final class ActivityManagerService extends ActivityManagerNative
    }
    public String getLaunchedFromPackage(IBinder activityToken) {
        ActivityRecord srec = ActivityRecord.forToken(activityToken);
        ActivityRecord srec;
        synchronized (this) {
            srec = ActivityRecord.forTokenLocked(activityToken);
        }
        if (srec == null) {
            return null;
        }
+134 −113
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.am;

import static com.android.server.am.ActivityManagerDebugConfig.*;
import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
import static com.android.server.am.ActivityManagerService.DEBUG_THUMBNAILS;
import static com.android.server.am.TaskPersister.DEBUG_PERSISTER;
import static com.android.server.am.TaskPersister.DEBUG_RESTORER;
@@ -319,45 +320,84 @@ final class ActivityRecord {
    }

    static class Token extends IApplicationToken.Stub {
        final WeakReference<ActivityRecord> weakActivity;
        private final WeakReference<ActivityRecord> weakActivity;
        private final ActivityManagerService mService;

        Token(ActivityRecord activity) {
        Token(ActivityRecord activity, ActivityManagerService service) {
            weakActivity = new WeakReference<>(activity);
            mService = service;
        }

        @Override public void windowsDrawn() {
            ActivityRecord activity = weakActivity.get();
            if (activity != null) {
                activity.windowsDrawn();
        @Override
        public void windowsDrawn() {
            synchronized (mService) {
                ActivityRecord r = tokenToActivityRecordLocked(this);
                if (r != null) {
                    r.windowsDrawnLocked();
                }
            }
        }

        @Override public void windowsVisible() {
            ActivityRecord activity = weakActivity.get();
            if (activity != null) {
                activity.windowsVisible();
        @Override
        public void windowsVisible() {
            synchronized (mService) {
                ActivityRecord r = tokenToActivityRecordLocked(this);
                if (r != null) {
                    r.windowsVisibleLocked();
                }
            }
        }

        @Override public void windowsGone() {
            ActivityRecord activity = weakActivity.get();
            if (activity != null) {
                activity.windowsGone();
        @Override
        public void windowsGone() {
            synchronized (mService) {
                ActivityRecord r = tokenToActivityRecordLocked(this);
                if (r != null) {
                    if (DEBUG_SWITCH) Log.v(TAG, "windowsGone(): " + r);
                    r.nowVisible = false;
                    return;
                }
            }

        @Override public boolean keyDispatchingTimedOut(String reason) {
            ActivityRecord activity = weakActivity.get();
            return activity != null && activity.keyDispatchingTimedOut(reason);
        }

        @Override public long getKeyDispatchingTimeout() {
            ActivityRecord activity = weakActivity.get();
            if (activity != null) {
                return activity.getKeyDispatchingTimeout();
        @Override
        public boolean keyDispatchingTimedOut(String reason) {
            ActivityRecord r;
            ActivityRecord anrActivity;
            ProcessRecord anrApp;
            synchronized (mService) {
                r = tokenToActivityRecordLocked(this);
                if (r == null) {
                    return false;
                }
                anrActivity = r.getWaitingHistoryRecordLocked();
                anrApp = r != null ? r.app : null;
            }
            return mService.inputDispatchingTimedOut(anrApp, anrActivity, r, false, reason);
        }

        @Override
        public long getKeyDispatchingTimeout() {
            synchronized (mService) {
                ActivityRecord r = tokenToActivityRecordLocked(this);
                if (r == null) {
                    return 0;
                }
                r = r.getWaitingHistoryRecordLocked();
                return ActivityManagerService.getInputDispatchingTimeoutLocked(r);
            }
        }

        private static final ActivityRecord tokenToActivityRecordLocked(Token token) {
            if (token == null) {
                return null;
            }
            ActivityRecord r = token.weakActivity.get();
            if (r == null || r.task == null || r.task.stack == null) {
                return null;
            }
            return r;
        }

        @Override
        public String toString() {
@@ -371,9 +411,9 @@ final class ActivityRecord {
        }
    }

    static ActivityRecord forToken(IBinder token) {
    static ActivityRecord forTokenLocked(IBinder token) {
        try {
            return token != null ? ((Token)token).weakActivity.get() : null;
            return Token.tokenToActivityRecordLocked((Token)token);
        } catch (ClassCastException e) {
            Slog.w(TAG, "Bad activity token: " + token, e);
            return null;
@@ -391,7 +431,7 @@ final class ActivityRecord {
            boolean _componentSpecified, ActivityStackSupervisor supervisor,
            ActivityContainer container, Bundle options) {
        service = _service;
        appToken = new Token(this);
        appToken = new Token(this, service);
        info = aInfo;
        launchedFromUid = _launchedFromUid;
        launchedFromPackage = _launchedFromPackage;
@@ -528,13 +568,8 @@ final class ActivityRecord {
    }

    void setTask(TaskRecord newTask, TaskRecord taskToAffiliateWith) {
        if (task != null && task.removeActivity(this)) {
            if (task != newTask) {
        if (task != null && task.removeActivity(this) && task != newTask && task.stack != null) {
            task.stack.removeTask(task, "setTask");
            } else {
                Slog.d(TAG, "!!! REMOVE THIS LOG !!! setTask: nearly removed stack=" +
                        (newTask == null ? null : newTask.stack));
            }
        }
        task = newTask;
        setTaskToAffiliateWith(taskToAffiliateWith);
@@ -580,6 +615,10 @@ final class ActivityRecord {
        return inHistory;
    }

    boolean isInStackLocked() {
        return task != null && task.stack != null && task.stack.isInStackLocked(this) != null;
    }

    boolean isHomeActivity() {
        return mActivityType == HOME_ACTIVITY_TYPE;
    }
@@ -599,9 +638,10 @@ final class ActivityRecord {
                        (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
    }

    void makeFinishing() {
    void makeFinishingLocked() {
        if (!finishing) {
            if (this == task.stack.getVisibleBehindActivity()) {
            if (task != null && task.stack != null
                    && this == task.stack.getVisibleBehindActivity()) {
                // A finishing activity should not remain as visible in the background
                mStackSupervisor.requestVisibleBehindLocked(this, false);
            }
@@ -670,7 +710,8 @@ final class ActivityRecord {
        // stack.
        final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
        boolean unsent = true;
        if ((state == ActivityState.RESUMED || (service.isSleeping()
        if ((state == ActivityState.RESUMED
                || (service.isSleeping() && task.stack != null
                    && task.stack.topRunningActivityLocked(null) == this))
                && app != null && app.thread != null) {
            try {
@@ -842,19 +883,27 @@ final class ActivityRecord {
    }

    boolean continueLaunchTickingLocked() {
        if (launchTickTime != 0) {
        if (launchTickTime == 0) {
            return false;
        }

        final ActivityStack stack = task.stack;
        if (stack == null) {
            return false;
        }

        Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG, this);
        stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
        stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK);
        return true;
    }
        return false;
    }

    void finishLaunchTickingLocked() {
        launchTickTime = 0;
        task.stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
        final ActivityStack stack = task.stack;
        if (stack != null) {
            stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
        }
    }

    // IApplicationToken
@@ -885,8 +934,8 @@ final class ActivityRecord {
        if (displayStartTime != 0) {
            reportLaunchTimeLocked(curTime);
        }
        if (fullyDrawnStartTime != 0) {
        final ActivityStack stack = task.stack;
        if (fullyDrawnStartTime != 0 && stack != null) {
            final long thisTime = curTime - fullyDrawnStartTime;
            final long totalTime = stack.mFullyDrawnStartTime != 0
                    ? (curTime - stack.mFullyDrawnStartTime) : thisTime;
@@ -911,13 +960,16 @@ final class ActivityRecord {
            if (totalTime > 0) {
                //service.mUsageStatsService.noteFullyDrawnTime(realActivity, (int) totalTime);
            }
            fullyDrawnStartTime = 0;
            stack.mFullyDrawnStartTime = 0;
        }
        fullyDrawnStartTime = 0;
    }

    private void reportLaunchTimeLocked(final long curTime) {
        final ActivityStack stack = task.stack;
        if (stack == null) {
            return;
        }
        final long thisTime = curTime - displayStartTime;
        final long totalTime = stack.mLaunchStartTime != 0
                ? (curTime - stack.mLaunchStartTime) : thisTime;
@@ -947,8 +999,7 @@ final class ActivityRecord {
        stack.mLaunchStartTime = 0;
    }

    public void windowsDrawn() {
        synchronized(service) {
    void windowsDrawnLocked() {
        if (displayStartTime != 0) {
            reportLaunchTimeLocked(SystemClock.uptimeMillis());
        }
@@ -959,32 +1010,26 @@ final class ActivityRecord {
            task.hasBeenVisible = true;
        }
    }
    }

    public void windowsVisible() {
        synchronized(service) {
    void windowsVisibleLocked() {
        mStackSupervisor.reportActivityVisibleLocked(this);
            if (ActivityManagerService.DEBUG_SWITCH) Log.v(TAG, "windowsVisible(): " + this);
        if (DEBUG_SWITCH) Log.v(TAG, "windowsVisibleLocked(): " + this);
        if (!nowVisible) {
            nowVisible = true;
            lastVisibleTime = SystemClock.uptimeMillis();
            if (!idle) {
                    // Instead of doing the full stop routine here, let's just
                    // hide any activities we now can, and let them stop when
                    // the normal idle happens.
                // Instead of doing the full stop routine here, let's just hide any activities
                // we now can, and let them stop when the normal idle happens.
                mStackSupervisor.processStoppingActivitiesLocked(false);
            } else {
                    // If this activity was already idle, then we now need to
                    // make sure we perform the full stop of any activities
                    // that are waiting to do so.  This is because we won't
                    // do that while they are still waiting for this one to
                    // become visible.
                    final int N = mStackSupervisor.mWaitingVisibleActivities.size();
                    if (N > 0) {
                        for (int i=0; i<N; i++) {
                // If this activity was already idle, then we now need to make sure we perform
                // the full stop of any activities that are waiting to do so. This is because
                // we won't do that while they are still waiting for this one to become visible.
                final int size = mStackSupervisor.mWaitingVisibleActivities.size();
                if (size > 0) {
                    for (int i = 0; i < size; i++) {
                        ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i);
                            if (ActivityManagerService.DEBUG_SWITCH) Log.v(TAG,
                                    "Was waiting for visible: " + r);
                        if (DEBUG_SWITCH) Log.v(TAG, "Was waiting for visible: " + r);
                    }
                    mStackSupervisor.mWaitingVisibleActivities.clear();
                    mStackSupervisor.scheduleIdleLocked();
@@ -993,14 +1038,8 @@ final class ActivityRecord {
            service.scheduleAppGcsLocked();
        }
    }
    }

    public void windowsGone() {
        if (ActivityManagerService.DEBUG_SWITCH) Log.v(TAG, "windowsGone(): " + this);
        nowVisible = false;
    }

    private ActivityRecord getWaitingHistoryRecordLocked() {
    ActivityRecord getWaitingHistoryRecordLocked() {
        // First find the real culprit...  if we are waiting
        // for another app to start, then we have paused dispatching
        // for this activity.
@@ -1021,24 +1060,6 @@ final class ActivityRecord {
        return r;
    }

    public boolean keyDispatchingTimedOut(String reason) {
        ActivityRecord r;
        ProcessRecord anrApp;
        synchronized(service) {
            r = getWaitingHistoryRecordLocked();
            anrApp = r != null ? r.app : null;
        }
        return service.inputDispatchingTimedOut(anrApp, r, this, false, reason);
    }

    /** Returns the key dispatching timeout for this application token. */
    public long getKeyDispatchingTimeout() {
        synchronized(service) {
            ActivityRecord r = getWaitingHistoryRecordLocked();
            return ActivityManagerService.getInputDispatchingTimeoutLocked(r);
        }
    }

    /**
     * This method will return true if the activity is either visible, is becoming visible, is
     * currently pausing, or is resumed.
@@ -1066,14 +1087,14 @@ final class ActivityRecord {
    }

    static void activityResumedLocked(IBinder token) {
        final ActivityRecord r = ActivityRecord.forToken(token);
        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
        if (DEBUG_SAVED_STATE) Slog.i(TAG, "Resumed activity; dropping state of: " + r);
        r.icicle = null;
        r.haveState = false;
    }

    static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
        final ActivityRecord r = ActivityRecord.forToken(token);
        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
        if (r == null) {
            return INVALID_TASK_ID;
        }
@@ -1086,7 +1107,7 @@ final class ActivityRecord {
    }

    static ActivityRecord isInStackLocked(IBinder token) {
        final ActivityRecord r = ActivityRecord.forToken(token);
        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
        return (r != null) ? r.task.stack.isInStackLocked(r) : null;
    }

+9 −9
Original line number Diff line number Diff line
@@ -461,7 +461,7 @@ final class ActivityStack {
    }

    ActivityRecord isInStackLocked(IBinder token) {
        final ActivityRecord r = ActivityRecord.forToken(token);
        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
        return isInStackLocked(r);
    }

@@ -470,7 +470,8 @@ final class ActivityStack {
            return null;
        }
        final TaskRecord task = r.task;
        if (task != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
        if (task != null && task.stack != null
                && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
            if (task.stack != this) Slog.w(TAG,
                    "Illegal state! task does not point to stack it is in.");
            return r;
@@ -2797,7 +2798,7 @@ final class ActivityStack {
            return false;
        }

        r.makeFinishing();
        r.makeFinishingLocked();
        final TaskRecord task = r.task;
        EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
                r.userId, System.identityHashCode(r),
@@ -2900,7 +2901,7 @@ final class ActivityStack {
                || prevState == ActivityState.INITIALIZING) {
            // If this activity is already stopped, we can just finish
            // it right now.
            r.makeFinishing();
            r.makeFinishingLocked();
            boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");
            if (activityRemoved) {
                mStackSupervisor.resumeTopActivitiesLocked();
@@ -2976,9 +2977,8 @@ final class ActivityStack {
        return false;
    }

    final boolean navigateUpToLocked(IBinder token, Intent destIntent, int resultCode,
    final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
            Intent resultData) {
        final ActivityRecord srec = ActivityRecord.forToken(token);
        final TaskRecord task = srec.task;
        final ArrayList<ActivityRecord> activities = task.mActivities;
        final int start = activities.indexOf(srec);
@@ -3125,7 +3125,7 @@ final class ActivityStack {
    private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) {
        mStackSupervisor.removeChildActivityContainers(r);
        finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
        r.makeFinishing();
        r.makeFinishingLocked();
        if (DEBUG_ADD_REMOVE) {
            RuntimeException here = new RuntimeException("here");
            here.fillInStackTrace();
@@ -3366,7 +3366,7 @@ final class ActivityStack {
    final void activityDestroyedLocked(IBinder token, String reason) {
        final long origId = Binder.clearCallingIdentity();
        try {
            ActivityRecord r = ActivityRecord.forToken(token);
            ActivityRecord r = ActivityRecord.forTokenLocked(token);
            if (r != null) {
                mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
            }
@@ -3947,7 +3947,7 @@ final class ActivityStack {
                }
            }
        }
        final ActivityRecord r = ActivityRecord.forToken(token);
        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
        if (r == null) {
            return false;
        }
+31 −13

File changed.

Preview size limit exceeded, changes collapsed.

+4 −2
Original line number Diff line number Diff line
@@ -275,8 +275,10 @@ final class PendingIntentRecord extends IIntentSender.Stub {
                        }
                        break;
                    case ActivityManager.INTENT_SENDER_ACTIVITY_RESULT:
                        if (key.activity.task.stack != null) {
                            key.activity.task.stack.sendActivityResultLocked(-1, key.activity,
                                    key.who, key.requestCode, code, finalIntent);
                        }
                        break;
                    case ActivityManager.INTENT_SENDER_BROADCAST:
                        try {
Loading