• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.util.ArraySet;
25 import android.util.TimeUtils;
26 import android.util.proto.ProtoOutputStream;
27 import android.util.proto.ProtoUtils;
28 
29 import com.android.internal.annotations.CompositeRWLock;
30 import com.android.internal.annotations.GuardedBy;
31 import com.android.server.am.UidObserverController.ChangeRecord;
32 
33 import java.util.function.Consumer;
34 
35 /**
36  * Overall information about a uid that has actively running processes.
37  */
38 public final class UidRecord {
39     private final ActivityManagerService mService;
40     private final ActivityManagerGlobalLock mProcLock;
41     private final int mUid;
42 
43     @CompositeRWLock({"mService", "mProcLock"})
44     private int mCurProcState;
45 
46     @CompositeRWLock({"mService", "mProcLock"})
47     private int mSetProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
48 
49     @CompositeRWLock({"mService", "mProcLock"})
50     private int mCurCapability;
51 
52     @CompositeRWLock({"mService", "mProcLock"})
53     private int mSetCapability;
54 
55     @CompositeRWLock({"mService", "mProcLock"})
56     private long mLastBackgroundTime;
57 
58     @CompositeRWLock({"mService", "mProcLock"})
59     private boolean mEphemeral;
60 
61     @CompositeRWLock({"mService", "mProcLock"})
62     private boolean mForegroundServices;
63 
64     @CompositeRWLock({"mService", "mProcLock"})
65     private boolean mCurAllowList;;
66 
67     @CompositeRWLock({"mService", "mProcLock"})
68     private boolean mSetAllowList;
69 
70     @CompositeRWLock({"mService", "mProcLock"})
71     private boolean mIdle;
72 
73     @CompositeRWLock({"mService", "mProcLock"})
74     private boolean mSetIdle;
75 
76     @CompositeRWLock({"mService", "mProcLock"})
77     private int mNumProcs;
78 
79     @CompositeRWLock({"mService", "mProcLock"})
80     private ArraySet<ProcessRecord> mProcRecords = new ArraySet<>();
81 
82     /**
83      * Sequence number associated with the {@link #mCurProcState}. This is incremented using
84      * {@link ActivityManagerService#mProcStateSeqCounter}
85      * when {@link #mCurProcState} changes from background to foreground or vice versa.
86      */
87     @GuardedBy("networkStateUpdate")
88     long curProcStateSeq;
89 
90     /**
91      * Last seq number for which NetworkPolicyManagerService notified ActivityManagerService that
92      * network policies rules were updated.
93      */
94     @GuardedBy("networkStateUpdate")
95     long lastNetworkUpdatedProcStateSeq;
96 
97     /**
98      * Last seq number for which AcitivityManagerService dispatched uid state change to
99      * NetworkPolicyManagerService.
100      */
101     @GuardedBy("networkStateUpdate")
102     long lastDispatchedProcStateSeq;
103 
104     /**
105      * Indicates if any thread is waiting for network rules to get updated for {@link #uid}.
106      */
107     volatile boolean waitingForNetwork;
108 
109     /**
110      * Indicates whether this uid has internet permission or not.
111      */
112     volatile boolean hasInternetPermission;
113 
114     /**
115      * This object is used for waiting for the network state to get updated.
116      */
117     final Object networkStateLock = new Object();
118 
119     static final int CHANGE_PROCSTATE = 0;
120     static final int CHANGE_GONE = 1<<0;
121     static final int CHANGE_IDLE = 1<<1;
122     static final int CHANGE_ACTIVE = 1<<2;
123     static final int CHANGE_CACHED = 1<<3;
124     static final int CHANGE_UNCACHED = 1<<4;
125     static final int CHANGE_CAPABILITY = 1<<5;
126 
127     // Keep the enum lists in sync
128     private static int[] ORIG_ENUMS = new int[] {
129             CHANGE_GONE,
130             CHANGE_IDLE,
131             CHANGE_ACTIVE,
132             CHANGE_CACHED,
133             CHANGE_UNCACHED,
134             CHANGE_CAPABILITY,
135     };
136     private static int[] PROTO_ENUMS = new int[] {
137             UidRecordProto.CHANGE_GONE,
138             UidRecordProto.CHANGE_IDLE,
139             UidRecordProto.CHANGE_ACTIVE,
140             UidRecordProto.CHANGE_CACHED,
141             UidRecordProto.CHANGE_UNCACHED,
142             UidRecordProto.CHANGE_CAPABILITY,
143     };
144 
145     // UidObserverController is the only thing that should modify this.
146     final ChangeRecord pendingChange = new ChangeRecord();
147 
148     @GuardedBy("mService")
149     private int mLastReportedChange;
150 
UidRecord(int uid, ActivityManagerService service)151     public UidRecord(int uid, ActivityManagerService service) {
152         mUid = uid;
153         mService = service;
154         mProcLock = service != null ? service.mProcLock : null;
155         mIdle = true;
156         reset();
157     }
158 
getUid()159     int getUid() {
160         return mUid;
161     }
162 
163     @GuardedBy(anyOf = {"mService", "mProcLock"})
getCurProcState()164     int getCurProcState() {
165         return mCurProcState;
166     }
167 
168     @GuardedBy({"mService", "mProcLock"})
setCurProcState(int curProcState)169     void setCurProcState(int curProcState) {
170         mCurProcState = curProcState;
171     }
172 
173     @GuardedBy(anyOf = {"mService", "mProcLock"})
getSetProcState()174     int getSetProcState() {
175         return mSetProcState;
176     }
177 
178     @GuardedBy({"mService", "mProcLock"})
setSetProcState(int setProcState)179     void setSetProcState(int setProcState) {
180         mSetProcState = setProcState;
181     }
182 
183     @GuardedBy(anyOf = {"mService", "mProcLock"})
getCurCapability()184     int getCurCapability() {
185         return mCurCapability;
186     }
187 
188     @GuardedBy({"mService", "mProcLock"})
setCurCapability(int curCapability)189     void setCurCapability(int curCapability) {
190         mCurCapability = curCapability;
191     }
192 
193     @GuardedBy(anyOf = {"mService", "mProcLock"})
getSetCapability()194     int getSetCapability() {
195         return mSetCapability;
196     }
197 
198     @GuardedBy({"mService", "mProcLock"})
setSetCapability(int setCapability)199     void setSetCapability(int setCapability) {
200         mSetCapability = setCapability;
201     }
202 
203     @GuardedBy(anyOf = {"mService", "mProcLock"})
getLastBackgroundTime()204     long getLastBackgroundTime() {
205         return mLastBackgroundTime;
206     }
207 
208     @GuardedBy({"mService", "mProcLock"})
setLastBackgroundTime(long lastBackgroundTime)209     void setLastBackgroundTime(long lastBackgroundTime) {
210         mLastBackgroundTime = lastBackgroundTime;
211     }
212 
213     @GuardedBy(anyOf = {"mService", "mProcLock"})
isEphemeral()214     boolean isEphemeral() {
215         return mEphemeral;
216     }
217 
218     @GuardedBy({"mService", "mProcLock"})
setEphemeral(boolean ephemeral)219     void setEphemeral(boolean ephemeral) {
220         mEphemeral = ephemeral;
221     }
222 
223     @GuardedBy(anyOf = {"mService", "mProcLock"})
hasForegroundServices()224     boolean hasForegroundServices() {
225         return mForegroundServices;
226     }
227 
228     @GuardedBy({"mService", "mProcLock"})
setForegroundServices(boolean foregroundServices)229     void setForegroundServices(boolean foregroundServices) {
230         mForegroundServices = foregroundServices;
231     }
232 
233     @GuardedBy(anyOf = {"mService", "mProcLock"})
isCurAllowListed()234     boolean isCurAllowListed() {
235         return mCurAllowList;
236     }
237 
238     @GuardedBy({"mService", "mProcLock"})
setCurAllowListed(boolean curAllowList)239     void setCurAllowListed(boolean curAllowList) {
240         mCurAllowList = curAllowList;
241     }
242 
243     @GuardedBy(anyOf = {"mService", "mProcLock"})
isSetAllowListed()244     boolean isSetAllowListed() {
245         return mSetAllowList;
246     }
247 
248     @GuardedBy({"mService", "mProcLock"})
setSetAllowListed(boolean setAllowlist)249     void setSetAllowListed(boolean setAllowlist) {
250         mSetAllowList = setAllowlist;
251     }
252 
253     @GuardedBy(anyOf = {"mService", "mProcLock"})
isIdle()254     boolean isIdle() {
255         return mIdle;
256     }
257 
258     @GuardedBy({"mService", "mProcLock"})
setIdle(boolean idle)259     void setIdle(boolean idle) {
260         mIdle = idle;
261     }
262 
263     @GuardedBy(anyOf = {"mService", "mProcLock"})
isSetIdle()264     boolean isSetIdle() {
265         return mSetIdle;
266     }
267 
268     @GuardedBy({"mService", "mProcLock"})
setSetIdle(boolean setIdle)269     void setSetIdle(boolean setIdle) {
270         mSetIdle = setIdle;
271     }
272 
273     @GuardedBy(anyOf = {"mService", "mProcLock"})
getNumOfProcs()274     int getNumOfProcs() {
275         return mProcRecords.size();
276     }
277 
278     @GuardedBy(anyOf = {"mService", "mProcLock"})
forEachProcess(Consumer<ProcessRecord> callback)279     void forEachProcess(Consumer<ProcessRecord> callback) {
280         for (int i = mProcRecords.size() - 1; i >= 0; i--) {
281             callback.accept(mProcRecords.valueAt(i));
282         }
283     }
284 
285     @GuardedBy({"mService", "mProcLock"})
addProcess(ProcessRecord app)286     void addProcess(ProcessRecord app) {
287         mProcRecords.add(app);
288     }
289 
290     @GuardedBy({"mService", "mProcLock"})
removeProcess(ProcessRecord app)291     void removeProcess(ProcessRecord app) {
292         mProcRecords.remove(app);
293     }
294 
295     @GuardedBy("mService")
setLastReportedChange(int lastReportedChange)296     void setLastReportedChange(int lastReportedChange) {
297         mLastReportedChange = lastReportedChange;
298     }
299 
300     @GuardedBy({"mService", "mProcLock"})
reset()301     void reset() {
302         setCurProcState(ActivityManager.PROCESS_STATE_CACHED_EMPTY);
303         mForegroundServices = false;
304         mCurCapability = 0;
305     }
306 
updateHasInternetPermission()307     public void updateHasInternetPermission() {
308         hasInternetPermission = ActivityManager.checkUidPermission(Manifest.permission.INTERNET,
309                 mUid) == PackageManager.PERMISSION_GRANTED;
310     }
311 
312     /**
313      * If the change being dispatched is not CHANGE_GONE (not interested in
314      * these changes), then update the {@link #lastDispatchedProcStateSeq} with
315      * {@link #curProcStateSeq}.
316      */
updateLastDispatchedProcStateSeq(int changeToDispatch)317     public void updateLastDispatchedProcStateSeq(int changeToDispatch) {
318         if ((changeToDispatch & CHANGE_GONE) == 0) {
319             lastDispatchedProcStateSeq = curProcStateSeq;
320         }
321     }
322 
323 
dumpDebug(ProtoOutputStream proto, long fieldId)324     void dumpDebug(ProtoOutputStream proto, long fieldId) {
325         long token = proto.start(fieldId);
326         proto.write(UidRecordProto.UID, mUid);
327         proto.write(UidRecordProto.CURRENT, ProcessList.makeProcStateProtoEnum(mCurProcState));
328         proto.write(UidRecordProto.EPHEMERAL, mEphemeral);
329         proto.write(UidRecordProto.FG_SERVICES, mForegroundServices);
330         proto.write(UidRecordProto.WHILELIST, mCurAllowList);
331         ProtoUtils.toDuration(proto, UidRecordProto.LAST_BACKGROUND_TIME,
332                 mLastBackgroundTime, SystemClock.elapsedRealtime());
333         proto.write(UidRecordProto.IDLE, mIdle);
334         if (mLastReportedChange != 0) {
335             ProtoUtils.writeBitWiseFlagsToProtoEnum(proto, UidRecordProto.LAST_REPORTED_CHANGES,
336                     mLastReportedChange, ORIG_ENUMS, PROTO_ENUMS);
337         }
338         proto.write(UidRecordProto.NUM_PROCS, mNumProcs);
339 
340         long seqToken = proto.start(UidRecordProto.NETWORK_STATE_UPDATE);
341         proto.write(UidRecordProto.ProcStateSequence.CURURENT, curProcStateSeq);
342         proto.write(UidRecordProto.ProcStateSequence.LAST_NETWORK_UPDATED,
343                 lastNetworkUpdatedProcStateSeq);
344         proto.write(UidRecordProto.ProcStateSequence.LAST_DISPATCHED, lastDispatchedProcStateSeq);
345         proto.end(seqToken);
346 
347         proto.end(token);
348     }
349 
toString()350     public String toString() {
351         StringBuilder sb = new StringBuilder(128);
352         sb.append("UidRecord{");
353         sb.append(Integer.toHexString(System.identityHashCode(this)));
354         sb.append(' ');
355         UserHandle.formatUid(sb, mUid);
356         sb.append(' ');
357         sb.append(ProcessList.makeProcStateString(mCurProcState));
358         if (mEphemeral) {
359             sb.append(" ephemeral");
360         }
361         if (mForegroundServices) {
362             sb.append(" fgServices");
363         }
364         if (mCurAllowList) {
365             sb.append(" allowlist");
366         }
367         if (mLastBackgroundTime > 0) {
368             sb.append(" bg:");
369             TimeUtils.formatDuration(SystemClock.elapsedRealtime() - mLastBackgroundTime, sb);
370         }
371         if (mIdle) {
372             sb.append(" idle");
373         }
374         if (mLastReportedChange != 0) {
375             sb.append(" change:");
376             boolean printed = false;
377             if ((mLastReportedChange & CHANGE_GONE) != 0) {
378                 printed = true;
379                 sb.append("gone");
380             }
381             if ((mLastReportedChange & CHANGE_IDLE) != 0) {
382                 if (printed) {
383                     sb.append("|");
384                 }
385                 printed = true;
386                 sb.append("idle");
387             }
388             if ((mLastReportedChange & CHANGE_ACTIVE) != 0) {
389                 if (printed) {
390                     sb.append("|");
391                 }
392                 printed = true;
393                 sb.append("active");
394             }
395             if ((mLastReportedChange & CHANGE_CACHED) != 0) {
396                 if (printed) {
397                     sb.append("|");
398                 }
399                 printed = true;
400                 sb.append("cached");
401             }
402             if ((mLastReportedChange & CHANGE_UNCACHED) != 0) {
403                 if (printed) {
404                     sb.append("|");
405                 }
406                 sb.append("uncached");
407             }
408         }
409         sb.append(" procs:");
410         sb.append(mNumProcs);
411         sb.append(" seq(");
412         sb.append(curProcStateSeq);
413         sb.append(",");
414         sb.append(lastNetworkUpdatedProcStateSeq);
415         sb.append(",");
416         sb.append(lastDispatchedProcStateSeq);
417         sb.append(")}");
418         return sb.toString();
419     }
420 }
421