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

Commit 09183fb1 authored by Mohammed Rashidy's avatar Mohammed Rashidy Committed by Android (Google) Code Review
Browse files

Merge changes Ie4b018d9,I790ea567

* changes:
  Disable resolving while intercepting based on a flag
  Adding ActivityInterceptorCallbackRegistry
parents b3df7130 0fb4f28f
Loading
Loading
Loading
Loading
+49 −0
Original line number Original line Diff line number Diff line
@@ -169,3 +169,52 @@ package com.android.server.wifi {


}
}


package com.android.server.wm {

  public interface ActivityInterceptorCallback {
    method public default void onActivityLaunched(@NonNull android.app.TaskInfo, @NonNull android.content.pm.ActivityInfo, @NonNull com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo);
    method @Nullable public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptResult onInterceptActivityLaunch(@NonNull com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo);
    field public static final int MAINLINE_SDK_SANDBOX_ORDER_ID = 1001; // 0x3e9
  }

  public static final class ActivityInterceptorCallback.ActivityInterceptResult {
    ctor public ActivityInterceptorCallback.ActivityInterceptResult(@NonNull android.content.Intent, @NonNull android.app.ActivityOptions, boolean);
    method @NonNull public android.app.ActivityOptions getActivityOptions();
    method @NonNull public android.content.Intent getIntent();
    method public boolean isActivityResolved();
  }

  public static final class ActivityInterceptorCallback.ActivityInterceptorInfo {
    method @NonNull public android.content.pm.ActivityInfo getActivityInfo();
    method @Nullable public String getCallingFeatureId();
    method @Nullable public String getCallingPackage();
    method public int getCallingPid();
    method public int getCallingUid();
    method @Nullable public android.app.ActivityOptions getCheckedOptions();
    method @Nullable public Runnable getClearOptionsAnimationRunnable();
    method @NonNull public android.content.Intent getIntent();
    method public int getRealCallingPid();
    method public int getRealCallingUid();
    method @NonNull public android.content.pm.ResolveInfo getResolveInfo();
    method @Nullable public String getResolvedType();
    method public int getUserId();
  }

  public static final class ActivityInterceptorCallback.ActivityInterceptorInfo.Builder {
    ctor public ActivityInterceptorCallback.ActivityInterceptorInfo.Builder(int, int, int, int, int, @NonNull android.content.Intent, @NonNull android.content.pm.ResolveInfo, @NonNull android.content.pm.ActivityInfo);
    method @NonNull public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo build();
    method @NonNull public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo.Builder setCallingFeatureId(@NonNull String);
    method @NonNull public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo.Builder setCallingPackage(@NonNull String);
    method @NonNull public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo.Builder setCheckedOptions(@NonNull android.app.ActivityOptions);
    method @NonNull public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo.Builder setClearOptionsAnimationRunnable(@NonNull Runnable);
    method @NonNull public com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo.Builder setResolvedType(@NonNull String);
  }

  public class ActivityInterceptorCallbackRegistry {
    method @NonNull public static com.android.server.wm.ActivityInterceptorCallbackRegistry getInstance();
    method public void registerActivityInterceptorCallback(int, @NonNull com.android.server.wm.ActivityInterceptorCallback);
    method public void unregisterActivityInterceptorCallback(int);
  }

}
+34 −3
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.wm;
import android.annotation.IntDef;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.ActivityOptions;
import android.app.ActivityOptions;
import android.app.TaskInfo;
import android.app.TaskInfo;
import android.content.Intent;
import android.content.Intent;
@@ -33,6 +34,7 @@ import java.lang.annotation.RetentionPolicy;
 * be called with the WindowManagerGlobalLock held.
 * be called with the WindowManagerGlobalLock held.
 * @hide
 * @hide
 */
 */
@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
public interface ActivityInterceptorCallback {
public interface ActivityInterceptorCallback {
    /**
    /**
     * Called to allow intercepting activity launching based on the provided launch parameters and
     * Called to allow intercepting activity launching based on the provided launch parameters and
@@ -165,6 +167,7 @@ public interface ActivityInterceptorCallback {
     * Data class for storing the various arguments needed for activity interception.
     * Data class for storing the various arguments needed for activity interception.
     * @hide
     * @hide
     */
     */
    @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
    final class ActivityInterceptorInfo {
    final class ActivityInterceptorInfo {
        private final int mCallingUid;
        private final int mCallingUid;
        private final int mCallingPid;
        private final int mCallingPid;
@@ -389,6 +392,7 @@ public interface ActivityInterceptorCallback {
     * Data class for storing the intercept result.
     * Data class for storing the intercept result.
     * @hide
     * @hide
     */
     */
    @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
    final class ActivityInterceptResult {
    final class ActivityInterceptResult {
        @NonNull
        @NonNull
        private final Intent mIntent;
        private final Intent mIntent;
@@ -396,15 +400,35 @@ public interface ActivityInterceptorCallback {
        @NonNull
        @NonNull
        private final ActivityOptions mActivityOptions;
        private final ActivityOptions mActivityOptions;


        /** Generates the result of intercepting launching the {@link android.app.Activity}
        private final boolean mActivityResolved;

        /**
         * This constructor should only be used if both {@link ActivityInfo} and {@link ResolveInfo}
         * did not get resolved while interception.
         * @hide
         */
        public ActivityInterceptResult(@NonNull Intent intent,
                @NonNull ActivityOptions activityOptions) {
            this(intent, activityOptions, false /* activityResolved */);
        }

        /**
         * Generates the result of intercepting launching the {@link android.app.Activity}
         *
         * <p>Interceptor should return non-{@code null} result when {@link
         * #onInterceptActivityLaunch(ActivityInterceptorInfo)} gets called as an indicator that
         * interception has happened.
         *
         *
         * @param intent is the modified {@link Intent} after interception.
         * @param intent is the modified {@link Intent} after interception.
         * @param activityOptions holds the {@link ActivityOptions} after interception.
         * @param activityOptions holds the {@link ActivityOptions} after interception.
         * @param activityResolved should be {@code true} only if {@link ActivityInfo} or {@link
         *                         ResolveInfo} gets resolved, otherwise should be {@code false}.
         */
         */
        public ActivityInterceptResult(
        public ActivityInterceptResult(@NonNull Intent intent,
                @NonNull Intent intent, @NonNull ActivityOptions activityOptions) {
                @NonNull ActivityOptions activityOptions, boolean activityResolved) {
            this.mIntent = intent;
            this.mIntent = intent;
            this.mActivityOptions = activityOptions;
            this.mActivityOptions = activityOptions;
            this.mActivityResolved = activityResolved;
        }
        }


        /** Returns the intercepted {@link Intent} */
        /** Returns the intercepted {@link Intent} */
@@ -419,5 +443,12 @@ public interface ActivityInterceptorCallback {
        public ActivityOptions getActivityOptions() {
        public ActivityOptions getActivityOptions() {
            return mActivityOptions;
            return mActivityOptions;
        }
        }

        /**
         * Returns if the {@link ActivityInfo} or {@link ResolveInfo} gets resolved.
         */
        public boolean isActivityResolved() {
            return mActivityResolved;
        }
    }
    }
}
}
+122 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2022 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.server.wm;

import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Binder;
import android.os.Process;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;

/**
 * This class should be used by system services which are part of mainline modules to register
 * {@link ActivityInterceptorCallback}. For other system services, this function should be used
 * instead {@link ActivityTaskManagerInternal#registerActivityStartInterceptor(
 * int, ActivityInterceptorCallback)}.
 * @hide
 */
@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
public class ActivityInterceptorCallbackRegistry {

    private static final ActivityInterceptorCallbackRegistry sInstance =
            new ActivityInterceptorCallbackRegistry();

    private ActivityInterceptorCallbackRegistry() {}

    /** Returns an already initialised singleton instance of this class. */
    @NonNull
    public static ActivityInterceptorCallbackRegistry getInstance() {
        return sInstance;
    }

    /**
     * Registers a callback which can intercept activity launching flow.
     *
     * <p>Only system services which are part of mainline modules should call this function.
     *
     * <p>To avoid Activity launch delays, the callbacks must execute quickly and avoid acquiring
     * other system process locks.
     *
     * @param mainlineOrderId has to be one of the following [{@link
     *                        ActivityInterceptorCallback#MAINLINE_FIRST_ORDERED_ID}].
     * @param callback the {@link ActivityInterceptorCallback} to register.
     * @throws IllegalArgumentException if duplicate ids are provided, the provided id is not the
     * mainline module range or the provided {@code callback} is null.
     */
    // ExecutorRegistration is suppressed as the callback is called synchronously in the system
    // server.
    @SuppressWarnings("ExecutorRegistration")
    public void registerActivityInterceptorCallback(
            @ActivityInterceptorCallback.OrderedId int mainlineOrderId,
            @NonNull ActivityInterceptorCallback callback) {
        if (getCallingUid() != Process.SYSTEM_UID) {
            throw new SecurityException("Only system server can register "
                    + "ActivityInterceptorCallback");
        }
        if (!ActivityInterceptorCallback.isValidMainlineOrderId(mainlineOrderId)) {
            throw new IllegalArgumentException("id is not in the mainline modules range, please use"
                    + "ActivityTaskManagerInternal.registerActivityStartInterceptor(OrderedId, "
                    + "ActivityInterceptorCallback) instead.");
        }
        if (callback == null) {
            throw new IllegalArgumentException("The passed ActivityInterceptorCallback can not be "
                    + "null");
        }
        ActivityTaskManagerInternal activityTaskManagerInternal =
                LocalServices.getService(ActivityTaskManagerInternal.class);
        activityTaskManagerInternal.registerActivityStartInterceptor(mainlineOrderId, callback);
    }

    /**
     * Unregisters an already registered {@link ActivityInterceptorCallback}.
     *
     * @param mainlineOrderId the order id of the {@link ActivityInterceptorCallback} should be
     *                        unregistered, this callback should be registered before by calling
     *                        {@link #registerActivityInterceptorCallback(int,
     *                        ActivityInterceptorCallback)} using the same order id.
     * @throws IllegalArgumentException if the provided id is not the mainline module range or is
     * not registered
     */
    public void unregisterActivityInterceptorCallback(
            @ActivityInterceptorCallback.OrderedId int mainlineOrderId) {
        if (getCallingUid() != Process.SYSTEM_UID) {
            throw new SecurityException("Only system server can register "
                    + "ActivityInterceptorCallback");
        }
        if (!ActivityInterceptorCallback.isValidMainlineOrderId(mainlineOrderId)) {
            throw new IllegalArgumentException("id is not in the mainline modules range, please use"
                    + "ActivityTaskManagerInternal.unregisterActivityStartInterceptor(OrderedId) "
                    + "instead.");
        }
        ActivityTaskManagerInternal activityTaskManagerInternal =
                LocalServices.getService(ActivityTaskManagerInternal.class);
        activityTaskManagerInternal.unregisterActivityStartInterceptor(mainlineOrderId);
    }

    /**
     * This hidden function is for unit tests as a way to behave like as if they are called from
     * system server process uid by mocking it and returning {@link Process#SYSTEM_UID}.
     * Do not make this {@code public} to apps as apps should not have a way to change the uid.
     * @hide
     */
    @VisibleForTesting
    int getCallingUid() {
        return Binder.getCallingUid();
    }
}
+3 −0
Original line number Original line Diff line number Diff line
@@ -244,6 +244,9 @@ class ActivityStartInterceptor {
            mActivityOptions = interceptResult.getActivityOptions();
            mActivityOptions = interceptResult.getActivityOptions();
            mCallingPid = mRealCallingPid;
            mCallingPid = mRealCallingPid;
            mCallingUid = mRealCallingUid;
            mCallingUid = mRealCallingUid;
            if (interceptResult.isActivityResolved()) {
                return true;
            }
            mRInfo = mSupervisor.resolveIntent(mIntent, null, mUserId, 0, mRealCallingUid);
            mRInfo = mSupervisor.resolveIntent(mIntent, null, mUserId, 0, mRealCallingUid);
            mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags,
            mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags,
                    null /*profilerInfo*/);
                    null /*profilerInfo*/);
+12 −1
Original line number Original line Diff line number Diff line
@@ -680,12 +680,23 @@ public abstract class ActivityTaskManagerInternal {


    /**
    /**
     * Registers a callback which can intercept activity starts.
     * Registers a callback which can intercept activity starts.
     * @throws IllegalArgumentException if duplicate ids are provided
     * @throws IllegalArgumentException if duplicate ids are provided or the provided {@code
     * callback} is null
     * @see ActivityInterceptorCallbackRegistry
     * #registerActivityInterceptorCallback(int, ActivityInterceptorCallback)
     */
     */
    public abstract void registerActivityStartInterceptor(
    public abstract void registerActivityStartInterceptor(
            @ActivityInterceptorCallback.OrderedId int id,
            @ActivityInterceptorCallback.OrderedId int id,
            ActivityInterceptorCallback callback);
            ActivityInterceptorCallback callback);


    /**
     * Unregisters an {@link ActivityInterceptorCallback}.
     * @throws IllegalArgumentException if id is not registered
     * @see ActivityInterceptorCallbackRegistry#unregisterActivityInterceptorCallback(int)
     */
    public abstract void unregisterActivityStartInterceptor(
            @ActivityInterceptorCallback.OrderedId int id);

    /** Get the most recent task excluding the first running task (the one on the front most). */
    /** Get the most recent task excluding the first running task (the one on the front most). */
    public abstract ActivityManager.RecentTaskInfo getMostRecentTaskFromBackground();
    public abstract ActivityManager.RecentTaskInfo getMostRecentTaskFromBackground();


Loading