1 /*
2  * Copyright (C) 2015 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.Manifest;
20 import android.app.ActivityManager;
21 import android.content.pm.PackageManager;
22 import android.os.SystemClock;
23 import android.os.UserHandle;
24 import android.text.TextUtils;
25 import android.util.ArraySet;
26 import android.util.TimeUtils;
27 import android.util.proto.ProtoOutputStream;
28 import android.util.proto.ProtoUtils;
29 
30 import com.android.internal.annotations.CompositeRWLock;
31 import com.android.internal.annotations.GuardedBy;
32 import com.android.server.am.UidObserverController.ChangeRecord;
33 
34 import java.util.function.Consumer;
35 
36 /**
37  * Overall information about a uid that has actively running processes.
38  */
39 public final class UidRecord {
40     private final ActivityManagerService mService;
41     private final ActivityManagerGlobalLock mProcLock;
42     private final int mUid;
43 
44     @CompositeRWLock({"mService", "mProcLock"})
45     private int mCurProcState;
46 
47     @CompositeRWLock({"mService", "mProcLock"})
48     private int mSetProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
49 
50     @CompositeRWLock({"mService", "mProcLock"})
51     private boolean mProcAdjChanged;
52 
53     @CompositeRWLock({"mService", "mProcLock"})
54     private int mCurAdj;
55 
56     @CompositeRWLock({"mService", "mProcLock"})
57     private int mSetAdj;
58 
59     @CompositeRWLock({"mService", "mProcLock"})
60     private int mCurCapability;
61 
62     @CompositeRWLock({"mService", "mProcLock"})
63     private int mSetCapability;
64 
65     @CompositeRWLock({"mService", "mProcLock"})
66     private long mLastBackgroundTime;
67 
68     @CompositeRWLock({"mService", "mProcLock"})
69     private boolean mEphemeral;
70 
71     @CompositeRWLock({"mService", "mProcLock"})
72     private boolean mForegroundServices;
73 
74     @CompositeRWLock({"mService", "mProcLock"})
75     private boolean mCurAllowList;;
76 
77     @CompositeRWLock({"mService", "mProcLock"})
78     private boolean mSetAllowList;
79 
80     @CompositeRWLock({"mService", "mProcLock"})
81     private boolean mIdle;
82 
83     @CompositeRWLock({"mService", "mProcLock"})
84     private boolean mSetIdle;
85 
86     @CompositeRWLock({"mService", "mProcLock"})
87     private int mNumProcs;
88 
89     @CompositeRWLock({"mService", "mProcLock"})
90     private ArraySet<ProcessRecord> mProcRecords = new ArraySet<>();
91 
92     /**
93      * Sequence number associated with the {@link #mCurProcState}. This is incremented using
94      * {@link ActivityManagerService#mProcStateSeqCounter}
95      * when {@link #mCurProcState} changes from background to foreground or vice versa.
96      */
97     @GuardedBy("networkStateUpdate")
98     long curProcStateSeq;
99 
100     /**
101      * Last seq number for which NetworkPolicyManagerService notified ActivityManagerService that
102      * network policies rules were updated.
103      */
104     @GuardedBy("networkStateUpdate")
105     long lastNetworkUpdatedProcStateSeq;
106 
107     /**
108      * Indicates if any thread is waiting for network rules to get updated for {@link #mUid}.
109      */
110     volatile long procStateSeqWaitingForNetwork;
111 
112     /**
113      * Indicates whether this uid has internet permission or not.
114      */
115     volatile boolean hasInternetPermission;
116 
117     /**
118      * This object is used for waiting for the network state to get updated.
119      */
120     final Object networkStateLock = new Object();
121 
122     /*
123      * Change bitmask flags.
124      */
125     static final int CHANGE_GONE = 1 << 0;
126     static final int CHANGE_IDLE = 1 << 1;
127     static final int CHANGE_ACTIVE = 1 << 2;
128     static final int CHANGE_CACHED = 1 << 3;
129     static final int CHANGE_UNCACHED = 1 << 4;
130     static final int CHANGE_CAPABILITY = 1 << 5;
131     static final int CHANGE_PROCADJ = 1 << 6;
132     static final int CHANGE_PROCSTATE = 1 << 31;
133 
134     // Keep the enum lists in sync
135     private static int[] ORIG_ENUMS = new int[] {
136             CHANGE_GONE,
137             CHANGE_IDLE,
138             CHANGE_ACTIVE,
139             CHANGE_CACHED,
140             CHANGE_UNCACHED,
141             CHANGE_CAPABILITY,
142             CHANGE_PROCSTATE,
143     };
144     private static int[] PROTO_ENUMS = new int[] {
145             UidRecordProto.CHANGE_GONE,
146             UidRecordProto.CHANGE_IDLE,
147             UidRecordProto.CHANGE_ACTIVE,
148             UidRecordProto.CHANGE_CACHED,
149             UidRecordProto.CHANGE_UNCACHED,
150             UidRecordProto.CHANGE_CAPABILITY,
151             UidRecordProto.CHANGE_PROCSTATE,
152     };
153 
154     // UidObserverController is the only thing that should modify this.
155     final ChangeRecord pendingChange = new ChangeRecord();
156 
157     @GuardedBy("mService")
158     private int mLastReportedChange;
159 
160     /**
161      * This indicates whether the entire Uid is frozen or not.
162      * It is used by CachedAppOptimizer to avoid sending multiple
163      * UID_FROZEN_STATE_UNFROZEN messages on process unfreeze.
164      */
165     @GuardedBy(anyOf = {"mService", "mProcLock"})
166     private boolean mUidIsFrozen;
167 
UidRecord(int uid, ActivityManagerService service)168     public UidRecord(int uid, ActivityManagerService service) {
169         mUid = uid;
170         mService = service;
171         mProcLock = service != null ? service.mProcLock : null;
172         mIdle = true;
173         reset();
174     }
175 
getUid()176     int getUid() {
177         return mUid;
178     }
179 
180     @GuardedBy(anyOf = {"mService", "mProcLock"})
getCurProcState()181     int getCurProcState() {
182         return mCurProcState;
183     }
184 
185     @GuardedBy({"mService", "mProcLock"})
setCurProcState(int curProcState)186     void setCurProcState(int curProcState) {
187         mCurProcState = curProcState;
188     }
189 
190     @GuardedBy(anyOf = {"mService", "mProcLock"})
getSetProcState()191     int getSetProcState() {
192         return mSetProcState;
193     }
194 
195     @GuardedBy({"mService", "mProcLock"})
setSetProcState(int setProcState)196     void setSetProcState(int setProcState) {
197         mSetProcState = setProcState;
198     }
199 
200     @GuardedBy({"mService", "mProcLock"})
noteProcAdjChanged()201     void noteProcAdjChanged() {
202         mProcAdjChanged = true;
203     }
204 
205     @GuardedBy({"mService", "mProcLock"})
clearProcAdjChanged()206     void clearProcAdjChanged() {
207         mProcAdjChanged = false;
208     }
209 
210     @GuardedBy(anyOf = {"mService", "mProcLock"})
getProcAdjChanged()211     boolean getProcAdjChanged() {
212         return mProcAdjChanged;
213     }
214 
215     @GuardedBy(anyOf = {"mService", "mProcLock"})
getMinProcAdj()216     int getMinProcAdj() {
217         int minAdj = ProcessList.UNKNOWN_ADJ;
218         for (int i = mProcRecords.size() - 1; i >= 0; i--) {
219             int adj = mProcRecords.valueAt(i).getSetAdj();
220             if (adj < minAdj) {
221                 minAdj = adj;
222             }
223         }
224         return minAdj;
225     }
226 
227     @GuardedBy(anyOf = {"mService", "mProcLock"})
getCurCapability()228     int getCurCapability() {
229         return mCurCapability;
230     }
231 
232     @GuardedBy({"mService", "mProcLock"})
setCurCapability(int curCapability)233     void setCurCapability(int curCapability) {
234         mCurCapability = curCapability;
235     }
236 
237     @GuardedBy(anyOf = {"mService", "mProcLock"})
getSetCapability()238     int getSetCapability() {
239         return mSetCapability;
240     }
241 
242     @GuardedBy({"mService", "mProcLock"})
setSetCapability(int setCapability)243     void setSetCapability(int setCapability) {
244         mSetCapability = setCapability;
245     }
246 
247     @GuardedBy(anyOf = {"mService", "mProcLock"})
getLastBackgroundTime()248     long getLastBackgroundTime() {
249         return mLastBackgroundTime;
250     }
251 
252     @GuardedBy({"mService", "mProcLock"})
setLastBackgroundTime(long lastBackgroundTime)253     void setLastBackgroundTime(long lastBackgroundTime) {
254         mLastBackgroundTime = lastBackgroundTime;
255     }
256 
257     @GuardedBy(anyOf = {"mService", "mProcLock"})
isEphemeral()258     boolean isEphemeral() {
259         return mEphemeral;
260     }
261 
262     @GuardedBy({"mService", "mProcLock"})
setEphemeral(boolean ephemeral)263     void setEphemeral(boolean ephemeral) {
264         mEphemeral = ephemeral;
265     }
266 
267     /** Returns whether the UID has any FGS of any type or not (including "short fgs") */
268     @GuardedBy(anyOf = {"mService", "mProcLock"})
hasForegroundServices()269     boolean hasForegroundServices() {
270         return mForegroundServices;
271     }
272 
273     /** Sets whether the UID has any FGS of any type or not (including "short fgs") */
274     @GuardedBy({"mService", "mProcLock"})
setForegroundServices(boolean foregroundServices)275     void setForegroundServices(boolean foregroundServices) {
276         mForegroundServices = foregroundServices;
277     }
278 
279     @GuardedBy(anyOf = {"mService", "mProcLock"})
isCurAllowListed()280     boolean isCurAllowListed() {
281         return mCurAllowList;
282     }
283 
284     @GuardedBy({"mService", "mProcLock"})
setCurAllowListed(boolean curAllowList)285     void setCurAllowListed(boolean curAllowList) {
286         mCurAllowList = curAllowList;
287     }
288 
289     @GuardedBy(anyOf = {"mService", "mProcLock"})
isSetAllowListed()290     boolean isSetAllowListed() {
291         return mSetAllowList;
292     }
293 
294     @GuardedBy({"mService", "mProcLock"})
setSetAllowListed(boolean setAllowlist)295     void setSetAllowListed(boolean setAllowlist) {
296         mSetAllowList = setAllowlist;
297     }
298 
299     @GuardedBy(anyOf = {"mService", "mProcLock"})
isIdle()300     boolean isIdle() {
301         return mIdle;
302     }
303 
304     @GuardedBy({"mService", "mProcLock"})
setIdle(boolean idle)305     void setIdle(boolean idle) {
306         mIdle = idle;
307     }
308 
309     @GuardedBy(anyOf = {"mService", "mProcLock"})
isSetIdle()310     boolean isSetIdle() {
311         return mSetIdle;
312     }
313 
314     @GuardedBy({"mService", "mProcLock"})
setSetIdle(boolean setIdle)315     void setSetIdle(boolean setIdle) {
316         mSetIdle = setIdle;
317     }
318 
319     @GuardedBy(anyOf = {"mService", "mProcLock"})
getNumOfProcs()320     int getNumOfProcs() {
321         return mProcRecords.size();
322     }
323 
324     @GuardedBy(anyOf = {"mService", "mProcLock"})
forEachProcess(Consumer<ProcessRecord> callback)325     void forEachProcess(Consumer<ProcessRecord> callback) {
326         for (int i = mProcRecords.size() - 1; i >= 0; i--) {
327             callback.accept(mProcRecords.valueAt(i));
328         }
329     }
330 
331     @GuardedBy(anyOf = {"mService", "mProcLock"})
getProcessRecordByIndex(int idx)332     ProcessRecord getProcessRecordByIndex(int idx) {
333         return mProcRecords.valueAt(idx);
334     }
335 
336     @GuardedBy(anyOf = {"mService", "mProcLock"})
getProcessInPackage(String packageName)337     ProcessRecord getProcessInPackage(String packageName) {
338         for (int i = mProcRecords.size() - 1; i >= 0; i--) {
339             final ProcessRecord app = mProcRecords.valueAt(i);
340             if (app != null && TextUtils.equals(app.info.packageName, packageName)) {
341                 return app;
342             }
343         }
344         return null;
345     }
346 
347     /**
348      * Check whether all processes in the Uid are frozen.
349      *
350      * @param excluding Skip this process record during the check.
351      * @return true if all processes in the Uid are frozen, false otherwise.
352      */
353     @GuardedBy(anyOf = {"mService", "mProcLock"})
areAllProcessesFrozen(ProcessRecord excluding)354     public boolean areAllProcessesFrozen(ProcessRecord excluding) {
355         for (int i = mProcRecords.size() - 1; i >= 0; i--) {
356             final ProcessRecord app = mProcRecords.valueAt(i);
357             final ProcessCachedOptimizerRecord opt = app.mOptRecord;
358 
359             if (excluding != app && !opt.isFrozen()) {
360                 return false;
361             }
362         }
363         return true;
364     }
365 
366     /**
367      * @return true if all processes in the Uid are frozen, false otherwise.
368      */
369     @GuardedBy(anyOf = {"mService", "mProcLock"})
areAllProcessesFrozen()370     public boolean areAllProcessesFrozen() {
371         return areAllProcessesFrozen(null);
372     }
373 
374     @GuardedBy(anyOf = {"mService", "mProcLock"})
setFrozen(boolean frozen)375     public void setFrozen(boolean frozen) {
376         mUidIsFrozen = frozen;
377     }
378 
379     @GuardedBy(anyOf = {"mService", "mProcLock"})
isFrozen()380     public boolean isFrozen() {
381         return mUidIsFrozen;
382     }
383 
384     @GuardedBy({"mService", "mProcLock"})
addProcess(ProcessRecord app)385     void addProcess(ProcessRecord app) {
386         mProcRecords.add(app);
387     }
388 
389     @GuardedBy({"mService", "mProcLock"})
removeProcess(ProcessRecord app)390     void removeProcess(ProcessRecord app) {
391         mProcRecords.remove(app);
392     }
393 
394     @GuardedBy("mService")
setLastReportedChange(int lastReportedChange)395     void setLastReportedChange(int lastReportedChange) {
396         mLastReportedChange = lastReportedChange;
397     }
398 
399     @GuardedBy({"mService", "mProcLock"})
reset()400     void reset() {
401         setCurProcState(ActivityManager.PROCESS_STATE_CACHED_EMPTY);
402         mForegroundServices = false;
403         mCurCapability = 0;
404     }
405 
updateHasInternetPermission()406     public void updateHasInternetPermission() {
407         hasInternetPermission = ActivityManager.checkUidPermission(Manifest.permission.INTERNET,
408                 mUid) == PackageManager.PERMISSION_GRANTED;
409     }
410 
dumpDebug(ProtoOutputStream proto, long fieldId)411     void dumpDebug(ProtoOutputStream proto, long fieldId) {
412         long token = proto.start(fieldId);
413         proto.write(UidRecordProto.UID, mUid);
414         proto.write(UidRecordProto.CURRENT, ProcessList.makeProcStateProtoEnum(mCurProcState));
415         proto.write(UidRecordProto.EPHEMERAL, mEphemeral);
416         proto.write(UidRecordProto.FG_SERVICES, mForegroundServices);
417         proto.write(UidRecordProto.WHILELIST, mCurAllowList);
418         ProtoUtils.toDuration(proto, UidRecordProto.LAST_BACKGROUND_TIME,
419                 mLastBackgroundTime, SystemClock.elapsedRealtime());
420         proto.write(UidRecordProto.IDLE, mIdle);
421         if (mLastReportedChange != 0) {
422             ProtoUtils.writeBitWiseFlagsToProtoEnum(proto, UidRecordProto.LAST_REPORTED_CHANGES,
423                     mLastReportedChange, ORIG_ENUMS, PROTO_ENUMS);
424         }
425         proto.write(UidRecordProto.NUM_PROCS, mNumProcs);
426 
427         long seqToken = proto.start(UidRecordProto.NETWORK_STATE_UPDATE);
428         proto.write(UidRecordProto.ProcStateSequence.CURURENT, curProcStateSeq);
429         proto.write(UidRecordProto.ProcStateSequence.LAST_NETWORK_UPDATED,
430                 lastNetworkUpdatedProcStateSeq);
431         proto.end(seqToken);
432 
433         proto.end(token);
434     }
435 
toString()436     public String toString() {
437         StringBuilder sb = new StringBuilder(128);
438         sb.append("UidRecord{");
439         sb.append(Integer.toHexString(System.identityHashCode(this)));
440         sb.append(' ');
441         UserHandle.formatUid(sb, mUid);
442         sb.append(' ');
443         sb.append(ProcessList.makeProcStateString(mCurProcState));
444         if (mEphemeral) {
445             sb.append(" ephemeral");
446         }
447         if (mForegroundServices) {
448             sb.append(" fgServices");
449         }
450         if (mCurAllowList) {
451             sb.append(" allowlist");
452         }
453         if (mLastBackgroundTime > 0) {
454             sb.append(" bg:");
455             TimeUtils.formatDuration(SystemClock.elapsedRealtime() - mLastBackgroundTime, sb);
456         }
457         if (mIdle) {
458             sb.append(" idle");
459         }
460         if (mLastReportedChange != 0) {
461             sb.append(" change:");
462             boolean printed = false;
463             if ((mLastReportedChange & CHANGE_GONE) != 0) {
464                 printed = true;
465                 sb.append("gone");
466             }
467             if ((mLastReportedChange & CHANGE_IDLE) != 0) {
468                 if (printed) {
469                     sb.append("|");
470                 }
471                 printed = true;
472                 sb.append("idle");
473             }
474             if ((mLastReportedChange & CHANGE_ACTIVE) != 0) {
475                 if (printed) {
476                     sb.append("|");
477                 }
478                 printed = true;
479                 sb.append("active");
480             }
481             if ((mLastReportedChange & CHANGE_CACHED) != 0) {
482                 if (printed) {
483                     sb.append("|");
484                 }
485                 printed = true;
486                 sb.append("cached");
487             }
488             if ((mLastReportedChange & CHANGE_UNCACHED) != 0) {
489                 if (printed) {
490                     sb.append("|");
491                 }
492                 sb.append("uncached");
493             }
494             if ((mLastReportedChange & CHANGE_PROCSTATE) != 0) {
495                 if (printed) {
496                     sb.append("|");
497                 }
498                 sb.append("procstate");
499             }
500             if ((mLastReportedChange & CHANGE_PROCADJ) != 0) {
501                 if (printed) {
502                     sb.append("|");
503                 }
504                 sb.append("procadj");
505             }
506         }
507         sb.append(" procs:");
508         sb.append(mNumProcs);
509         sb.append(" seq(");
510         sb.append(curProcStateSeq);
511         sb.append(",");
512         sb.append(lastNetworkUpdatedProcStateSeq);
513         sb.append(")}");
514         sb.append(" caps=");
515         ActivityManager.printCapabilitiesSummary(sb, mCurCapability);
516         return sb.toString();
517     }
518 }
519