1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.app.ActivityOptions; 23 import android.app.TaskInfo; 24 import android.content.Intent; 25 import android.content.pm.ActivityInfo; 26 import android.content.pm.ResolveInfo; 27 28 import java.lang.annotation.Retention; 29 import java.lang.annotation.RetentionPolicy; 30 31 /** 32 * Callback to intercept activity starts and possibly block/redirect them. The callback methods will 33 * be called with the WindowManagerGlobalLock held. 34 */ 35 public abstract class ActivityInterceptorCallback { 36 /** 37 * Intercept the launch intent based on various signals. If an interception happened, returns 38 * a new/existing non-null {@link ActivityInterceptResult} which may redirect to another 39 * activity or with new {@link ActivityOptions}. 40 * 41 * @return null if no interception occurred, or a non-null result which replaces the existing 42 * intent and activity options. 43 */ intercept(ActivityInterceptorInfo info)44 public abstract @Nullable ActivityInterceptResult intercept(ActivityInterceptorInfo info); 45 46 /** 47 * Called when an activity is successfully launched. The intent included in the 48 * ActivityInterceptorInfo may have changed from the one sent in 49 * {@link #intercept(ActivityInterceptorInfo)}, due to the return from 50 * {@link #intercept(ActivityInterceptorInfo)}. 51 */ onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo, ActivityInterceptorInfo info)52 public void onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo, 53 ActivityInterceptorInfo info) { 54 } 55 56 /** 57 * The unique id of each interceptor which determines the order it will execute in. 58 */ 59 @IntDef(suffix = { "_ORDERED_ID" }, value = { 60 FIRST_ORDERED_ID, 61 PERMISSION_POLICY_ORDERED_ID, 62 VIRTUAL_DEVICE_SERVICE_ORDERED_ID, 63 DREAM_MANAGER_ORDERED_ID, 64 LAST_ORDERED_ID // Update this when adding new ids 65 }) 66 @Retention(RetentionPolicy.SOURCE) 67 public @interface OrderedId {} 68 69 /** 70 * The first id, used by the framework to determine the valid range of ids. 71 */ 72 static final int FIRST_ORDERED_ID = 0; 73 74 /** 75 * The identifier for {@link com.android.server.policy.PermissionPolicyService} interceptor 76 */ 77 public static final int PERMISSION_POLICY_ORDERED_ID = 1; 78 79 /** 80 * The identifier for {@link com.android.server.companion.virtual.VirtualDeviceManagerService} 81 * interceptor. 82 */ 83 public static final int VIRTUAL_DEVICE_SERVICE_ORDERED_ID = 3; 84 85 /** 86 * The identifier for {@link com.android.server.dreams.DreamManagerService} interceptor. 87 */ 88 public static final int DREAM_MANAGER_ORDERED_ID = 4; 89 90 /** 91 * The final id, used by the framework to determine the valid range of ids. Update this when 92 * adding new ids. 93 */ 94 static final int LAST_ORDERED_ID = DREAM_MANAGER_ORDERED_ID; 95 96 /** 97 * Data class for storing the various arguments needed for activity interception. 98 */ 99 public static final class ActivityInterceptorInfo { 100 public final int realCallingUid; 101 public final int realCallingPid; 102 public final int userId; 103 public final String callingPackage; 104 public final String callingFeatureId; 105 public final Intent intent; 106 public final ResolveInfo rInfo; 107 public final ActivityInfo aInfo; 108 public final String resolvedType; 109 public final int callingPid; 110 public final int callingUid; 111 public final ActivityOptions checkedOptions; 112 public final @Nullable Runnable clearOptionsAnimation; 113 ActivityInterceptorInfo(int realCallingUid, int realCallingPid, int userId, String callingPackage, String callingFeatureId, Intent intent, ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType, int callingPid, int callingUid, ActivityOptions checkedOptions, @Nullable Runnable clearOptionsAnimation)114 public ActivityInterceptorInfo(int realCallingUid, int realCallingPid, int userId, 115 String callingPackage, String callingFeatureId, Intent intent, 116 ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType, int callingPid, 117 int callingUid, ActivityOptions checkedOptions, 118 @Nullable Runnable clearOptionsAnimation) { 119 this.realCallingUid = realCallingUid; 120 this.realCallingPid = realCallingPid; 121 this.userId = userId; 122 this.callingPackage = callingPackage; 123 this.callingFeatureId = callingFeatureId; 124 this.intent = intent; 125 this.rInfo = rInfo; 126 this.aInfo = aInfo; 127 this.resolvedType = resolvedType; 128 this.callingPid = callingPid; 129 this.callingUid = callingUid; 130 this.checkedOptions = checkedOptions; 131 this.clearOptionsAnimation = clearOptionsAnimation; 132 } 133 } 134 135 /** 136 * Data class for storing the intercept result. 137 */ 138 public static final class ActivityInterceptResult { 139 @NonNull public final Intent intent; 140 @NonNull public final ActivityOptions activityOptions; 141 ActivityInterceptResult( @onNull Intent intent, @NonNull ActivityOptions activityOptions)142 public ActivityInterceptResult( 143 @NonNull Intent intent, 144 @NonNull ActivityOptions activityOptions) { 145 this.intent = intent; 146 this.activityOptions = activityOptions; 147 } 148 } 149 } 150