1 /*
2  * Copyright (C) 2019 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.am;
18 
19 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ACTIVITY;
20 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ADDED_APPLICATION;
21 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_BACKUP;
22 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_BROADCAST;
23 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_CONTENT_PROVIDER;
24 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_EMPTY;
25 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_LINK_FAIL;
26 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_NEXT_ACTIVITY;
27 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_NEXT_TOP_ACTIVITY;
28 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ON_HOLD;
29 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_RESTART;
30 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SERVICE;
31 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SYSTEM;
32 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_TOP_ACTIVITY;
33 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_ALARM;
34 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_JOB;
35 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_PUSH_MESSAGE;
36 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA;
37 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_UNKNOWN;
38 import static com.android.internal.util.FrameworkStatsLog.PROCESS_START_TIME__TYPE__UNKNOWN;
39 
40 import android.annotation.NonNull;
41 import android.annotation.Nullable;
42 import android.content.ComponentName;
43 
44 /**
45  * This class describes various information required to start a process.
46  *
47  * The {@code mHostingType} field describes the reason why we started a process, and
48  * is only used for logging and stats.
49  *
50  * The {@code mHostingName} field describes the Component for which we are starting the
51  * process, and is only used for logging and stats.
52  *
53  * The {@code mHostingZygote} field describes from which Zygote the new process should be spawned.
54  *
55  * The {@code mTriggerType} field describes the trigger that started this processs. This could be
56  * an alarm or a push-message for a broadcast, for example. This is purely for logging and stats.
57  *
58  * {@code mDefiningPackageName} contains the packageName of the package that defines the
59  * component we want to start; this can be different from the packageName and uid in the
60  * ApplicationInfo that we're creating the process with, in case the service is a
61  * {@link android.content.Context#BIND_EXTERNAL_SERVICE} service. In that case, the packageName
62  * and uid in the ApplicationInfo will be set to those of the caller, not of the defining package.
63  *
64  * {@code mDefiningUid} contains the uid of the application that defines the component we want to
65  * start; this can be different from the packageName and uid in the ApplicationInfo that we're
66  * creating the process with, in case the service is a
67  * {@link android.content.Context#BIND_EXTERNAL_SERVICE} service. In that case, the packageName
68  * and uid in the ApplicationInfo will be set to those of the caller, not of the defining package.
69  *
70  * {@code mIsTopApp} will be passed to {@link android.os.Process#start}. So Zygote will initialize
71  * the process with high priority.
72  *
73  *  {@code mAction} the broadcast's intent action if the process is started for a broadcast
74  *  receiver.
75  */
76 
77 public final class HostingRecord {
78     private static final int REGULAR_ZYGOTE = 0;
79     private static final int WEBVIEW_ZYGOTE = 1;
80     private static final int APP_ZYGOTE = 2;
81 
82     public static final String HOSTING_TYPE_ACTIVITY = "activity";
83     public static final String HOSTING_TYPE_ADDED_APPLICATION = "added application";
84     public static final String HOSTING_TYPE_BACKUP = "backup";
85     public static final String HOSTING_TYPE_BROADCAST = "broadcast";
86     public static final String HOSTING_TYPE_CONTENT_PROVIDER = "content provider";
87     public static final String HOSTING_TYPE_LINK_FAIL = "link fail";
88     public static final String HOSTING_TYPE_ON_HOLD = "on-hold";
89     public static final String HOSTING_TYPE_NEXT_ACTIVITY = "next-activity";
90     public static final String HOSTING_TYPE_NEXT_TOP_ACTIVITY = "next-top-activity";
91     public static final String HOSTING_TYPE_RESTART = "restart";
92     public static final String HOSTING_TYPE_SERVICE = "service";
93     public static final String HOSTING_TYPE_SYSTEM = "system";
94     public static final String HOSTING_TYPE_TOP_ACTIVITY = "top-activity";
95     public static final String HOSTING_TYPE_EMPTY = "";
96 
97     public static final String TRIGGER_TYPE_UNKNOWN = "unknown";
98     public static final String TRIGGER_TYPE_ALARM = "alarm";
99     public static final String TRIGGER_TYPE_PUSH_MESSAGE = "push_message";
100     public static final String TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA = "push_message_over_quota";
101     public static final String TRIGGER_TYPE_JOB = "job";
102 
103     @NonNull private final String mHostingType;
104     private final String mHostingName;
105     private final int mHostingZygote;
106     private final String mDefiningPackageName;
107     private final int mDefiningUid;
108     private final boolean mIsTopApp;
109     private final String mDefiningProcessName;
110     @Nullable private final String mAction;
111     @NonNull private final String mTriggerType;
112 
HostingRecord(@onNull String hostingType)113     public HostingRecord(@NonNull String hostingType) {
114         this(hostingType, null /* hostingName */, REGULAR_ZYGOTE, null /* definingPackageName */,
115                 -1 /* mDefiningUid */, false /* isTopApp */, null /* definingProcessName */,
116                 null /* action */, TRIGGER_TYPE_UNKNOWN);
117     }
118 
HostingRecord(@onNull String hostingType, ComponentName hostingName)119     public HostingRecord(@NonNull String hostingType, ComponentName hostingName) {
120         this(hostingType, hostingName, REGULAR_ZYGOTE);
121     }
122 
HostingRecord(@onNull String hostingType, ComponentName hostingName, @Nullable String action, @Nullable String triggerType)123     public HostingRecord(@NonNull String hostingType, ComponentName hostingName,
124             @Nullable String action, @Nullable String triggerType) {
125         this(hostingType, hostingName.toShortString(), REGULAR_ZYGOTE,
126                 null /* definingPackageName */, -1 /* mDefiningUid */, false /* isTopApp */,
127                 null /* definingProcessName */, action, triggerType);
128     }
129 
HostingRecord(@onNull String hostingType, ComponentName hostingName, String definingPackageName, int definingUid, String definingProcessName, String triggerType)130     public HostingRecord(@NonNull String hostingType, ComponentName hostingName,
131             String definingPackageName, int definingUid, String definingProcessName,
132             String triggerType) {
133         this(hostingType, hostingName.toShortString(), REGULAR_ZYGOTE, definingPackageName,
134                 definingUid, false /* isTopApp */, definingProcessName, null /* action */,
135                 triggerType);
136     }
137 
HostingRecord(@onNull String hostingType, ComponentName hostingName, boolean isTopApp)138     public HostingRecord(@NonNull String hostingType, ComponentName hostingName, boolean isTopApp) {
139         this(hostingType, hostingName.toShortString(), REGULAR_ZYGOTE,
140                 null /* definingPackageName */, -1 /* mDefiningUid */, isTopApp /* isTopApp */,
141                 null /* definingProcessName */, null /* action */, TRIGGER_TYPE_UNKNOWN);
142     }
143 
HostingRecord(@onNull String hostingType, String hostingName)144     public HostingRecord(@NonNull String hostingType, String hostingName) {
145         this(hostingType, hostingName, REGULAR_ZYGOTE);
146     }
147 
HostingRecord(@onNull String hostingType, ComponentName hostingName, int hostingZygote)148     private HostingRecord(@NonNull String hostingType, ComponentName hostingName,
149             int hostingZygote) {
150         this(hostingType, hostingName.toShortString(), hostingZygote);
151     }
152 
HostingRecord(@onNull String hostingType, String hostingName, int hostingZygote)153     private HostingRecord(@NonNull String hostingType, String hostingName, int hostingZygote) {
154         this(hostingType, hostingName, hostingZygote, null /* definingPackageName */,
155                 -1 /* mDefiningUid */, false /* isTopApp */, null /* definingProcessName */,
156                 null /* action */, TRIGGER_TYPE_UNKNOWN);
157     }
158 
HostingRecord(@onNull String hostingType, String hostingName, int hostingZygote, String definingPackageName, int definingUid, boolean isTopApp, String definingProcessName, @Nullable String action, String triggerType)159     private HostingRecord(@NonNull String hostingType, String hostingName, int hostingZygote,
160             String definingPackageName, int definingUid, boolean isTopApp,
161             String definingProcessName, @Nullable String action, String triggerType) {
162         mHostingType = hostingType;
163         mHostingName = hostingName;
164         mHostingZygote = hostingZygote;
165         mDefiningPackageName = definingPackageName;
166         mDefiningUid = definingUid;
167         mIsTopApp = isTopApp;
168         mDefiningProcessName = definingProcessName;
169         mAction = action;
170         mTriggerType = triggerType;
171     }
172 
getType()173     public @NonNull String getType() {
174         return mHostingType;
175     }
176 
getName()177     public String getName() {
178         return mHostingName;
179     }
180 
isTopApp()181     public boolean isTopApp() {
182         return mIsTopApp;
183     }
184 
185     /**
186      * Returns the UID of the package defining the component we want to start. Only valid
187      * when {@link #usesAppZygote()} returns true.
188      *
189      * @return the UID of the hosting application
190      */
getDefiningUid()191     public int getDefiningUid() {
192         return mDefiningUid;
193     }
194 
195     /**
196      * Returns the packageName of the package defining the component we want to start. Only valid
197      * when {@link #usesAppZygote()} returns true.
198      *
199      * @return the packageName of the hosting application
200      */
getDefiningPackageName()201     public String getDefiningPackageName() {
202         return mDefiningPackageName;
203     }
204 
205     /**
206      * Returns the processName of the component we want to start as specified in the defining app's
207      * manifest.
208      *
209      * @return the processName of the process in the hosting application
210      */
getDefiningProcessName()211     public String getDefiningProcessName() {
212         return mDefiningProcessName;
213     }
214 
215     /**
216      * Returns the broadcast's intent action if the process is started for a broadcast receiver.
217      *
218      * @return the intent action of the broadcast.
219      */
getAction()220     public @Nullable String getAction() {
221         return mAction;
222     }
223 
224     /** Returns the type of trigger that led to this process start. */
getTriggerType()225     public @NonNull String getTriggerType() {
226         return mTriggerType;
227     }
228 
229     /**
230      * Creates a HostingRecord for a process that must spawn from the webview zygote
231      * @param hostingName name of the component to be hosted in this process
232      * @return The constructed HostingRecord
233      */
byWebviewZygote(ComponentName hostingName, String definingPackageName, int definingUid, String definingProcessName)234     public static HostingRecord byWebviewZygote(ComponentName hostingName,
235             String definingPackageName, int definingUid, String definingProcessName) {
236         return new HostingRecord(HostingRecord.HOSTING_TYPE_EMPTY, hostingName.toShortString(),
237                 WEBVIEW_ZYGOTE, definingPackageName, definingUid, false /* isTopApp */,
238                 definingProcessName, null /* action */, TRIGGER_TYPE_UNKNOWN);
239     }
240 
241     /**
242      * Creates a HostingRecord for a process that must spawn from the application zygote
243      * @param hostingName name of the component to be hosted in this process
244      * @param definingPackageName name of the package defining the service
245      * @param definingUid uid of the package defining the service
246      * @return The constructed HostingRecord
247      */
byAppZygote(ComponentName hostingName, String definingPackageName, int definingUid, String definingProcessName)248     public static HostingRecord byAppZygote(ComponentName hostingName, String definingPackageName,
249             int definingUid, String definingProcessName) {
250         return new HostingRecord(HostingRecord.HOSTING_TYPE_EMPTY, hostingName.toShortString(),
251                 APP_ZYGOTE, definingPackageName, definingUid, false /* isTopApp */,
252                 definingProcessName, null /* action */, TRIGGER_TYPE_UNKNOWN);
253     }
254 
255     /**
256      * @return whether the process should spawn from the application zygote
257      */
usesAppZygote()258     public boolean usesAppZygote() {
259         return mHostingZygote == APP_ZYGOTE;
260     }
261 
262     /**
263      * @return whether the process should spawn from the webview zygote
264      */
usesWebviewZygote()265     public boolean usesWebviewZygote() {
266         return mHostingZygote == WEBVIEW_ZYGOTE;
267     }
268 
269     /**
270      * Map the string hostingType to enum HostingType defined in ProcessStartTime proto.
271      * @param hostingType
272      * @return enum HostingType defined in ProcessStartTime proto
273      */
getHostingTypeIdStatsd(@onNull String hostingType)274     public static int getHostingTypeIdStatsd(@NonNull String hostingType) {
275         switch(hostingType) {
276             case HOSTING_TYPE_ACTIVITY:
277                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ACTIVITY;
278             case HOSTING_TYPE_ADDED_APPLICATION:
279                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ADDED_APPLICATION;
280             case HOSTING_TYPE_BACKUP:
281                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_BACKUP;
282             case HOSTING_TYPE_BROADCAST:
283                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_BROADCAST;
284             case HOSTING_TYPE_CONTENT_PROVIDER:
285                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_CONTENT_PROVIDER;
286             case HOSTING_TYPE_LINK_FAIL:
287                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_LINK_FAIL;
288             case HOSTING_TYPE_ON_HOLD:
289                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_ON_HOLD;
290             case HOSTING_TYPE_NEXT_ACTIVITY:
291                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_NEXT_ACTIVITY;
292             case HOSTING_TYPE_NEXT_TOP_ACTIVITY:
293                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_NEXT_TOP_ACTIVITY;
294             case HOSTING_TYPE_RESTART:
295                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_RESTART;
296             case HOSTING_TYPE_SERVICE:
297                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SERVICE;
298             case HOSTING_TYPE_SYSTEM:
299                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_SYSTEM;
300             case HOSTING_TYPE_TOP_ACTIVITY:
301                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_TOP_ACTIVITY;
302             case HOSTING_TYPE_EMPTY:
303                 return PROCESS_START_TIME__HOSTING_TYPE_ID__HOSTING_TYPE_EMPTY;
304             default:
305                 return PROCESS_START_TIME__TYPE__UNKNOWN;
306         }
307     }
308 
309     /**
310      * Map the string triggerType to enum TriggerType defined in ProcessStartTime proto.
311      * @param triggerType
312      * @return enum TriggerType defined in ProcessStartTime proto
313      */
getTriggerTypeForStatsd(@onNull String triggerType)314     public static int getTriggerTypeForStatsd(@NonNull String triggerType) {
315         switch(triggerType) {
316             case TRIGGER_TYPE_ALARM:
317                 return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_ALARM;
318             case TRIGGER_TYPE_PUSH_MESSAGE:
319                 return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_PUSH_MESSAGE;
320             case TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA:
321                 return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_PUSH_MESSAGE_OVER_QUOTA;
322             case TRIGGER_TYPE_JOB:
323                 return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_JOB;
324             default:
325                 return PROCESS_START_TIME__TRIGGER_TYPE__TRIGGER_TYPE_UNKNOWN;
326         }
327     }
328 
isTypeActivity(String hostingType)329     private static boolean isTypeActivity(String hostingType) {
330         return HOSTING_TYPE_ACTIVITY.equals(hostingType)
331                 || HOSTING_TYPE_NEXT_ACTIVITY.equals(hostingType)
332                 || HOSTING_TYPE_NEXT_TOP_ACTIVITY.equals(hostingType)
333                 || HOSTING_TYPE_TOP_ACTIVITY.equals(hostingType);
334     }
335 
isTypeActivity()336     public boolean isTypeActivity() {
337         return isTypeActivity(mHostingType);
338     }
339 }
340