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

Commit 87c7caa4 authored by Robert Horvath's avatar Robert Horvath
Browse files

Finish DreamActivity on creation if it is obsolete

DreamService keeps a reference to its DreamActivity, and finishes it
when the dream stops. This reference is set when the DreamActivity
receives its onCreate lifecycle callback.

If a dream is stopped shortly after it started, before its DreamActivity
was created, the DreamActivity can be created after the dream is
supposed to be finished, and finish isn't called on the activity.
If another dream starts another DreamActivity, the reference to the old
DreamActivity is overwritten and lost, so that DreamService can no
longer finish the old DreamActivity.

This change tracks the DreamToken, unique to each dream, that an
activity was started for. If an activity is created for a dream that is
already finished, the activity is finished immediately.

Bug: 229561570
Test: manual, with adding delay before startDreamActivity to ease
      reproduction
Change-Id: I0fca226855ee4e2317ac807a4c87c8656c72169b
parent 9cbaca73
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -58,8 +58,9 @@ public class DreamActivity extends Activity {
            setTitle(title);
        }

        DreamService.DreamServiceWrapper callback =
                (DreamService.DreamServiceWrapper) getIntent().getIBinderExtra(EXTRA_CALLBACK);
        final Bundle extras = getIntent().getExtras();
        final DreamService.DreamActivityCallback callback =
                (DreamService.DreamActivityCallback) extras.getBinder(EXTRA_CALLBACK);

        if (callback != null) {
            callback.onActivityCreated(this);
+31 −5
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.content.pm.ServiceInfo;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
@@ -1264,7 +1265,7 @@ public class DreamService extends Service implements Window.Callback {
            Intent i = new Intent(this, DreamActivity.class);
            i.setPackage(getApplicationContext().getPackageName());
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            i.putExtra(DreamActivity.EXTRA_CALLBACK, mDreamServiceWrapper);
            i.putExtra(DreamActivity.EXTRA_CALLBACK, new DreamActivityCallback(mDreamToken));
            final ServiceInfo serviceInfo = fetchServiceInfo(this,
                    new ComponentName(this, getClass()));
            i.putExtra(DreamActivity.EXTRA_DREAM_TITLE, fetchDreamLabel(this, serviceInfo));
@@ -1444,11 +1445,36 @@ public class DreamService extends Service implements Window.Callback {
        public void wakeUp() {
            mHandler.post(() -> DreamService.this.wakeUp(true /*fromSystem*/));
        }
    }

    /** @hide */
        void onActivityCreated(DreamActivity a) {
            mActivity = a;
            onWindowCreated(a.getWindow());
    final class DreamActivityCallback extends Binder {
        private final IBinder mActivityDreamToken;

        DreamActivityCallback(IBinder token) {
            mActivityDreamToken = token;
        }

        void onActivityCreated(DreamActivity activity) {
            if (mActivityDreamToken != mDreamToken || mFinished) {
                Slog.d(TAG, "DreamActivity was created after the dream was finished or "
                        + "a new dream started, finishing DreamActivity");
                if (!activity.isFinishing()) {
                    activity.finishAndRemoveTask();
                }
                return;
            }
            if (mActivity != null) {
                Slog.w(TAG, "A DreamActivity has already been started, "
                        + "finishing latest DreamActivity");
                if (!activity.isFinishing()) {
                    activity.finishAndRemoveTask();
                }
                return;
            }

            mActivity = activity;
            onWindowCreated(activity.getWindow());
        }
    }