• 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.app.ActivityManagerProto;
22 import android.content.pm.PackageManager;
23 import android.os.SystemClock;
24 import android.os.UserHandle;
25 import android.util.TimeUtils;
26 import android.util.proto.ProtoOutputStream;
27 import android.util.proto.ProtoUtils;
28 
29 import com.android.internal.annotations.GuardedBy;
30 import com.android.internal.annotations.VisibleForTesting;
31 
32 /**
33  * Overall information about a uid that has actively running processes.
34  */
35 public final class UidRecord {
36     final int uid;
37     int curProcState;
38     int setProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
39     long lastBackgroundTime;
40     boolean ephemeral;
41     boolean foregroundServices;
42     boolean curWhitelist;
43     boolean setWhitelist;
44     boolean idle;
45     boolean setIdle;
46     int numProcs;
47 
48     /**
49      * Sequence number associated with the {@link #curProcState}. This is incremented using
50      * {@link ActivityManagerService#mProcStateSeqCounter}
51      * when {@link #curProcState} changes from background to foreground or vice versa.
52      */
53     @GuardedBy("networkStateUpdate")
54     long curProcStateSeq;
55 
56     /**
57      * Last seq number for which NetworkPolicyManagerService notified ActivityManagerService that
58      * network policies rules were updated.
59      */
60     @GuardedBy("networkStateUpdate")
61     long lastNetworkUpdatedProcStateSeq;
62 
63     /**
64      * Last seq number for which AcitivityManagerService dispatched uid state change to
65      * NetworkPolicyManagerService.
66      */
67     @GuardedBy("networkStateUpdate")
68     long lastDispatchedProcStateSeq;
69 
70     /**
71      * Indicates if any thread is waiting for network rules to get updated for {@link #uid}.
72      */
73     volatile boolean waitingForNetwork;
74 
75     /**
76      * Indicates whether this uid has internet permission or not.
77      */
78     volatile boolean hasInternetPermission;
79 
80     /**
81      * This object is used for waiting for the network state to get updated.
82      */
83     final Object networkStateLock = new Object();
84 
85     static final int CHANGE_PROCSTATE = 0;
86     static final int CHANGE_GONE = 1<<0;
87     static final int CHANGE_IDLE = 1<<1;
88     static final int CHANGE_ACTIVE = 1<<2;
89     static final int CHANGE_CACHED = 1<<3;
90     static final int CHANGE_UNCACHED = 1<<4;
91 
92     // Keep the enum lists in sync
93     private static int[] ORIG_ENUMS = new int[] {
94             CHANGE_GONE,
95             CHANGE_IDLE,
96             CHANGE_ACTIVE,
97             CHANGE_CACHED,
98             CHANGE_UNCACHED,
99     };
100     private static int[] PROTO_ENUMS = new int[] {
101             UidRecordProto.CHANGE_GONE,
102             UidRecordProto.CHANGE_IDLE,
103             UidRecordProto.CHANGE_ACTIVE,
104             UidRecordProto.CHANGE_CACHED,
105             UidRecordProto.CHANGE_UNCACHED,
106     };
107 
108     static final class ChangeItem {
109         UidRecord uidRecord;
110         int uid;
111         int change;
112         int processState;
113         boolean ephemeral;
114         long procStateSeq;
115     }
116 
117     ChangeItem pendingChange;
118     int lastReportedChange;
119 
UidRecord(int _uid)120     public UidRecord(int _uid) {
121         uid = _uid;
122         idle = true;
123         reset();
124     }
125 
reset()126     public void reset() {
127         curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
128         foregroundServices = false;
129     }
130 
updateHasInternetPermission()131     public void updateHasInternetPermission() {
132         hasInternetPermission = ActivityManager.checkUidPermission(Manifest.permission.INTERNET,
133                 uid) == PackageManager.PERMISSION_GRANTED;
134     }
135 
136     /**
137      * If the change being dispatched is not CHANGE_GONE (not interested in
138      * these changes), then update the {@link #lastDispatchedProcStateSeq} with
139      * {@link #curProcStateSeq}.
140      */
updateLastDispatchedProcStateSeq(int changeToDispatch)141     public void updateLastDispatchedProcStateSeq(int changeToDispatch) {
142         if ((changeToDispatch & CHANGE_GONE) == 0) {
143             lastDispatchedProcStateSeq = curProcStateSeq;
144         }
145     }
146 
147 
writeToProto(ProtoOutputStream proto, long fieldId)148     void writeToProto(ProtoOutputStream proto, long fieldId) {
149         long token = proto.start(fieldId);
150         proto.write(UidRecordProto.UID, uid);
151         proto.write(UidRecordProto.CURRENT, ProcessList.makeProcStateProtoEnum(curProcState));
152         proto.write(UidRecordProto.EPHEMERAL, ephemeral);
153         proto.write(UidRecordProto.FG_SERVICES, foregroundServices);
154         proto.write(UidRecordProto.WHILELIST, curWhitelist);
155         ProtoUtils.toDuration(proto, UidRecordProto.LAST_BACKGROUND_TIME,
156                 lastBackgroundTime, SystemClock.elapsedRealtime());
157         proto.write(UidRecordProto.IDLE, idle);
158         if (lastReportedChange != 0) {
159             ProtoUtils.writeBitWiseFlagsToProtoEnum(proto, UidRecordProto.LAST_REPORTED_CHANGES,
160                     lastReportedChange, ORIG_ENUMS, PROTO_ENUMS);
161         }
162         proto.write(UidRecordProto.NUM_PROCS, numProcs);
163 
164         long seqToken = proto.start(UidRecordProto.NETWORK_STATE_UPDATE);
165         proto.write(UidRecordProto.ProcStateSequence.CURURENT, curProcStateSeq);
166         proto.write(UidRecordProto.ProcStateSequence.LAST_NETWORK_UPDATED,
167                 lastNetworkUpdatedProcStateSeq);
168         proto.write(UidRecordProto.ProcStateSequence.LAST_DISPATCHED, lastDispatchedProcStateSeq);
169         proto.end(seqToken);
170 
171         proto.end(token);
172     }
173 
toString()174     public String toString() {
175         StringBuilder sb = new StringBuilder(128);
176         sb.append("UidRecord{");
177         sb.append(Integer.toHexString(System.identityHashCode(this)));
178         sb.append(' ');
179         UserHandle.formatUid(sb, uid);
180         sb.append(' ');
181         sb.append(ProcessList.makeProcStateString(curProcState));
182         if (ephemeral) {
183             sb.append(" ephemeral");
184         }
185         if (foregroundServices) {
186             sb.append(" fgServices");
187         }
188         if (curWhitelist) {
189             sb.append(" whitelist");
190         }
191         if (lastBackgroundTime > 0) {
192             sb.append(" bg:");
193             TimeUtils.formatDuration(SystemClock.elapsedRealtime()-lastBackgroundTime, sb);
194         }
195         if (idle) {
196             sb.append(" idle");
197         }
198         if (lastReportedChange != 0) {
199             sb.append(" change:");
200             boolean printed = false;
201             if ((lastReportedChange & CHANGE_GONE) != 0) {
202                 printed = true;
203                 sb.append("gone");
204             }
205             if ((lastReportedChange & CHANGE_IDLE) != 0) {
206                 if (printed) {
207                     sb.append("|");
208                 }
209                 printed = true;
210                 sb.append("idle");
211             }
212             if ((lastReportedChange & CHANGE_ACTIVE) != 0) {
213                 if (printed) {
214                     sb.append("|");
215                 }
216                 printed = true;
217                 sb.append("active");
218             }
219             if ((lastReportedChange & CHANGE_CACHED) != 0) {
220                 if (printed) {
221                     sb.append("|");
222                 }
223                 printed = true;
224                 sb.append("cached");
225             }
226             if ((lastReportedChange & CHANGE_UNCACHED) != 0) {
227                 if (printed) {
228                     sb.append("|");
229                 }
230                 sb.append("uncached");
231             }
232         }
233         sb.append(" procs:");
234         sb.append(numProcs);
235         sb.append(" seq(");
236         sb.append(curProcStateSeq);
237         sb.append(",");
238         sb.append(lastNetworkUpdatedProcStateSeq);
239         sb.append(",");
240         sb.append(lastDispatchedProcStateSeq);
241         sb.append(")}");
242         return sb.toString();
243     }
244 }
245