1 /* 2 * Copyright (C) 2023 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 android.app; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.content.ComponentName; 23 24 import java.lang.annotation.Retention; 25 import java.lang.annotation.RetentionPolicy; 26 27 /** 28 * A service module such as MediaSessionService, VOIP, Camera, Microphone, Location can ask 29 * ActivityManagerService to start a foreground service delegate on behalf of the actual app, 30 * by which the client app's process state can be promoted to FOREGROUND_SERVICE process state which 31 * is higher than the app's actual process state if the app is in the background. This can help to 32 * keep the app in the memory and extra run-time. 33 * The app does not need to define an actual service component nor add it into manifest file. 34 * 35 * @hide 36 */ 37 public class ForegroundServiceDelegationOptions { 38 39 public static final int DELEGATION_SERVICE_DEFAULT = 0; 40 public static final int DELEGATION_SERVICE_DATA_SYNC = 1; 41 public static final int DELEGATION_SERVICE_MEDIA_PLAYBACK = 2; 42 public static final int DELEGATION_SERVICE_PHONE_CALL = 3; 43 public static final int DELEGATION_SERVICE_LOCATION = 4; 44 public static final int DELEGATION_SERVICE_CONNECTED_DEVICE = 5; 45 public static final int DELEGATION_SERVICE_MEDIA_PROJECTION = 6; 46 public static final int DELEGATION_SERVICE_CAMERA = 7; 47 public static final int DELEGATION_SERVICE_MICROPHONE = 8; 48 public static final int DELEGATION_SERVICE_HEALTH = 9; 49 public static final int DELEGATION_SERVICE_REMOTE_MESSAGING = 10; 50 public static final int DELEGATION_SERVICE_SYSTEM_EXEMPTED = 11; 51 public static final int DELEGATION_SERVICE_SPECIAL_USE = 12; 52 53 @IntDef(flag = false, prefix = { "DELEGATION_SERVICE_" }, value = { 54 DELEGATION_SERVICE_DEFAULT, 55 DELEGATION_SERVICE_DATA_SYNC, 56 DELEGATION_SERVICE_MEDIA_PLAYBACK, 57 DELEGATION_SERVICE_PHONE_CALL, 58 DELEGATION_SERVICE_LOCATION, 59 DELEGATION_SERVICE_CONNECTED_DEVICE, 60 DELEGATION_SERVICE_MEDIA_PROJECTION, 61 DELEGATION_SERVICE_CAMERA, 62 DELEGATION_SERVICE_MICROPHONE, 63 DELEGATION_SERVICE_HEALTH, 64 DELEGATION_SERVICE_REMOTE_MESSAGING, 65 DELEGATION_SERVICE_SYSTEM_EXEMPTED, 66 DELEGATION_SERVICE_SPECIAL_USE, 67 }) 68 @Retention(RetentionPolicy.SOURCE) 69 public @interface DelegationService {} 70 71 // The actual app's PID 72 public final int mClientPid; 73 // The actual app's UID 74 public final int mClientUid; 75 // The actual app's package name 76 @NonNull 77 public final String mClientPackageName; 78 // The actual app's app thread 79 @Nullable 80 public final IApplicationThread mClientAppThread; 81 public final boolean mSticky; // Is it a sticky service 82 83 // The delegation service's instance name which is to identify the delegate. 84 @NonNull 85 public String mClientInstanceName; 86 // The foreground service types it consists of. 87 public final int mForegroundServiceTypes; 88 /** 89 * The service's name such as MediaSessionService, VOIP, Camera, Microphone, Location. This is 90 * the internal module's name which actually starts the FGS delegate on behalf of the client 91 * app. 92 */ 93 public final @DelegationService int mDelegationService; 94 95 /** 96 * The optional notification Id of the foreground service delegation. 97 */ 98 public final int mClientNotificationId; 99 100 /** 101 * The optional notification of the foreground service delegation. 102 */ 103 public final @Nullable Notification mClientNotification; 104 ForegroundServiceDelegationOptions(int clientPid, int clientUid, @NonNull String clientPackageName, @NonNull IApplicationThread clientAppThread, boolean isSticky, @NonNull String clientInstanceName, int foregroundServiceTypes, @DelegationService int delegationService)105 public ForegroundServiceDelegationOptions(int clientPid, 106 int clientUid, 107 @NonNull String clientPackageName, 108 @NonNull IApplicationThread clientAppThread, 109 boolean isSticky, 110 @NonNull String clientInstanceName, 111 int foregroundServiceTypes, 112 @DelegationService int delegationService) { 113 this(clientPid, clientUid, clientPackageName, clientAppThread, isSticky, 114 clientInstanceName, foregroundServiceTypes, delegationService, 115 0 /* notificationId */, null /* notification */); 116 } 117 ForegroundServiceDelegationOptions(int clientPid, int clientUid, @NonNull String clientPackageName, @NonNull IApplicationThread clientAppThread, boolean isSticky, @NonNull String clientInstanceName, int foregroundServiceTypes, @DelegationService int delegationService, int clientNotificationId, @Nullable Notification clientNotification)118 public ForegroundServiceDelegationOptions(int clientPid, 119 int clientUid, 120 @NonNull String clientPackageName, 121 @NonNull IApplicationThread clientAppThread, 122 boolean isSticky, 123 @NonNull String clientInstanceName, 124 int foregroundServiceTypes, 125 @DelegationService int delegationService, 126 int clientNotificationId, 127 @Nullable Notification clientNotification) { 128 mClientPid = clientPid; 129 mClientUid = clientUid; 130 mClientPackageName = clientPackageName; 131 mClientAppThread = clientAppThread; 132 mSticky = isSticky; 133 mClientInstanceName = clientInstanceName; 134 mForegroundServiceTypes = foregroundServiceTypes; 135 mDelegationService = delegationService; 136 mClientNotificationId = clientNotificationId; 137 mClientNotification = clientNotification; 138 } 139 140 /** 141 * A service delegates a foreground service state to a clientUID using a instanceName. 142 * This delegation is uniquely identified by 143 * mDelegationService/mClientUid/mClientPid/mClientInstanceName 144 */ isSameDelegate(ForegroundServiceDelegationOptions that)145 public boolean isSameDelegate(ForegroundServiceDelegationOptions that) { 146 return this.mDelegationService == that.mDelegationService 147 && this.mClientUid == that.mClientUid 148 && this.mClientPid == that.mClientPid 149 && this.mClientInstanceName.equals(that.mClientInstanceName); 150 } 151 152 /** 153 * Construct a component name for this delegate. 154 */ getComponentName()155 public ComponentName getComponentName() { 156 return new ComponentName(mClientPackageName, serviceCodeToString(mDelegationService) 157 + ":" + mClientInstanceName); 158 } 159 160 /** 161 * Get string description of this delegate options. 162 */ getDescription()163 public String getDescription() { 164 StringBuilder sb = new StringBuilder(128); 165 sb.append("ForegroundServiceDelegate{") 166 .append("package:") 167 .append(mClientPackageName) 168 .append(",") 169 .append("service:") 170 .append(serviceCodeToString(mDelegationService)) 171 .append(",") 172 .append("uid:") 173 .append(mClientUid) 174 .append(",") 175 .append("pid:") 176 .append(mClientPid) 177 .append(",") 178 .append("instance:") 179 .append(mClientInstanceName) 180 .append("}"); 181 return sb.toString(); 182 } 183 184 /** 185 * Map the integer service code to string name. 186 * @param serviceCode 187 * @return 188 */ serviceCodeToString(@elegationService int serviceCode)189 public static String serviceCodeToString(@DelegationService int serviceCode) { 190 switch (serviceCode) { 191 case DELEGATION_SERVICE_DEFAULT: 192 return "DEFAULT"; 193 case DELEGATION_SERVICE_DATA_SYNC: 194 return "DATA_SYNC"; 195 case DELEGATION_SERVICE_MEDIA_PLAYBACK: 196 return "MEDIA_PLAYBACK"; 197 case DELEGATION_SERVICE_PHONE_CALL: 198 return "PHONE_CALL"; 199 case DELEGATION_SERVICE_LOCATION: 200 return "LOCATION"; 201 case DELEGATION_SERVICE_CONNECTED_DEVICE: 202 return "CONNECTED_DEVICE"; 203 case DELEGATION_SERVICE_MEDIA_PROJECTION: 204 return "MEDIA_PROJECTION"; 205 case DELEGATION_SERVICE_CAMERA: 206 return "CAMERA"; 207 case DELEGATION_SERVICE_MICROPHONE: 208 return "MICROPHONE"; 209 case DELEGATION_SERVICE_HEALTH: 210 return "HEALTH"; 211 case DELEGATION_SERVICE_REMOTE_MESSAGING: 212 return "REMOTE_MESSAGING"; 213 case DELEGATION_SERVICE_SYSTEM_EXEMPTED: 214 return "SYSTEM_EXEMPTED"; 215 case DELEGATION_SERVICE_SPECIAL_USE: 216 return "SPECIAL_USE"; 217 default: 218 return "(unknown:" + serviceCode + ")"; 219 } 220 } 221 222 /** 223 * The helper class to build the instance of {@link ForegroundServiceDelegate}. 224 * 225 * @hide 226 */ 227 public static class Builder { 228 int mClientPid; // The actual app PID 229 int mClientUid; // The actual app UID 230 String mClientPackageName; // The actual app's package name 231 int mClientNotificationId; // The actual app's notification id 232 Notification mClientNotification; // The actual app's notification 233 IApplicationThread mClientAppThread; // The actual app's app thread 234 boolean mSticky; // Is it a sticky service 235 String mClientInstanceName; // The delegation service instance name 236 int mForegroundServiceTypes; // The foreground service types it consists of 237 @DelegationService int mDelegationService; // The internal service's name, i.e. VOIP 238 239 /** 240 * Set the client app's PID. 241 */ setClientPid(int clientPid)242 public Builder setClientPid(int clientPid) { 243 mClientPid = clientPid; 244 return this; 245 } 246 247 /** 248 * Set the client app's UID. 249 */ setClientUid(int clientUid)250 public Builder setClientUid(int clientUid) { 251 mClientUid = clientUid; 252 return this; 253 } 254 255 /** 256 * Set the client app's package name. 257 */ setClientPackageName(@onNull String clientPackageName)258 public Builder setClientPackageName(@NonNull String clientPackageName) { 259 mClientPackageName = clientPackageName; 260 return this; 261 } 262 263 /** 264 * Set the notification from the client app. 265 */ setClientNotification(int clientNotificationId, @Nullable Notification clientNotification)266 public Builder setClientNotification(int clientNotificationId, 267 @Nullable Notification clientNotification) { 268 mClientNotificationId = clientNotificationId; 269 mClientNotification = clientNotification; 270 return this; 271 } 272 273 /** 274 * Set the client app's application thread. 275 */ setClientAppThread(@onNull IApplicationThread clientAppThread)276 public Builder setClientAppThread(@NonNull IApplicationThread clientAppThread) { 277 mClientAppThread = clientAppThread; 278 return this; 279 } 280 281 /** 282 * Set the client instance of this service. 283 */ setClientInstanceName(@onNull String clientInstanceName)284 public Builder setClientInstanceName(@NonNull String clientInstanceName) { 285 mClientInstanceName = clientInstanceName; 286 return this; 287 } 288 289 /** 290 * Set stickiness of this service. 291 */ setSticky(boolean isSticky)292 public Builder setSticky(boolean isSticky) { 293 mSticky = isSticky; 294 return this; 295 } 296 297 /** 298 * Set the foreground service type. 299 */ setForegroundServiceTypes(int foregroundServiceTypes)300 public Builder setForegroundServiceTypes(int foregroundServiceTypes) { 301 mForegroundServiceTypes = foregroundServiceTypes; 302 return this; 303 } 304 305 /** 306 * Set the delegation service type. 307 */ setDelegationService(@elegationService int delegationService)308 public Builder setDelegationService(@DelegationService int delegationService) { 309 mDelegationService = delegationService; 310 return this; 311 } 312 313 /** 314 * @return An instance of {@link ForegroundServiceDelegationOptions}. 315 */ build()316 public ForegroundServiceDelegationOptions build() { 317 return new ForegroundServiceDelegationOptions(mClientPid, 318 mClientUid, 319 mClientPackageName, 320 mClientAppThread, 321 mSticky, 322 mClientInstanceName, 323 mForegroundServiceTypes, 324 mDelegationService, 325 mClientNotificationId, 326 mClientNotification 327 ); 328 } 329 } 330 } 331