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.annotation.SystemApi; 23 import android.app.ActivityOptions; 24 import android.app.TaskInfo; 25 import android.content.Intent; 26 import android.content.pm.ActivityInfo; 27 import android.content.pm.ResolveInfo; 28 29 import java.lang.annotation.Retention; 30 import java.lang.annotation.RetentionPolicy; 31 32 /** 33 * Callback to intercept activity starts and possibly block/redirect them. The callback methods will 34 * be called with the WindowManagerGlobalLock held. 35 * @hide 36 */ 37 @SystemApi(client = SystemApi.Client.SYSTEM_SERVER) 38 public interface ActivityInterceptorCallback { 39 /** 40 * Called to allow intercepting activity launching based on the provided launch parameters and 41 * intent resolution. 42 * 43 * <p>If the interceptor decides to change the {@link Intent} or return different {@link 44 * ActivityOptions}, it should return a non-{@code null} {@link ActivityInterceptResult} which 45 * may redirect to another activity or use new {@link ActivityOptions}. Otherwise, the 46 * interceptor should return {@code null} to indicate that passed {@link Intent} should not be 47 * changed. 48 * 49 * @param info the information about the {@link Intent} that is being intercepted to launch an 50 * {@link android.app.Activity}. 51 * @return {@code null} if the interceptor decides not to change the existing intent, or a non- 52 * {@code null} result which replaces the existing intent and activity options. 53 */ 54 @Nullable onInterceptActivityLaunch(@onNull ActivityInterceptorInfo info)55 ActivityInterceptResult onInterceptActivityLaunch(@NonNull ActivityInterceptorInfo info); 56 57 /** 58 * Called when an activity is successfully launched. 59 * 60 * <p>The intent included in the ActivityInterceptorInfo may have changed from the one sent in 61 * {@link #onInterceptActivityLaunch(ActivityInterceptorInfo)}, due to the changes might applied 62 * during internception. 63 * 64 * <p>There is no callback in case that the {@link android.app.Activity} is failed to launch, 65 * and this is not necessary to be added for the known use-cases. 66 * 67 * @param taskInfo the information about the @{@link Task} holds the launched 68 * {@link android.app.Activity}. 69 * @param activityInfo the information about the launched {@link android.app.Activity}. 70 * @param info the information about the {@link Intent} after calling {@link 71 * #onInterceptActivityLaunch(ActivityInterceptorInfo)}. 72 */ onActivityLaunched(@onNull TaskInfo taskInfo, @NonNull ActivityInfo activityInfo, @NonNull ActivityInterceptorInfo info)73 default void onActivityLaunched(@NonNull TaskInfo taskInfo, @NonNull ActivityInfo activityInfo, 74 @NonNull ActivityInterceptorInfo info) {} 75 76 /** 77 * The unique id of each interceptor registered by a system service which determines the order 78 * it will execute in. 79 * @hide 80 */ 81 @IntDef(suffix = { "_ORDERED_ID" }, value = { 82 // Order Ids for system services 83 SYSTEM_FIRST_ORDERED_ID, 84 PERMISSION_POLICY_ORDERED_ID, 85 VIRTUAL_DEVICE_SERVICE_ORDERED_ID, 86 DREAM_MANAGER_ORDERED_ID, 87 PRODUCT_ORDERED_ID, 88 SYSTEM_LAST_ORDERED_ID, // Update this when adding new ids 89 // Order Ids for mainline module services 90 MAINLINE_FIRST_ORDERED_ID, 91 MAINLINE_SDK_SANDBOX_ORDER_ID, 92 MAINLINE_LAST_ORDERED_ID // Update this when adding new mainline module ids 93 }) 94 @Retention(RetentionPolicy.SOURCE) 95 @interface OrderedId {} 96 97 /** 98 * The first id, used by the framework to determine the valid range of ids. 99 * @hide 100 */ 101 int SYSTEM_FIRST_ORDERED_ID = 0; 102 103 /** 104 * The identifier for {@link com.android.server.policy.PermissionPolicyService} interceptor 105 * @hide 106 */ 107 int PERMISSION_POLICY_ORDERED_ID = 1; 108 109 /** 110 * The identifier for {@link com.android.server.companion.virtual.VirtualDeviceManagerService} 111 * interceptor. 112 * @hide 113 */ 114 int VIRTUAL_DEVICE_SERVICE_ORDERED_ID = 3; 115 116 /** 117 * The identifier for {@link com.android.server.dreams.DreamManagerService} interceptor. 118 * @hide 119 */ 120 int DREAM_MANAGER_ORDERED_ID = 4; 121 122 /** 123 * The identifier for an interceptor which is specific to the type of android product like 124 * automotive, wear, TV etc. 125 * @hide 126 */ 127 int PRODUCT_ORDERED_ID = 5; 128 129 /** 130 * The final id, used by the framework to determine the valid range of ids. Update this when 131 * adding new ids. 132 * @hide 133 */ 134 int SYSTEM_LAST_ORDERED_ID = PRODUCT_ORDERED_ID; 135 136 /** 137 * The first mainline module id, used by the framework to determine the valid range of ids 138 * could be used by mainline modules. 139 * @hide 140 */ 141 int MAINLINE_FIRST_ORDERED_ID = 1000; 142 143 /** 144 * The identifier for {@link com.android.server.sdksandbox.SdkSandboxManagerService.Lifecycle} 145 * interceptor. 146 */ 147 int MAINLINE_SDK_SANDBOX_ORDER_ID = 1001; 148 149 /** 150 * The final mainline module id, used by the framework to determine the valid range of ids 151 * could be used by mainline modules. Update this when adding new ids for mainline modules. 152 * @hide 153 */ 154 int MAINLINE_LAST_ORDERED_ID = MAINLINE_SDK_SANDBOX_ORDER_ID; 155 156 /** 157 * Returns {@code true} if the id is in the range of valid system services including mainline 158 * module services. 159 * @hide 160 */ isValidOrderId(int id)161 static boolean isValidOrderId(int id) { 162 return isValidMainlineOrderId(id) 163 || (id >= SYSTEM_FIRST_ORDERED_ID && id <= SYSTEM_LAST_ORDERED_ID); 164 } 165 166 /** 167 * Returns {@code true} if the id is in the range of valid mainline module services. 168 * @hide 169 */ isValidMainlineOrderId(int id)170 static boolean isValidMainlineOrderId(int id) { 171 return id >= MAINLINE_FIRST_ORDERED_ID && id <= MAINLINE_LAST_ORDERED_ID; 172 } 173 174 /** 175 * Data class for storing the various arguments needed for activity interception. 176 * @hide 177 */ 178 @SystemApi(client = SystemApi.Client.SYSTEM_SERVER) 179 final class ActivityInterceptorInfo { 180 private final int mCallingUid; 181 private final int mCallingPid; 182 private final int mRealCallingUid; 183 private final int mRealCallingPid; 184 private final int mUserId; 185 private final Intent mIntent; 186 @NonNull 187 private final ResolveInfo mResolveInfo; 188 @NonNull 189 private final ActivityInfo mActivityInfo; 190 @Nullable 191 private final String mResolvedType; 192 @Nullable 193 private final String mCallingPackage; 194 @Nullable 195 private final String mCallingFeatureId; 196 @Nullable 197 private final ActivityOptions mCheckedOptions; 198 @Nullable 199 private final Runnable mClearOptionsAnimation; 200 201 /** 202 * @hide 203 */ ActivityInterceptorInfo(Builder builder)204 public ActivityInterceptorInfo(Builder builder) { 205 this.mCallingUid = builder.mCallingUid; 206 this.mCallingPid = builder.mCallingPid; 207 this.mRealCallingUid = builder.mRealCallingUid; 208 this.mRealCallingPid = builder.mRealCallingPid; 209 this.mUserId = builder.mUserId; 210 this.mIntent = builder.mIntent; 211 this.mResolveInfo = builder.mResolveInfo; 212 this.mActivityInfo = builder.mActivityInfo; 213 this.mResolvedType = builder.mResolvedType; 214 this.mCallingPackage = builder.mCallingPackage; 215 this.mCallingFeatureId = builder.mCallingFeatureId; 216 this.mCheckedOptions = builder.mCheckedOptions; 217 this.mClearOptionsAnimation = builder.mClearOptionsAnimation; 218 } 219 220 /** 221 * Builder class to build instances of {@link ActivityInterceptorInfo}. 222 */ 223 public static final class Builder { 224 private final int mCallingUid; 225 private final int mCallingPid; 226 private final int mRealCallingUid; 227 private final int mRealCallingPid; 228 private final int mUserId; 229 private final Intent mIntent; 230 @NonNull 231 private final ResolveInfo mResolveInfo; 232 @NonNull 233 private final ActivityInfo mActivityInfo; 234 @Nullable 235 private String mResolvedType; 236 @Nullable 237 private String mCallingPackage = null; 238 @Nullable 239 private String mCallingFeatureId = null; 240 @Nullable 241 private ActivityOptions mCheckedOptions = null; 242 @Nullable 243 private Runnable mClearOptionsAnimation = null; 244 245 /** 246 * Constructor of {@link ActivityInterceptorInfo.Builder}. 247 */ Builder(int callingUid, int callingPid, int realCallingUid, int realCallingPid, int userId, @NonNull Intent intent, @NonNull ResolveInfo rInfo, @NonNull ActivityInfo aInfo)248 public Builder(int callingUid, int callingPid, int realCallingUid, 249 int realCallingPid, int userId, @NonNull Intent intent, 250 @NonNull ResolveInfo rInfo, @NonNull ActivityInfo aInfo) { 251 this.mCallingUid = callingUid; 252 this.mCallingPid = callingPid; 253 this.mRealCallingUid = realCallingUid; 254 this.mRealCallingPid = realCallingPid; 255 this.mUserId = userId; 256 this.mIntent = intent; 257 this.mResolveInfo = rInfo; 258 this.mActivityInfo = aInfo; 259 } 260 261 /** 262 * Returns a new instance of {@link ActivityInterceptorInfo} based on the {@link 263 * Builder} fields. 264 * 265 * @return a new instance of {@link ActivityInterceptorInfo}. 266 */ 267 @NonNull build()268 public ActivityInterceptorInfo build() { 269 return new ActivityInterceptorInfo(this); 270 } 271 272 /** 273 * Sets the value for the resolved type. 274 * @param resolvedType the resolved type. 275 */ 276 @NonNull setResolvedType(@ullable String resolvedType)277 public Builder setResolvedType(@Nullable String resolvedType) { 278 mResolvedType = resolvedType; 279 return this; 280 } 281 282 /** 283 * Sets the value for the calling package. 284 * @param callingPackage the calling package. 285 */ 286 @NonNull setCallingPackage(@ullable String callingPackage)287 public Builder setCallingPackage(@Nullable String callingPackage) { 288 mCallingPackage = callingPackage; 289 return this; 290 } 291 292 /** 293 * Sets the value for the calling feature id. 294 * @param callingFeatureId the calling feature id. 295 */ 296 @NonNull setCallingFeatureId(@ullable String callingFeatureId)297 public Builder setCallingFeatureId(@Nullable String callingFeatureId) { 298 mCallingFeatureId = callingFeatureId; 299 return this; 300 } 301 302 /** 303 * Sets the value for the {@link ActivityOptions}. 304 * @param checkedOptions the {@link ActivityOptions}. 305 */ 306 @NonNull setCheckedOptions(@ullable ActivityOptions checkedOptions)307 public Builder setCheckedOptions(@Nullable ActivityOptions checkedOptions) { 308 mCheckedOptions = checkedOptions; 309 return this; 310 } 311 312 /** 313 * Sets the value for the {@link Runnable} object to clear options Animation. 314 * @param clearOptionsAnimationRunnable the calling package. 315 */ 316 @NonNull setClearOptionsAnimationRunnable(@ullable Runnable clearOptionsAnimationRunnable)317 public Builder setClearOptionsAnimationRunnable(@Nullable 318 Runnable clearOptionsAnimationRunnable) { 319 mClearOptionsAnimation = clearOptionsAnimationRunnable; 320 return this; 321 } 322 } 323 324 /** Returns the calling uid. */ getCallingUid()325 public int getCallingUid() { 326 return mCallingUid; 327 } 328 329 /** Returns the calling pid. */ getCallingPid()330 public int getCallingPid() { 331 return mCallingPid; 332 } 333 334 /** Returns the real calling uid. */ getRealCallingUid()335 public int getRealCallingUid() { 336 return mRealCallingUid; 337 } 338 339 /** Returns the real calling pid. */ getRealCallingPid()340 public int getRealCallingPid() { 341 return mRealCallingPid; 342 } 343 344 /** Returns the user id. */ getUserId()345 public int getUserId() { 346 return mUserId; 347 } 348 349 /** Returns the {@link Intent}. */ 350 @SuppressWarnings("IntentBuilderName") 351 @NonNull getIntent()352 public Intent getIntent() { 353 return mIntent; 354 } 355 356 /** Returns the {@link ResolveInfo}. */ 357 @NonNull getResolveInfo()358 public ResolveInfo getResolveInfo() { 359 return mResolveInfo; 360 } 361 362 /** Returns the {@link ActivityInfo}. */ 363 @NonNull getActivityInfo()364 public ActivityInfo getActivityInfo() { 365 return mActivityInfo; 366 } 367 368 /** Returns the real resolved type. */ 369 @Nullable getResolvedType()370 public String getResolvedType() { 371 return mResolvedType; 372 } 373 374 /** Returns the calling package. */ 375 @Nullable getCallingPackage()376 public String getCallingPackage() { 377 return mCallingPackage; 378 } 379 380 /** Returns the calling feature id. */ 381 @Nullable getCallingFeatureId()382 public String getCallingFeatureId() { 383 return mCallingFeatureId; 384 } 385 386 /** Returns the {@link ActivityOptions}. */ 387 @Nullable getCheckedOptions()388 public ActivityOptions getCheckedOptions() { 389 return mCheckedOptions; 390 } 391 392 /** 393 * Returns the {@link Runnable} object to clear options Animation. Note that the runnable 394 * should not be executed inside a lock because the implementation of runnable holds window 395 * manager's lock. 396 */ 397 @Nullable getClearOptionsAnimationRunnable()398 public Runnable getClearOptionsAnimationRunnable() { 399 return mClearOptionsAnimation; 400 } 401 } 402 403 /** 404 * Data class for storing the intercept result. 405 * @hide 406 */ 407 @SystemApi(client = SystemApi.Client.SYSTEM_SERVER) 408 final class ActivityInterceptResult { 409 @NonNull 410 private final Intent mIntent; 411 412 @NonNull 413 private final ActivityOptions mActivityOptions; 414 415 private final boolean mActivityResolved; 416 417 /** 418 * This constructor should only be used if both {@link ActivityInfo} and {@link ResolveInfo} 419 * did not get resolved while interception. 420 * @hide 421 */ ActivityInterceptResult(@onNull Intent intent, @NonNull ActivityOptions activityOptions)422 public ActivityInterceptResult(@NonNull Intent intent, 423 @NonNull ActivityOptions activityOptions) { 424 this(intent, activityOptions, false /* activityResolved */); 425 } 426 427 /** 428 * Generates the result of intercepting launching the {@link android.app.Activity} 429 * 430 * <p>Interceptor should return non-{@code null} result when {@link 431 * #onInterceptActivityLaunch(ActivityInterceptorInfo)} gets called as an indicator that 432 * interception has happened. 433 * 434 * @param intent is the modified {@link Intent} after interception. 435 * @param activityOptions holds the {@link ActivityOptions} after interception. 436 * @param activityResolved should be {@code true} only if {@link ActivityInfo} or {@link 437 * ResolveInfo} gets resolved, otherwise should be {@code false}. 438 */ ActivityInterceptResult(@onNull Intent intent, @NonNull ActivityOptions activityOptions, boolean activityResolved)439 public ActivityInterceptResult(@NonNull Intent intent, 440 @NonNull ActivityOptions activityOptions, boolean activityResolved) { 441 this.mIntent = intent; 442 this.mActivityOptions = activityOptions; 443 this.mActivityResolved = activityResolved; 444 } 445 446 /** Returns the intercepted {@link Intent} */ 447 @SuppressWarnings("IntentBuilderName") 448 @NonNull getIntent()449 public Intent getIntent() { 450 return mIntent; 451 } 452 453 /** Returns the intercepted {@link ActivityOptions} */ 454 @NonNull getActivityOptions()455 public ActivityOptions getActivityOptions() { 456 return mActivityOptions; 457 } 458 459 /** 460 * Returns if the {@link ActivityInfo} or {@link ResolveInfo} gets resolved. 461 */ isActivityResolved()462 public boolean isActivityResolved() { 463 return mActivityResolved; 464 } 465 } 466 } 467