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