1 /* 2 * Copyright (C) 2022 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.NonNull; 20 import android.annotation.SystemApi; 21 import android.os.Binder; 22 import android.os.Process; 23 24 import com.android.internal.annotations.VisibleForTesting; 25 import com.android.server.LocalServices; 26 27 /** 28 * This class should be used by system services which are part of mainline modules to register 29 * {@link ActivityInterceptorCallback}. For other system services, this function should be used 30 * instead {@link ActivityTaskManagerInternal#registerActivityStartInterceptor( 31 * int, ActivityInterceptorCallback)}. 32 * @hide 33 */ 34 @SystemApi(client = SystemApi.Client.SYSTEM_SERVER) 35 public class ActivityInterceptorCallbackRegistry { 36 37 private static final ActivityInterceptorCallbackRegistry sInstance = 38 new ActivityInterceptorCallbackRegistry(); 39 ActivityInterceptorCallbackRegistry()40 private ActivityInterceptorCallbackRegistry() {} 41 42 /** Returns an already initialised singleton instance of this class. */ 43 @NonNull getInstance()44 public static ActivityInterceptorCallbackRegistry getInstance() { 45 return sInstance; 46 } 47 48 /** 49 * Registers a callback which can intercept activity launching flow. 50 * 51 * <p>Only system services which are part of mainline modules should call this function. 52 * 53 * <p>To avoid Activity launch delays, the callbacks must execute quickly and avoid acquiring 54 * other system process locks. 55 * 56 * @param mainlineOrderId has to be one of the following [{@link 57 * ActivityInterceptorCallback#MAINLINE_FIRST_ORDERED_ID}]. 58 * @param callback the {@link ActivityInterceptorCallback} to register. 59 * @throws IllegalArgumentException if duplicate ids are provided, the provided id is not the 60 * mainline module range or the provided {@code callback} is null. 61 */ 62 // ExecutorRegistration is suppressed as the callback is called synchronously in the system 63 // server. 64 @SuppressWarnings("ExecutorRegistration") registerActivityInterceptorCallback( @ctivityInterceptorCallback.OrderedId int mainlineOrderId, @NonNull ActivityInterceptorCallback callback)65 public void registerActivityInterceptorCallback( 66 @ActivityInterceptorCallback.OrderedId int mainlineOrderId, 67 @NonNull ActivityInterceptorCallback callback) { 68 if (getCallingUid() != Process.SYSTEM_UID) { 69 throw new SecurityException("Only system server can register " 70 + "ActivityInterceptorCallback"); 71 } 72 if (!ActivityInterceptorCallback.isValidMainlineOrderId(mainlineOrderId)) { 73 throw new IllegalArgumentException("id is not in the mainline modules range, please use" 74 + "ActivityTaskManagerInternal.registerActivityStartInterceptor(OrderedId, " 75 + "ActivityInterceptorCallback) instead."); 76 } 77 if (callback == null) { 78 throw new IllegalArgumentException("The passed ActivityInterceptorCallback can not be " 79 + "null"); 80 } 81 ActivityTaskManagerInternal activityTaskManagerInternal = 82 LocalServices.getService(ActivityTaskManagerInternal.class); 83 activityTaskManagerInternal.registerActivityStartInterceptor(mainlineOrderId, callback); 84 } 85 86 /** 87 * Unregisters an already registered {@link ActivityInterceptorCallback}. 88 * 89 * @param mainlineOrderId the order id of the {@link ActivityInterceptorCallback} should be 90 * unregistered, this callback should be registered before by calling 91 * {@link #registerActivityInterceptorCallback(int, 92 * ActivityInterceptorCallback)} using the same order id. 93 * @throws IllegalArgumentException if the provided id is not the mainline module range or is 94 * not registered 95 */ unregisterActivityInterceptorCallback( @ctivityInterceptorCallback.OrderedId int mainlineOrderId)96 public void unregisterActivityInterceptorCallback( 97 @ActivityInterceptorCallback.OrderedId int mainlineOrderId) { 98 if (getCallingUid() != Process.SYSTEM_UID) { 99 throw new SecurityException("Only system server can register " 100 + "ActivityInterceptorCallback"); 101 } 102 if (!ActivityInterceptorCallback.isValidMainlineOrderId(mainlineOrderId)) { 103 throw new IllegalArgumentException("id is not in the mainline modules range, please use" 104 + "ActivityTaskManagerInternal.unregisterActivityStartInterceptor(OrderedId) " 105 + "instead."); 106 } 107 ActivityTaskManagerInternal activityTaskManagerInternal = 108 LocalServices.getService(ActivityTaskManagerInternal.class); 109 activityTaskManagerInternal.unregisterActivityStartInterceptor(mainlineOrderId); 110 } 111 112 /** 113 * This hidden function is for unit tests as a way to behave like as if they are called from 114 * system server process uid by mocking it and returning {@link Process#SYSTEM_UID}. 115 * Do not make this {@code public} to apps as apps should not have a way to change the uid. 116 * @hide 117 */ 118 @VisibleForTesting getCallingUid()119 int getCallingUid() { 120 return Binder.getCallingUid(); 121 } 122 } 123