blob: 30811a175bac7a479d0b48d41549f66665a63d0e [file] [log] [blame]
/*
* Copyright (C) 2019 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 com.android.server.am;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ACTIVITY;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ADDED_APPLICATION;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_BACKUP;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_BROADCAST;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_CONTENT_PROVIDER;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_EMPTY;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_LINK_FAIL;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_NEXT_ACTIVITY;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_NEXT_TOP_ACTIVITY;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ON_HOLD;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_RESTART;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SERVICE;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SYSTEM;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_TOP_ACTIVITY;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_ALARM;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_JOB;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_PUSH_MESSAGE;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TYPE__UNKNOWN;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
/**
* This class describes various information required to start a process.
*
* The {@code mHostingType} field describes the reason why we started a process, and
* is only used for logging and stats.
*
* The {@code mHostingName} field describes the Component for which we are starting the
* process, and is only used for logging and stats.
*
* The {@code mHostingZygote} field describes from which Zygote the new process should be spawned.
*
* The {@code mTriggerType} field describes the trigger that started this processs. This could be
* an alarm or a push-message for a broadcast, for example. This is purely for logging and stats.
*
* {@code mDefiningPackageName} contains the packageName of the package that defines the
* component we want to start; this can be different from the packageName and uid in the
* ApplicationInfo that we're creating the process with, in case the service is a
* {@link android.content.Context#BIND_EXTERNAL_SERVICE} service. In that case, the packageName
* and uid in the ApplicationInfo will be set to those of the caller, not of the defining package.
*
* {@code mDefiningUid} contains the uid of the application that defines the component we want to
* start; this can be different from the packageName and uid in the ApplicationInfo that we're
* creating the process with, in case the service is a
* {@link android.content.Context#BIND_EXTERNAL_SERVICE} service. In that case, the packageName
* and uid in the ApplicationInfo will be set to those of the caller, not of the defining package.
*
* {@code mIsTopApp} will be passed to {@link android.os.Process#start}. So Zygote will initialize
* the process with high priority.
*
* {@code mAction} the broadcast's intent action if the process is started for a broadcast
* receiver.
*/
public final class HostingRecord {
private static final int REGULAR_ZYGOTE = 0;
private static final int WEBVIEW_ZYGOTE = 1;
private static final int APP_ZYGOTE = 2;
public static final String HOSTING_TYPE_ACTIVITY = "activity";
public static final String HOSTING_TYPE_ADDED_APPLICATION = "added application";
public static final String HOSTING_TYPE_BACKUP = "backup";
public static final String HOSTING_TYPE_BROADCAST = "broadcast";
public static final String HOSTING_TYPE_CONTENT_PROVIDER = "content provider";
public static final String HOSTING_TYPE_LINK_FAIL = "link fail";
public static final String HOSTING_TYPE_ON_HOLD = "on-hold";
public static final String HOSTING_TYPE_NEXT_ACTIVITY = "next-activity";
public static final String HOSTING_TYPE_NEXT_TOP_ACTIVITY = "next-top-activity";
public static final String HOSTING_TYPE_RESTART = "restart";
public static final String HOSTING_TYPE_SERVICE = "service";
public static final String HOSTING_TYPE_SYSTEM = "system";
public static final String HOSTING_TYPE_TOP_ACTIVITY = "top-activity";
public static final String HOSTING_TYPE_EMPTY = "";
public static final String TRIGGER_TYPE_UNKNOWN = "unknown";
public static final String TRIGGER_TYPE_ALARM = "alarm";
public static final String TRIGGER_TYPE_PUSH_MESSAGE = "push_message";
public static final String TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA = "push_message_over_quota";
public static final String TRIGGER_TYPE_JOB = "job";
@NonNull private final String mHostingType;
private final String mHostingName;
private final int mHostingZygote;
private final String mDefiningPackageName;
private final int mDefiningUid;
private final boolean mIsTopApp;
private final String mDefiningProcessName;
@Nullable private final String mAction;
@NonNull private final String mTriggerType;
public HostingRecord(@NonNull String hostingType) {
this(hostingType, null /* hostingName */, REGULAR_ZYGOTE, null /* definingPackageName */,
-1 /* mDefiningUid */, false /* isTopApp */, null /* definingProcessName */,
null /* action */, TRIGGER_TYPE_UNKNOWN);
}
public HostingRecord(@NonNull String hostingType, ComponentName hostingName) {
this(hostingType, hostingName, REGULAR_ZYGOTE);
}
public HostingRecord(@NonNull String hostingType, ComponentName hostingName,
@Nullable String action, @Nullable String triggerType) {
this(hostingType, hostingName.toShortString(), REGULAR_ZYGOTE,
null /* definingPackageName */, -1 /* mDefiningUid */, false /* isTopApp */,
null /* definingProcessName */, action, triggerType);
}
public HostingRecord(@NonNull String hostingType, ComponentName hostingName,
String definingPackageName, int definingUid, String definingProcessName,
String triggerType) {
this(hostingType, hostingName.toShortString(), REGULAR_ZYGOTE, definingPackageName,
definingUid, false /* isTopApp */, definingProcessName, null /* action */,
triggerType);
}
public HostingRecord(@NonNull String hostingType, ComponentName hostingName, boolean isTopApp) {
this(hostingType, hostingName.toShortString(), REGULAR_ZYGOTE,
null /* definingPackageName */, -1 /* mDefiningUid */, isTopApp /* isTopApp */,
null /* definingProcessName */, null /* action */, TRIGGER_TYPE_UNKNOWN);
}
public HostingRecord(@NonNull String hostingType, String hostingName) {
this(hostingType, hostingName, REGULAR_ZYGOTE);
}
private HostingRecord(@NonNull String hostingType, ComponentName hostingName,
int hostingZygote) {
this(hostingType, hostingName.toShortString(), hostingZygote);
}
private HostingRecord(@NonNull String hostingType, String hostingName, int hostingZygote) {
this(hostingType, hostingName, hostingZygote, null /* definingPackageName */,
-1 /* mDefiningUid */, false /* isTopApp */, null /* definingProcessName */,
null /* action */, TRIGGER_TYPE_UNKNOWN);
}
private HostingRecord(@NonNull String hostingType, String hostingName, int hostingZygote,
String definingPackageName, int definingUid, boolean isTopApp,
String definingProcessName, @Nullable String action, String triggerType) {
mHostingType = hostingType;
mHostingName = hostingName;
mHostingZygote = hostingZygote;
mDefiningPackageName = definingPackageName;
mDefiningUid = definingUid;
mIsTopApp = isTopApp;
mDefiningProcessName = definingProcessName;
mAction = action;
mTriggerType = triggerType;
}
public @NonNull String getType() {
return mHostingType;
}
public String getName() {
return mHostingName;
}
public boolean isTopApp() {
return mIsTopApp;
}
/**
* Returns the UID of the package defining the component we want to start. Only valid
* when {@link #usesAppZygote()} returns true.
*
* @return the UID of the hosting application
*/
public int getDefiningUid() {
return mDefiningUid;
}
/**
* Returns the packageName of the package defining the component we want to start. Only valid
* when {@link #usesAppZygote()} returns true.
*
* @return the packageName of the hosting application
*/
public String getDefiningPackageName() {
return mDefiningPackageName;
}
/**
* Returns the processName of the component we want to start as specified in the defining app's
* manifest.
*
* @return the processName of the process in the hosting application
*/
public String getDefiningProcessName() {
return mDefiningProcessName;
}
/**
* Returns the broadcast's intent action if the process is started for a broadcast receiver.
*
* @return the intent action of the broadcast.
*/
public @Nullable String getAction() {
return mAction;
}
/** Returns the type of trigger that led to this process start. */
public @NonNull String getTriggerType() {
return mTriggerType;
}
/**
* Creates a HostingRecord for a process that must spawn from the webview zygote
* @param hostingName name of the component to be hosted in this process
* @return The constructed HostingRecord
*/
public static HostingRecord byWebviewZygote(ComponentName hostingName,
String definingPackageName, int definingUid, String definingProcessName) {
return new HostingRecord(HostingRecord.HOSTING_TYPE_EMPTY, hostingName.toShortString(),
WEBVIEW_ZYGOTE, definingPackageName, definingUid, false /* isTopApp */,
definingProcessName, null /* action */, TRIGGER_TYPE_UNKNOWN);
}
/**
* Creates a HostingRecord for a process that must spawn from the application zygote
* @param hostingName name of the component to be hosted in this process
* @param definingPackageName name of the package defining the service
* @param definingUid uid of the package defining the service
* @return The constructed HostingRecord
*/
public static HostingRecord byAppZygote(ComponentName hostingName, String definingPackageName,
int definingUid, String definingProcessName) {
return new HostingRecord(HostingRecord.HOSTING_TYPE_EMPTY, hostingName.toShortString(),
APP_ZYGOTE, definingPackageName, definingUid, false /* isTopApp */,
definingProcessName, null /* action */, TRIGGER_TYPE_UNKNOWN);
}
/**
* @return whether the process should spawn from the application zygote
*/
public boolean usesAppZygote() {
return mHostingZygote == APP_ZYGOTE;
}
/**
* @return whether the process should spawn from the webview zygote
*/
public boolean usesWebviewZygote() {
return mHostingZygote == WEBVIEW_ZYGOTE;
}
/**
* Map the string hostingType to enum HostingType defined in ProcessStartTime proto.
* @param hostingType
* @return enum HostingType defined in ProcessStartTime proto
*/
public static int getHostingTypeIdStatsd(@NonNull String hostingType) {
switch(hostingType) {
case HOSTING_TYPE_ACTIVITY:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ACTIVITY;
case HOSTING_TYPE_ADDED_APPLICATION:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ADDED_APPLICATION;
case HOSTING_TYPE_BACKUP:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_BACKUP;
case HOSTING_TYPE_BROADCAST:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_BROADCAST;
case HOSTING_TYPE_CONTENT_PROVIDER:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_CONTENT_PROVIDER;
case HOSTING_TYPE_LINK_FAIL:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_LINK_FAIL;
case HOSTING_TYPE_ON_HOLD:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ON_HOLD;
case HOSTING_TYPE_NEXT_ACTIVITY:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_NEXT_ACTIVITY;
case HOSTING_TYPE_NEXT_TOP_ACTIVITY:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_NEXT_TOP_ACTIVITY;
case HOSTING_TYPE_RESTART:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_RESTART;
case HOSTING_TYPE_SERVICE:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SERVICE;
case HOSTING_TYPE_SYSTEM:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SYSTEM;
case HOSTING_TYPE_TOP_ACTIVITY:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_TOP_ACTIVITY;
case HOSTING_TYPE_EMPTY:
return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_EMPTY;
default:
return PROCESS_START_TIME__TYPE__UNKNOWN;
}
}
/**
* Map the string triggerType to enum TriggerType defined in ProcessStartTime proto.
* @param triggerType
* @return enum TriggerType defined in ProcessStartTime proto
*/
public static int getTriggerTypeForStatsd(@NonNull String triggerType) {
switch(triggerType) {
case TRIGGER_TYPE_ALARM:
return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_ALARM;
case TRIGGER_TYPE_PUSH_MESSAGE:
return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_PUSH_MESSAGE;
case TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA:
return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA;
case TRIGGER_TYPE_JOB:
return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_JOB;
default:
return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_UNKNOWN;
}
}
}