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

Commit 00295b21 authored by Azhara Assanova's avatar Azhara Assanova
Browse files

Add Component Caller APIs for Activity's results

In continuation to ag/25895815, with activities potentially receiving
multiple results at the same time, it is important to match intents to
their callers correctly. Hence this change overloads existing
onActivityResult() with a ComponentCaller - onActivityResult(int, int,
Intent, ComponentCaller).

More CTS for ComponentCaller#checkContentUriPermission are incoming.

Bug: 293467489
Test: atest CtsAndroidAppTestCases:android.app.cts.ComponentCallerTest
Test: atest CtsAndroidAppTestCases:android.app.cts.ShareIdentityTest
Change-Id: Idb56fc8cc6331afee7b30653bd0e3e771ba2e3f0
parent c6eaf1ca
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -4433,6 +4433,7 @@ package android.app {
    method @CallSuper public void onActionModeStarted(android.view.ActionMode);
    method public void onActivityReenter(int, android.content.Intent);
    method protected void onActivityResult(int, int, android.content.Intent);
    method @FlaggedApi("android.security.content_uri_permission_apis") public void onActivityResult(int, int, @NonNull android.content.Intent, @NonNull android.app.ComponentCaller);
    method @Deprecated public void onAttachFragment(android.app.Fragment);
    method public void onAttachedToWindow();
    method @Deprecated public void onBackPressed();
+61 −9
Original line number Diff line number Diff line
@@ -858,11 +858,15 @@ public class Activity extends ContextThemeWrapper
     */
    private ComponentCaller mCaller;
    /**
     * Caller associated with an Intent within {@link #onNewIntent}. Can be retrieved from
     * {@link #getCurrentCaller}, or by overriding {@link #onNewIntent(Intent, ComponentCaller)} and
     * getting the second argument.
     * Caller associated with an Intent within {@link #onNewIntent} and {@link #onActivityResult}.
     * Can be retrieved from either of these methods:
     * - {@link #getCurrentCaller}
     * - By overriding {@link #onNewIntent(Intent, ComponentCaller)} and getting the second argument
     * - By overriding {@link #onActivityResult(int, int, Intent, ComponentCaller)} and getting the
     * fourth argument
     *
     * <p>The value of this field will be {@code null} outside of {@link #onNewIntent}.
     * <p>The value of this field will be {@code null} outside of {@link #onNewIntent} and
     * {@link #onActivityResult}.
     */
    private ComponentCaller mCurrentCaller;

@@ -7140,13 +7144,15 @@ public class Activity extends ContextThemeWrapper

    /**
     * Returns the ComponentCaller instance of the app that re-launched this activity with a new
     * intent via {@link #onNewIntent}.
     * intent via {@link #onNewIntent} or {@link #onActivityResult}.
     *
     * <p>Note that this method only works within the {@link #onNewIntent} method. If you call this
     * method outside {@link #onNewIntent}, it will throw an {@link IllegalStateException}.
     * <p>Note that this method only works within the {@link #onNewIntent} and
     * {@link #onActivityResult} methods. If you call this method outside {@link #onNewIntent} and
     * {@link #onActivityResult}, it will throw an {@link IllegalStateException}.
     *
     * <p>You can also retrieve the caller if you override
     * {@link #onNewIntent(Intent, ComponentCaller)}.
     * {@link #onNewIntent(Intent, ComponentCaller)} or
     * {@link #onActivityResult(int, int, Intent, ComponentCaller)}.
     *
     * <p>To keep the ComponentCaller instance for future use, call
     * {@link #setIntent(Intent, ComponentCaller)}, and use {@link #getCaller} to retrieve it.
@@ -7426,6 +7432,31 @@ public class Activity extends ContextThemeWrapper
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    }

    /**
     * Same as {@link #onActivityResult(int, int, Intent)}, but with an extra parameter for the
     * ComponentCaller instance associated with the app that sent the result.
     *
     * <p>If you want to retrieve the caller without overriding this method, call
     * {@link #getCurrentCaller} inside your existing {@link #onActivityResult(int, int, Intent)}.
     *
     * <p>Note that you should only override one {@link #onActivityResult} method.
     *
     * @param requestCode The integer request code originally supplied to
     *                    startActivityForResult(), allowing you to identify who this
     *                    result came from.
     * @param resultCode The integer result code returned by the child activity
     *                   through its setResult().
     * @param data An Intent, which can return result data to the caller
     *               (various data can be attached to Intent "extras").
     * @param caller The {@link ComponentCaller} instance associated with the app that sent the
     *               intent.
     */
    @FlaggedApi(android.security.Flags.FLAG_CONTENT_URI_PERMISSION_APIS)
    public void onActivityResult(int requestCode, int resultCode, @NonNull Intent data,
            @NonNull ComponentCaller caller) {
        onActivityResult(requestCode, resultCode, data);
    }

    /**
     * Called when an activity you launched with an activity transition exposes this
     * Activity through a returning activity transition, giving you the resultCode
@@ -9270,15 +9301,36 @@ public class Activity extends ContextThemeWrapper
        }
    }

    void dispatchActivityResult(String who, int requestCode, int resultCode, Intent data,
            ComponentCaller caller, String reason) {
        internalDispatchActivityResult(who, requestCode, resultCode, data, caller, reason);
    }

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    void dispatchActivityResult(String who, int requestCode, int resultCode, Intent data,
            String reason) {
        if (android.security.Flags.contentUriPermissionApis()) {
            internalDispatchActivityResult(who, requestCode, resultCode, data,
                    new ComponentCaller(getActivityToken(), /* callerToken */ null), reason);
        } else {
            internalDispatchActivityResult(who, requestCode, resultCode, data, null, reason);
        }
    }

    private void internalDispatchActivityResult(String who, int requestCode, int resultCode,
            Intent data, ComponentCaller caller, String reason) {
        if (false) Log.v(
            TAG, "Dispatching result: who=" + who + ", reqCode=" + requestCode
            + ", resCode=" + resultCode + ", data=" + data);
        mFragments.noteStateNotSaved();
        if (who == null) {
            if (android.security.Flags.contentUriPermissionApis()) {
                mCurrentCaller = caller;
                onActivityResult(requestCode, resultCode, data, caller);
                mCurrentCaller = null;
            } else {
                onActivityResult(requestCode, resultCode, data);
            }
        } else if (who.startsWith(REQUEST_PERMISSIONS_WHO_PREFIX)) {
            who = who.substring(REQUEST_PERMISSIONS_WHO_PREFIX.length());
            if (TextUtils.isEmpty(who)) {
+2 −2
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ public class ActivityGroup extends Activity {

    @Override
    void dispatchActivityResult(String who, int requestCode, int resultCode,
            Intent data, String reason) {
            Intent data, ComponentCaller caller, String reason) {
        if (who != null) {
            Activity act = mLocalActivityManager.getActivity(who);
            /*
@@ -125,7 +125,7 @@ public class ActivityGroup extends Activity {
                return;
            }
        }
        super.dispatchActivityResult(who, requestCode, resultCode, data, reason);
        super.dispatchActivityResult(who, requestCode, resultCode, data, caller, reason);
    }
}

+9 −3
Original line number Diff line number Diff line
@@ -3736,7 +3736,7 @@ public final class ActivityThread extends ClientTransactionHandler
        if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id
                + " req=" + requestCode + " res=" + resultCode + " data=" + data);
        final ArrayList<ResultInfo> list = new ArrayList<>();
        list.add(new ResultInfo(id, requestCode, resultCode, data));
        list.add(new ResultInfo(id, requestCode, resultCode, data, activityToken));
        final ClientTransaction clientTransaction = ClientTransaction.obtain(mAppThread);
        final ActivityResultItem activityResultItem = ActivityResultItem.obtain(
                activityToken, list);
@@ -5757,8 +5757,14 @@ public final class ActivityThread extends ClientTransactionHandler
                }
                if (DEBUG_RESULTS) Slog.v(TAG,
                        "Delivering result to activity " + r + " : " + ri);
                if (android.security.Flags.contentUriPermissionApis()) {
                    ComponentCaller caller = new ComponentCaller(r.token, ri.mCallerToken);
                    r.activity.dispatchActivityResult(ri.mResultWho,
                            ri.mRequestCode, ri.mResultCode, ri.mData, caller, reason);
                } else {
                    r.activity.dispatchActivityResult(ri.mResultWho,
                            ri.mRequestCode, ri.mResultCode, ri.mData, reason);
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(r.activity, e)) {
                    throw new RuntimeException(
+13 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;

@@ -36,14 +37,21 @@ public class ResultInfo implements Parcelable {
    public final int mResultCode;
    @UnsupportedAppUsage
    public final Intent mData;
    public final IBinder mCallerToken;

    @UnsupportedAppUsage
    public ResultInfo(String resultWho, int requestCode, int resultCode,
            Intent data) {
        this(resultWho, requestCode, resultCode, data, /* callerToken */ null);
    }

    public ResultInfo(String resultWho, int requestCode, int resultCode,
            Intent data, IBinder callerToken) {
        mResultWho = resultWho;
        mRequestCode = requestCode;
        mResultCode = resultCode;
        mData = data;
        mCallerToken = callerToken;
    }

    public String toString() {
@@ -65,6 +73,7 @@ public class ResultInfo implements Parcelable {
        } else {
            out.writeInt(0);
        }
        out.writeStrongBinder(mCallerToken);
    }

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -88,6 +97,7 @@ public class ResultInfo implements Parcelable {
        } else {
            mData = null;
        }
        mCallerToken = in.readStrongBinder();
    }

    @Override
@@ -100,7 +110,8 @@ public class ResultInfo implements Parcelable {
                : mData.filterEquals(other.mData);
        return intentsEqual && Objects.equals(mResultWho, other.mResultWho)
                && mResultCode == other.mResultCode
                && mRequestCode == other.mRequestCode;
                && mRequestCode == other.mRequestCode
                && mCallerToken == other.mCallerToken;
    }

    @Override
@@ -112,6 +123,7 @@ public class ResultInfo implements Parcelable {
        if (mData != null) {
            result = 31 * result + mData.filterHashCode();
        }
        result = 31 * result + Objects.hashCode(mCallerToken);
        return result;
    }
}
Loading