331 lines
12 KiB
Java
331 lines
12 KiB
Java
/*
|
|
* Copyright (C) 2023 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 android.app;
|
|
|
|
import android.annotation.IntDef;
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.content.ComponentName;
|
|
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
|
|
/**
|
|
* A service module such as MediaSessionService, VOIP, Camera, Microphone, Location can ask
|
|
* ActivityManagerService to start a foreground service delegate on behalf of the actual app,
|
|
* by which the client app's process state can be promoted to FOREGROUND_SERVICE process state which
|
|
* is higher than the app's actual process state if the app is in the background. This can help to
|
|
* keep the app in the memory and extra run-time.
|
|
* The app does not need to define an actual service component nor add it into manifest file.
|
|
*
|
|
* @hide
|
|
*/
|
|
public class ForegroundServiceDelegationOptions {
|
|
|
|
public static final int DELEGATION_SERVICE_DEFAULT = 0;
|
|
public static final int DELEGATION_SERVICE_DATA_SYNC = 1;
|
|
public static final int DELEGATION_SERVICE_MEDIA_PLAYBACK = 2;
|
|
public static final int DELEGATION_SERVICE_PHONE_CALL = 3;
|
|
public static final int DELEGATION_SERVICE_LOCATION = 4;
|
|
public static final int DELEGATION_SERVICE_CONNECTED_DEVICE = 5;
|
|
public static final int DELEGATION_SERVICE_MEDIA_PROJECTION = 6;
|
|
public static final int DELEGATION_SERVICE_CAMERA = 7;
|
|
public static final int DELEGATION_SERVICE_MICROPHONE = 8;
|
|
public static final int DELEGATION_SERVICE_HEALTH = 9;
|
|
public static final int DELEGATION_SERVICE_REMOTE_MESSAGING = 10;
|
|
public static final int DELEGATION_SERVICE_SYSTEM_EXEMPTED = 11;
|
|
public static final int DELEGATION_SERVICE_SPECIAL_USE = 12;
|
|
|
|
@IntDef(flag = false, prefix = { "DELEGATION_SERVICE_" }, value = {
|
|
DELEGATION_SERVICE_DEFAULT,
|
|
DELEGATION_SERVICE_DATA_SYNC,
|
|
DELEGATION_SERVICE_MEDIA_PLAYBACK,
|
|
DELEGATION_SERVICE_PHONE_CALL,
|
|
DELEGATION_SERVICE_LOCATION,
|
|
DELEGATION_SERVICE_CONNECTED_DEVICE,
|
|
DELEGATION_SERVICE_MEDIA_PROJECTION,
|
|
DELEGATION_SERVICE_CAMERA,
|
|
DELEGATION_SERVICE_MICROPHONE,
|
|
DELEGATION_SERVICE_HEALTH,
|
|
DELEGATION_SERVICE_REMOTE_MESSAGING,
|
|
DELEGATION_SERVICE_SYSTEM_EXEMPTED,
|
|
DELEGATION_SERVICE_SPECIAL_USE,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface DelegationService {}
|
|
|
|
// The actual app's PID
|
|
public final int mClientPid;
|
|
// The actual app's UID
|
|
public final int mClientUid;
|
|
// The actual app's package name
|
|
@NonNull
|
|
public final String mClientPackageName;
|
|
// The actual app's app thread
|
|
@Nullable
|
|
public final IApplicationThread mClientAppThread;
|
|
public final boolean mSticky; // Is it a sticky service
|
|
|
|
// The delegation service's instance name which is to identify the delegate.
|
|
@NonNull
|
|
public String mClientInstanceName;
|
|
// The foreground service types it consists of.
|
|
public final int mForegroundServiceTypes;
|
|
/**
|
|
* The service's name such as MediaSessionService, VOIP, Camera, Microphone, Location. This is
|
|
* the internal module's name which actually starts the FGS delegate on behalf of the client
|
|
* app.
|
|
*/
|
|
public final @DelegationService int mDelegationService;
|
|
|
|
/**
|
|
* The optional notification Id of the foreground service delegation.
|
|
*/
|
|
public final int mClientNotificationId;
|
|
|
|
/**
|
|
* The optional notification of the foreground service delegation.
|
|
*/
|
|
public final @Nullable Notification mClientNotification;
|
|
|
|
public ForegroundServiceDelegationOptions(int clientPid,
|
|
int clientUid,
|
|
@NonNull String clientPackageName,
|
|
@NonNull IApplicationThread clientAppThread,
|
|
boolean isSticky,
|
|
@NonNull String clientInstanceName,
|
|
int foregroundServiceTypes,
|
|
@DelegationService int delegationService) {
|
|
this(clientPid, clientUid, clientPackageName, clientAppThread, isSticky,
|
|
clientInstanceName, foregroundServiceTypes, delegationService,
|
|
0 /* notificationId */, null /* notification */);
|
|
}
|
|
|
|
public 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) {
|
|
mClientPid = clientPid;
|
|
mClientUid = clientUid;
|
|
mClientPackageName = clientPackageName;
|
|
mClientAppThread = clientAppThread;
|
|
mSticky = isSticky;
|
|
mClientInstanceName = clientInstanceName;
|
|
mForegroundServiceTypes = foregroundServiceTypes;
|
|
mDelegationService = delegationService;
|
|
mClientNotificationId = clientNotificationId;
|
|
mClientNotification = clientNotification;
|
|
}
|
|
|
|
/**
|
|
* A service delegates a foreground service state to a clientUID using a instanceName.
|
|
* This delegation is uniquely identified by
|
|
* mDelegationService/mClientUid/mClientPid/mClientInstanceName
|
|
*/
|
|
public boolean isSameDelegate(ForegroundServiceDelegationOptions that) {
|
|
return this.mDelegationService == that.mDelegationService
|
|
&& this.mClientUid == that.mClientUid
|
|
&& this.mClientPid == that.mClientPid
|
|
&& this.mClientInstanceName.equals(that.mClientInstanceName);
|
|
}
|
|
|
|
/**
|
|
* Construct a component name for this delegate.
|
|
*/
|
|
public ComponentName getComponentName() {
|
|
return new ComponentName(mClientPackageName, serviceCodeToString(mDelegationService)
|
|
+ ":" + mClientInstanceName);
|
|
}
|
|
|
|
/**
|
|
* Get string description of this delegate options.
|
|
*/
|
|
public String getDescription() {
|
|
StringBuilder sb = new StringBuilder(128);
|
|
sb.append("ForegroundServiceDelegate{")
|
|
.append("package:")
|
|
.append(mClientPackageName)
|
|
.append(",")
|
|
.append("service:")
|
|
.append(serviceCodeToString(mDelegationService))
|
|
.append(",")
|
|
.append("uid:")
|
|
.append(mClientUid)
|
|
.append(",")
|
|
.append("pid:")
|
|
.append(mClientPid)
|
|
.append(",")
|
|
.append("instance:")
|
|
.append(mClientInstanceName)
|
|
.append("}");
|
|
return sb.toString();
|
|
}
|
|
|
|
/**
|
|
* Map the integer service code to string name.
|
|
* @param serviceCode
|
|
* @return
|
|
*/
|
|
public static String serviceCodeToString(@DelegationService int serviceCode) {
|
|
switch (serviceCode) {
|
|
case DELEGATION_SERVICE_DEFAULT:
|
|
return "DEFAULT";
|
|
case DELEGATION_SERVICE_DATA_SYNC:
|
|
return "DATA_SYNC";
|
|
case DELEGATION_SERVICE_MEDIA_PLAYBACK:
|
|
return "MEDIA_PLAYBACK";
|
|
case DELEGATION_SERVICE_PHONE_CALL:
|
|
return "PHONE_CALL";
|
|
case DELEGATION_SERVICE_LOCATION:
|
|
return "LOCATION";
|
|
case DELEGATION_SERVICE_CONNECTED_DEVICE:
|
|
return "CONNECTED_DEVICE";
|
|
case DELEGATION_SERVICE_MEDIA_PROJECTION:
|
|
return "MEDIA_PROJECTION";
|
|
case DELEGATION_SERVICE_CAMERA:
|
|
return "CAMERA";
|
|
case DELEGATION_SERVICE_MICROPHONE:
|
|
return "MICROPHONE";
|
|
case DELEGATION_SERVICE_HEALTH:
|
|
return "HEALTH";
|
|
case DELEGATION_SERVICE_REMOTE_MESSAGING:
|
|
return "REMOTE_MESSAGING";
|
|
case DELEGATION_SERVICE_SYSTEM_EXEMPTED:
|
|
return "SYSTEM_EXEMPTED";
|
|
case DELEGATION_SERVICE_SPECIAL_USE:
|
|
return "SPECIAL_USE";
|
|
default:
|
|
return "(unknown:" + serviceCode + ")";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The helper class to build the instance of {@link ForegroundServiceDelegate}.
|
|
*
|
|
* @hide
|
|
*/
|
|
public static class Builder {
|
|
int mClientPid; // The actual app PID
|
|
int mClientUid; // The actual app UID
|
|
String mClientPackageName; // The actual app's package name
|
|
int mClientNotificationId; // The actual app's notification id
|
|
Notification mClientNotification; // The actual app's notification
|
|
IApplicationThread mClientAppThread; // The actual app's app thread
|
|
boolean mSticky; // Is it a sticky service
|
|
String mClientInstanceName; // The delegation service instance name
|
|
int mForegroundServiceTypes; // The foreground service types it consists of
|
|
@DelegationService int mDelegationService; // The internal service's name, i.e. VOIP
|
|
|
|
/**
|
|
* Set the client app's PID.
|
|
*/
|
|
public Builder setClientPid(int clientPid) {
|
|
mClientPid = clientPid;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set the client app's UID.
|
|
*/
|
|
public Builder setClientUid(int clientUid) {
|
|
mClientUid = clientUid;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set the client app's package name.
|
|
*/
|
|
public Builder setClientPackageName(@NonNull String clientPackageName) {
|
|
mClientPackageName = clientPackageName;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set the notification from the client app.
|
|
*/
|
|
public Builder setClientNotification(int clientNotificationId,
|
|
@Nullable Notification clientNotification) {
|
|
mClientNotificationId = clientNotificationId;
|
|
mClientNotification = clientNotification;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set the client app's application thread.
|
|
*/
|
|
public Builder setClientAppThread(@NonNull IApplicationThread clientAppThread) {
|
|
mClientAppThread = clientAppThread;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set the client instance of this service.
|
|
*/
|
|
public Builder setClientInstanceName(@NonNull String clientInstanceName) {
|
|
mClientInstanceName = clientInstanceName;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set stickiness of this service.
|
|
*/
|
|
public Builder setSticky(boolean isSticky) {
|
|
mSticky = isSticky;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set the foreground service type.
|
|
*/
|
|
public Builder setForegroundServiceTypes(int foregroundServiceTypes) {
|
|
mForegroundServiceTypes = foregroundServiceTypes;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set the delegation service type.
|
|
*/
|
|
public Builder setDelegationService(@DelegationService int delegationService) {
|
|
mDelegationService = delegationService;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @return An instance of {@link ForegroundServiceDelegationOptions}.
|
|
*/
|
|
public ForegroundServiceDelegationOptions build() {
|
|
return new ForegroundServiceDelegationOptions(mClientPid,
|
|
mClientUid,
|
|
mClientPackageName,
|
|
mClientAppThread,
|
|
mSticky,
|
|
mClientInstanceName,
|
|
mForegroundServiceTypes,
|
|
mDelegationService,
|
|
mClientNotificationId,
|
|
mClientNotification
|
|
);
|
|
}
|
|
}
|
|
}
|