• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 android.app.ActivityManager;
20 import android.content.Context;
21 import android.os.IBinder;
22 import android.util.ArrayMap;
23 import android.util.ArraySet;
24 
25 import com.android.internal.annotations.GuardedBy;
26 
27 import java.io.PrintWriter;
28 import java.util.ArrayList;
29 
30 /**
31  * The state info of all services in the process.
32  */
33 final class ProcessServiceRecord {
34     /**
35      * Are there any client services with activities?
36      */
37     private boolean mHasClientActivities;
38 
39     /**
40      * Running any services that are foreground?
41      */
42     private boolean mHasForegroundServices;
43 
44     /**
45      * Service that applied current connectionGroup/Importance.
46      */
47     private ServiceRecord mConnectionService;
48 
49     /**
50      * Last group set by a connection.
51      */
52     private int mConnectionGroup;
53 
54     /**
55      * Last importance set by a connection.
56      */
57     private int mConnectionImportance;
58 
59     /**
60      * Type of foreground service, if there is a foreground service.
61      */
62     private int mFgServiceTypes;
63 
64     /**
65      * Last reported foreground service types.
66      */
67     private int mRepFgServiceTypes;
68 
69     /**
70      * Bound using BIND_ABOVE_CLIENT, so want to be lower.
71      */
72     private boolean mHasAboveClient;
73 
74     /**
75      * Bound using BIND_TREAT_LIKE_ACTIVITY.
76      */
77     private boolean mTreatLikeActivity;
78 
79     /**
80      * Do we need to be executing services in the foreground?
81      */
82     private boolean mExecServicesFg;
83 
84     /**
85      * App is allowed to manage allowlists such as temporary Power Save mode allowlist.
86      */
87     boolean mAllowlistManager;
88 
89     /**
90      * All ServiceRecord running in this process.
91      */
92     final ArraySet<ServiceRecord> mServices = new ArraySet<>();
93 
94     /**
95      * Services that are currently executing code (need to remain foreground).
96      */
97     private final ArraySet<ServiceRecord> mExecutingServices = new ArraySet<>();
98 
99     /**
100      * All ConnectionRecord this process holds.
101      */
102     private final ArraySet<ConnectionRecord> mConnections = new ArraySet<>();
103 
104     /**
105      * A set of UIDs of all bound clients.
106      */
107     private ArraySet<Integer> mBoundClientUids = new ArraySet<>();
108 
109     final ProcessRecord mApp;
110 
111     private final ActivityManagerService mService;
112 
ProcessServiceRecord(ProcessRecord app)113     ProcessServiceRecord(ProcessRecord app) {
114         mApp = app;
115         mService = app.mService;
116     }
117 
setHasClientActivities(boolean hasClientActivities)118     void setHasClientActivities(boolean hasClientActivities) {
119         mHasClientActivities = hasClientActivities;
120         mApp.getWindowProcessController().setHasClientActivities(hasClientActivities);
121     }
122 
hasClientActivities()123     boolean hasClientActivities() {
124         return mHasClientActivities;
125     }
126 
setHasForegroundServices(boolean hasForegroundServices, int fgServiceTypes)127     void setHasForegroundServices(boolean hasForegroundServices, int fgServiceTypes) {
128         mHasForegroundServices = hasForegroundServices;
129         mFgServiceTypes = fgServiceTypes;
130         mApp.getWindowProcessController().setHasForegroundServices(hasForegroundServices);
131     }
132 
hasForegroundServices()133     boolean hasForegroundServices() {
134         return mHasForegroundServices;
135     }
136 
getForegroundServiceTypes()137     int getForegroundServiceTypes() {
138         return mHasForegroundServices ? mFgServiceTypes : 0;
139     }
140 
getReportedForegroundServiceTypes()141     int getReportedForegroundServiceTypes() {
142         return mRepFgServiceTypes;
143     }
144 
setReportedForegroundServiceTypes(int foregroundServiceTypes)145     void setReportedForegroundServiceTypes(int foregroundServiceTypes) {
146         mRepFgServiceTypes = foregroundServiceTypes;
147     }
148 
getConnectionService()149     ServiceRecord getConnectionService() {
150         return mConnectionService;
151     }
152 
setConnectionService(ServiceRecord connectionService)153     void setConnectionService(ServiceRecord connectionService) {
154         mConnectionService = connectionService;
155     }
156 
getConnectionGroup()157     int getConnectionGroup() {
158         return mConnectionGroup;
159     }
160 
setConnectionGroup(int connectionGroup)161     void setConnectionGroup(int connectionGroup) {
162         mConnectionGroup = connectionGroup;
163     }
164 
getConnectionImportance()165     int getConnectionImportance() {
166         return mConnectionImportance;
167     }
168 
setConnectionImportance(int connectionImportance)169     void setConnectionImportance(int connectionImportance) {
170         mConnectionImportance = connectionImportance;
171     }
172 
updateHasAboveClientLocked()173     void updateHasAboveClientLocked() {
174         mHasAboveClient = false;
175         for (int i = mConnections.size() - 1; i >= 0; i--) {
176             ConnectionRecord cr = mConnections.valueAt(i);
177             if ((cr.flags & Context.BIND_ABOVE_CLIENT) != 0) {
178                 mHasAboveClient = true;
179                 break;
180             }
181         }
182     }
183 
setHasAboveClient(boolean hasAboveClient)184     void setHasAboveClient(boolean hasAboveClient) {
185         mHasAboveClient = hasAboveClient;
186     }
187 
hasAboveClient()188     boolean hasAboveClient() {
189         return mHasAboveClient;
190     }
191 
modifyRawOomAdj(int adj)192     int modifyRawOomAdj(int adj) {
193         if (mHasAboveClient) {
194             // If this process has bound to any services with BIND_ABOVE_CLIENT,
195             // then we need to drop its adjustment to be lower than the service's
196             // in order to honor the request.  We want to drop it by one adjustment
197             // level...  but there is special meaning applied to various levels so
198             // we will skip some of them.
199             if (adj < ProcessList.FOREGROUND_APP_ADJ) {
200                 // System process will not get dropped, ever
201             } else if (adj < ProcessList.VISIBLE_APP_ADJ) {
202                 adj = ProcessList.VISIBLE_APP_ADJ;
203             } else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) {
204                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
205             } else if (adj < ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
206                 adj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
207             } else if (adj < ProcessList.CACHED_APP_MIN_ADJ) {
208                 adj = ProcessList.CACHED_APP_MIN_ADJ;
209             } else if (adj < ProcessList.CACHED_APP_MAX_ADJ) {
210                 adj++;
211             }
212         }
213         return adj;
214     }
215 
isTreatedLikeActivity()216     boolean isTreatedLikeActivity() {
217         return mTreatLikeActivity;
218     }
219 
setTreatLikeActivity(boolean treatLikeActivity)220     void setTreatLikeActivity(boolean treatLikeActivity) {
221         mTreatLikeActivity = treatLikeActivity;
222     }
223 
shouldExecServicesFg()224     boolean shouldExecServicesFg() {
225         return mExecServicesFg;
226     }
227 
setExecServicesFg(boolean execServicesFg)228     void setExecServicesFg(boolean execServicesFg) {
229         mExecServicesFg = execServicesFg;
230     }
231 
232     /**
233      * Records a service as running in the process. Note that this method does not actually start
234      * the service, but records the service as started for bookkeeping.
235      *
236      * @return true if the service was added, false otherwise.
237      */
startService(ServiceRecord record)238     boolean startService(ServiceRecord record) {
239         if (record == null) {
240             return false;
241         }
242         boolean added = mServices.add(record);
243         if (added && record.serviceInfo != null) {
244             mApp.getWindowProcessController().onServiceStarted(record.serviceInfo);
245         }
246         return added;
247     }
248 
249     /**
250      * Records a service as stopped. Note that like {@link #startService(ServiceRecord)} this method
251      * does not actually stop the service, but records the service as stopped for bookkeeping.
252      *
253      * @return true if the service was removed, false otherwise.
254      */
stopService(ServiceRecord record)255     boolean stopService(ServiceRecord record) {
256         return mServices.remove(record);
257     }
258 
259     /**
260      * The same as calling {@link #stopService(ServiceRecord)} on all current running services.
261      */
stopAllServices()262     void stopAllServices() {
263         mServices.clear();
264     }
265 
266     /**
267      * Returns the number of services added with {@link #startService(ServiceRecord)} and not yet
268      * removed by a call to {@link #stopService(ServiceRecord)} or {@link #stopAllServices()}.
269      *
270      * @see #startService(ServiceRecord)
271      * @see #stopService(ServiceRecord)
272      */
numberOfRunningServices()273     int numberOfRunningServices() {
274         return mServices.size();
275     }
276 
277     /**
278      * Returns the service at the specified {@code index}.
279      *
280      * @see #numberOfRunningServices()
281      */
getRunningServiceAt(int index)282     ServiceRecord getRunningServiceAt(int index) {
283         return mServices.valueAt(index);
284     }
285 
startExecutingService(ServiceRecord service)286     void startExecutingService(ServiceRecord service) {
287         mExecutingServices.add(service);
288     }
289 
stopExecutingService(ServiceRecord service)290     void stopExecutingService(ServiceRecord service) {
291         mExecutingServices.remove(service);
292     }
293 
stopAllExecutingServices()294     void stopAllExecutingServices() {
295         mExecutingServices.clear();
296     }
297 
getExecutingServiceAt(int index)298     ServiceRecord getExecutingServiceAt(int index) {
299         return mExecutingServices.valueAt(index);
300     }
301 
numberOfExecutingServices()302     int numberOfExecutingServices() {
303         return mExecutingServices.size();
304     }
305 
addConnection(ConnectionRecord connection)306     void addConnection(ConnectionRecord connection) {
307         mConnections.add(connection);
308     }
309 
removeConnection(ConnectionRecord connection)310     void removeConnection(ConnectionRecord connection) {
311         mConnections.remove(connection);
312     }
313 
removeAllConnections()314     void removeAllConnections() {
315         mConnections.clear();
316     }
317 
getConnectionAt(int index)318     ConnectionRecord getConnectionAt(int index) {
319         return mConnections.valueAt(index);
320     }
321 
numberOfConnections()322     int numberOfConnections() {
323         return mConnections.size();
324     }
325 
addBoundClientUid(int clientUid)326     void addBoundClientUid(int clientUid) {
327         mBoundClientUids.add(clientUid);
328         mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids);
329     }
330 
updateBoundClientUids()331     void updateBoundClientUids() {
332         if (mServices.isEmpty()) {
333             clearBoundClientUids();
334             return;
335         }
336         // grab a set of clientUids of all mConnections of all services
337         final ArraySet<Integer> boundClientUids = new ArraySet<>();
338         final int serviceCount = mServices.size();
339         for (int j = 0; j < serviceCount; j++) {
340             final ArrayMap<IBinder, ArrayList<ConnectionRecord>> conns =
341                     mServices.valueAt(j).getConnections();
342             final int size = conns.size();
343             for (int conni = 0; conni < size; conni++) {
344                 ArrayList<ConnectionRecord> c = conns.valueAt(conni);
345                 for (int i = 0; i < c.size(); i++) {
346                     boundClientUids.add(c.get(i).clientUid);
347                 }
348             }
349         }
350         mBoundClientUids = boundClientUids;
351         mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids);
352     }
353 
addBoundClientUidsOfNewService(ServiceRecord sr)354     void addBoundClientUidsOfNewService(ServiceRecord sr) {
355         if (sr == null) {
356             return;
357         }
358         ArrayMap<IBinder, ArrayList<ConnectionRecord>> conns = sr.getConnections();
359         for (int conni = conns.size() - 1; conni >= 0; conni--) {
360             ArrayList<ConnectionRecord> c = conns.valueAt(conni);
361             for (int i = 0; i < c.size(); i++) {
362                 mBoundClientUids.add(c.get(i).clientUid);
363             }
364         }
365         mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids);
366     }
367 
clearBoundClientUids()368     void clearBoundClientUids() {
369         mBoundClientUids.clear();
370         mApp.getWindowProcessController().setBoundClientUids(mBoundClientUids);
371     }
372 
373     @GuardedBy("mService")
incServiceCrashCountLocked(long now)374     boolean incServiceCrashCountLocked(long now) {
375         final boolean procIsBoundForeground = mApp.mState.getCurProcState()
376                 == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
377         boolean tryAgain = false;
378         // Bump up the crash count of any services currently running in the proc.
379         for (int i = numberOfRunningServices() - 1; i >= 0; i--) {
380             // Any services running in the application need to be placed
381             // back in the pending list.
382             ServiceRecord sr = getRunningServiceAt(i);
383             // If the service was restarted a while ago, then reset crash count, else increment it.
384             if (now > sr.restartTime + ActivityManagerConstants.MIN_CRASH_INTERVAL) {
385                 sr.crashCount = 1;
386             } else {
387                 sr.crashCount++;
388             }
389             // Allow restarting for started or bound foreground services that are crashing.
390             // This includes wallpapers.
391             if (sr.crashCount < mService.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY
392                     && (sr.isForeground || procIsBoundForeground)) {
393                 tryAgain = true;
394             }
395         }
396         return tryAgain;
397     }
398 
399     @GuardedBy("mService")
onCleanupApplicationRecordLocked()400     void onCleanupApplicationRecordLocked() {
401         mTreatLikeActivity = false;
402         mHasAboveClient = false;
403         setHasClientActivities(false);
404     }
405 
dump(PrintWriter pw, String prefix, long nowUptime)406     void dump(PrintWriter pw, String prefix, long nowUptime) {
407         if (mHasForegroundServices || mApp.mState.getForcingToImportant() != null) {
408             pw.print(prefix); pw.print("mHasForegroundServices="); pw.print(mHasForegroundServices);
409             pw.print(" forcingToImportant="); pw.println(mApp.mState.getForcingToImportant());
410         }
411         if (mHasClientActivities || mHasAboveClient || mTreatLikeActivity) {
412             pw.print(prefix); pw.print("hasClientActivities="); pw.print(mHasClientActivities);
413             pw.print(" hasAboveClient="); pw.print(mHasAboveClient);
414             pw.print(" treatLikeActivity="); pw.println(mTreatLikeActivity);
415         }
416         if (mConnectionService != null || mConnectionGroup != 0) {
417             pw.print(prefix); pw.print("connectionGroup="); pw.print(mConnectionGroup);
418             pw.print(" Importance="); pw.print(mConnectionImportance);
419             pw.print(" Service="); pw.println(mConnectionService);
420         }
421         if (mAllowlistManager) {
422             pw.print(prefix); pw.print("allowlistManager="); pw.println(mAllowlistManager);
423         }
424         if (mServices.size() > 0) {
425             pw.print(prefix); pw.println("Services:");
426             for (int i = 0, size = mServices.size(); i < size; i++) {
427                 pw.print(prefix); pw.print("  - "); pw.println(mServices.valueAt(i));
428             }
429         }
430         if (mExecutingServices.size() > 0) {
431             pw.print(prefix); pw.print("Executing Services (fg=");
432             pw.print(mExecServicesFg); pw.println(")");
433             for (int i = 0, size = mExecutingServices.size(); i < size; i++) {
434                 pw.print(prefix); pw.print("  - "); pw.println(mExecutingServices.valueAt(i));
435             }
436         }
437         if (mConnections.size() > 0) {
438             pw.print(prefix); pw.println("mConnections:");
439             for (int i = 0, size = mConnections.size(); i < size; i++) {
440                 pw.print(prefix); pw.print("  - "); pw.println(mConnections.valueAt(i));
441             }
442         }
443     }
444 }
445