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

Commit dedda055 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Using a proxy activity for startActivityForResult

This ensures that the home task is never blocked by a different task

Bug: 74500048
Change-Id: I01fd26f1d6242e39b2d8fabac5e064b748aebe62
parent 7daf892f
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -85,6 +85,13 @@
            android:name="com.android.launcher3.uioverrides.dynamicui.WallpaperManagerCompatVL$ColorExtractionService"
            tools:node="remove" />

        <activity
            android:name="com.android.launcher3.proxy.ProxyActivityStarter"
            android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"
            android:launchMode="singleTask"
            android:clearTaskOnLaunch="true"
            android:exported="false" />

    </application>

</manifest>
+82 −0
Original line number Diff line number Diff line
/*
 * 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.launcher3.proxy;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.util.Log;

public class ProxyActivityStarter extends Activity {

    private static final String TAG = "ProxyActivityStarter";

    public static final String EXTRA_PARAMS = "start-activity-params";

    private StartActivityParams mParams;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setVisible(false);

        mParams = getIntent().getParcelableExtra(EXTRA_PARAMS);
        if (mParams == null) {
            Log.d(TAG, "Proxy activity started without params");
            finishAndRemoveTask();
            return;
        }

        if (savedInstanceState != null) {
            // Already started the activity. Just wait for the result.
            return;
        }

        if (mParams.intent != null) {
            startActivityForResult(mParams.intent, mParams.requestCode, mParams.options);
            return;
        } else if (mParams.intentSender != null) {
            try {
                startIntentSenderForResult(mParams.intentSender, mParams.requestCode,
                        mParams.fillInIntent, mParams.flagsMask, mParams.flagsValues,
                        mParams.extraFlags,
                        mParams.options);
                return;
            } catch (SendIntentException e) {
                mParams.deliverResult(this, RESULT_CANCELED, null);
            }
        }
        finishAndRemoveTask();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == mParams.requestCode) {
            mParams.deliverResult(this, resultCode, data);
        }
        finishAndRemoveTask();
    }

    public static Intent getLaunchIntent(Context context, StartActivityParams params) {
        return new Intent(context, ProxyActivityStarter.class)
                .putExtra(EXTRA_PARAMS, params)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                        | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    }
}
+103 −0
Original line number Diff line number Diff line
/*
 * 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.launcher3.proxy;

import android.app.Activity;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

public class StartActivityParams implements Parcelable {

    private static final String TAG = "StartActivityParams";

    private final PendingIntent mCallback;
    public final int requestCode;

    public Intent intent;

    public IntentSender intentSender;
    public Intent fillInIntent;
    public int flagsMask;
    public int flagsValues;
    public int extraFlags;
    public Bundle options;

    public StartActivityParams(Activity activity, int requestCode) {
        mCallback = activity.createPendingResult(requestCode, new Intent(),
                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
        this.requestCode = requestCode;
    }

    private StartActivityParams(Parcel parcel) {
        mCallback = parcel.readTypedObject(PendingIntent.CREATOR);
        requestCode = parcel.readInt();
        intent = parcel.readTypedObject(Intent.CREATOR);

        intentSender = parcel.readTypedObject(IntentSender.CREATOR);
        fillInIntent = parcel.readTypedObject(Intent.CREATOR);
        flagsMask = parcel.readInt();
        flagsValues = parcel.readInt();
        extraFlags = parcel.readInt();
        options = parcel.readBundle();
    }


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeTypedObject(mCallback, flags);
        parcel.writeInt(requestCode);
        parcel.writeTypedObject(intent, flags);

        parcel.writeTypedObject(intentSender, flags);
        parcel.writeTypedObject(fillInIntent, flags);
        parcel.writeInt(flagsMask);
        parcel.writeInt(flagsValues);
        parcel.writeInt(extraFlags);
        parcel.writeBundle(options);
    }

    public void deliverResult(Context context, int resultCode, Intent data) {
        try {
            mCallback.send(context, resultCode, data);
        } catch (CanceledException e) {
            Log.e(TAG, "Unable to send back result", e);
        }
    }

    public static final Parcelable.Creator<StartActivityParams> CREATOR =
            new Parcelable.Creator<StartActivityParams>() {
                public StartActivityParams createFromParcel(Parcel source) {
                    return new StartActivityParams(source);
                }

                public StartActivityParams[] newArray(int size) {
                    return new StartActivityParams[size];
                }
            };
}
+41 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.launcher3.uioverrides;

import static android.app.Activity.RESULT_CANCELED;

import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
import static com.android.launcher3.LauncherState.ALL_APPS;
@@ -31,6 +33,9 @@ import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.util.Base64;

@@ -43,6 +48,8 @@ import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.QuickstepAppTransitionManagerImpl;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.proxy.ProxyActivityStarter;
import com.android.launcher3.proxy.StartActivityParams;
import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.SysUINavigationMode;
@@ -192,6 +199,40 @@ public class UiFactory extends RecentsUiFactory {
        return true;
    }

    public static boolean startIntentSenderForResult(Activity activity, IntentSender intent,
            int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
            Bundle options) {
        StartActivityParams params = new StartActivityParams(activity, requestCode);
        params.intentSender = intent;
        params.fillInIntent = fillInIntent;
        params.flagsMask = flagsMask;
        params.flagsValues = flagsValues;
        params.extraFlags = extraFlags;
        params.options = options;
        ((Context) activity).startActivity(ProxyActivityStarter.getLaunchIntent(activity, params));
        return true;
    }

    public static boolean startActivityForResult(Activity activity, Intent intent, int requestCode,
            Bundle options) {
        StartActivityParams params = new StartActivityParams(activity, requestCode);
        params.intent = intent;
        params.options = options;
        activity.startActivity(ProxyActivityStarter.getLaunchIntent(activity, params));
        return true;
    }

    /**
     * Removes any active ProxyActivityStarter task and sends RESULT_CANCELED to Launcher.
     *
     * ProxyActivityStarter is started with clear task to reset the task after which it removes the
     * task itself.
     */
    public static void resetPendingActivityResults(Launcher launcher, int requestCode) {
        launcher.onActivityResult(requestCode, RESULT_CANCELED, null);
        launcher.startActivity(ProxyActivityStarter.getLaunchIntent(launcher, null));
    }

    public static ScaleAndTranslation getOverviewScaleAndTranslationForNormalState(Launcher l) {
        if (SysUINavigationMode.getMode(l) == Mode.NO_BUTTON) {
            float offscreenTranslationX = l.getDeviceProfile().widthPx
+39 −8
Original line number Diff line number Diff line
@@ -72,7 +72,6 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.OvershootInterpolator;
import android.widget.Toast;
@@ -191,6 +190,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
    private static final String RUNTIME_STATE = "launcher.state";
    // Type: PendingRequestArgs
    private static final String RUNTIME_STATE_PENDING_REQUEST_ARGS = "launcher.request_args";
    // Type: int
    private static final String RUNTIME_STATE_PENDING_REQUEST_CODE = "launcher.request_code";
    // Type: ActivityResultInfo
    private static final String RUNTIME_STATE_PENDING_ACTIVITY_RESULT = "launcher.activity_result";
    // Type: SparseArray<Parcelable>
@@ -264,6 +265,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
     * {@link #startActivityForResult(Intent, int)} or {@link #requestPermissions(String[], int)}
     */
    private PendingRequestArgs mPendingRequestArgs;
    // Request id for any pending activity result
    private int mPendingActivityRequestCode = -1;

    public ViewGroupFocusHelper mFocusHandler;

@@ -762,6 +765,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
    @Override
    public void onActivityResult(
            final int requestCode, final int resultCode, final Intent data) {
        mPendingActivityRequestCode = -1;
        handleActivityResult(requestCode, resultCode, data);
        if (mLauncherCallbacks != null) {
            mLauncherCallbacks.onActivityResult(requestCode, resultCode, data);
@@ -890,7 +894,19 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,

            UiFactory.onLauncherStateOrResumeChanged(this);
            AppLaunchTracker.INSTANCE.get(this).onReturnedToHome();
            resetPendingActivityResultIfNeeded();
        }
    }

    private void resetPendingActivityResultIfNeeded() {
        if (hasBeenResumed() && mPendingActivityRequestCode != -1 && isInState(NORMAL)) {
            UiFactory.resetPendingActivityResults(this, mPendingActivityRequestCode);
        }
    }

    protected void onStateSet(LauncherState state) {
        getAppWidgetHost().setResumed(state == LauncherState.NORMAL);
        resetPendingActivityResultIfNeeded();
    }

    @Override
@@ -1009,6 +1025,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
        if (requestArgs != null) {
            setWaitingForResult(requestArgs);
        }
        mPendingActivityRequestCode = savedState.getInt(RUNTIME_STATE_PENDING_REQUEST_CODE);

        mPendingActivityResult = savedState.getParcelable(RUNTIME_STATE_PENDING_ACTIVITY_RESULT);

@@ -1392,6 +1409,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
        if (mPendingRequestArgs != null) {
            outState.putParcelable(RUNTIME_STATE_PENDING_REQUEST_ARGS, mPendingRequestArgs);
        }
        outState.putInt(RUNTIME_STATE_PENDING_REQUEST_CODE, mPendingActivityRequestCode);

        if (mPendingActivityResult != null) {
            outState.putParcelable(RUNTIME_STATE_PENDING_ACTIVITY_RESULT, mPendingActivityResult);
        }
@@ -1448,12 +1467,23 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,

    @Override
    public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
        if (requestCode != -1) {
            mPendingActivityRequestCode = requestCode;
        }
        if (requestCode == -1
                || !UiFactory.startActivityForResult(this, intent, requestCode, options)) {
            super.startActivityForResult(intent, requestCode, options);
        }
    }

    @Override
    public void startIntentSenderForResult(IntentSender intent, int requestCode,
            Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options) {
        if (requestCode != -1) {
            mPendingActivityRequestCode = requestCode;
        }
        if (requestCode == -1 || !UiFactory.startIntentSenderForResult(this, intent, requestCode,
                fillInIntent, flagsMask, flagsValues, extraFlags, options)) {
            try {
                super.startIntentSenderForResult(intent, requestCode,
                        fillInIntent, flagsMask, flagsValues, extraFlags, options);
@@ -1461,6 +1491,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
                throw new ActivityNotFoundException();
            }
        }
    }

    /**
     * Indicates that we want global search for this activity by setting the globalSearch
Loading