• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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.ActivityManagerDebugConfig.TAG_AM;
20 import static com.android.server.am.ProcessList.UNKNOWN_ADJ;
21 
22 import android.annotation.Nullable;
23 import android.app.IServiceConnection;
24 import android.app.PendingIntent;
25 import android.content.ComponentName;
26 import android.content.Context;
27 import android.os.SystemClock;
28 import android.util.Slog;
29 import android.util.proto.ProtoOutputStream;
30 import android.util.proto.ProtoUtils;
31 
32 import com.android.internal.app.procstats.AssociationState;
33 import com.android.internal.app.procstats.ProcessStats;
34 import com.android.server.wm.ActivityServiceConnectionsHolder;
35 
36 import java.io.PrintWriter;
37 
38 /**
39  * Description of a single binding to a service.
40  */
41 final class ConnectionRecord implements OomAdjusterModernImpl.Connection{
42     final AppBindRecord binding;    // The application/service binding.
43     final ActivityServiceConnectionsHolder<ConnectionRecord> activity;  // If non-null, the owning activity.
44     final IServiceConnection conn;  // The client connection.
45     private final long flags;                // Binding options.
46     final int clientLabel;          // String resource labeling this client.
47     final PendingIntent clientIntent; // How to launch the client.
48     final int clientUid;            // The identity of this connection's client
49     final String clientProcessName; // The source process of this connection's client
50     final String clientPackageName; // The source package of this connection's client
51     public AssociationState.SourceState association; // Association tracking
52     String stringName;              // Caching of toString.
53     boolean serviceDead;            // Well is it?
54     private Object mProcStatsLock;  // Internal lock for accessing AssociationState
55     /**
56      * If the connection was made against an alias, then the alias conponent name. Otherwise, null.
57      * We return this component name to the client.
58      */
59     @Nullable
60     final ComponentName aliasComponent;
61 
62     // Please keep the following two enum list synced.
63     private static final int[] BIND_ORIG_ENUMS = new int[] {
64             Context.BIND_AUTO_CREATE,
65             Context.BIND_DEBUG_UNBIND,
66             Context.BIND_NOT_FOREGROUND,
67             Context.BIND_IMPORTANT_BACKGROUND,
68             Context.BIND_ABOVE_CLIENT,
69             Context.BIND_ALLOW_OOM_MANAGEMENT,
70             Context.BIND_WAIVE_PRIORITY,
71             Context.BIND_IMPORTANT,
72             Context.BIND_ADJUST_WITH_ACTIVITY,
73             Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
74             Context.BIND_FOREGROUND_SERVICE,
75             Context.BIND_TREAT_LIKE_ACTIVITY,
76             Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE,
77             Context.BIND_SHOWING_UI,
78             Context.BIND_NOT_VISIBLE,
79             Context.BIND_NOT_PERCEPTIBLE,
80             Context.BIND_INCLUDE_CAPABILITIES,
81             Context.BIND_ALLOW_ACTIVITY_STARTS,
82     };
83     private static final int[] BIND_PROTO_ENUMS = new int[] {
84             ConnectionRecordProto.AUTO_CREATE,
85             ConnectionRecordProto.DEBUG_UNBIND,
86             ConnectionRecordProto.NOT_FG,
87             ConnectionRecordProto.IMPORTANT_BG,
88             ConnectionRecordProto.ABOVE_CLIENT,
89             ConnectionRecordProto.ALLOW_OOM_MANAGEMENT,
90             ConnectionRecordProto.WAIVE_PRIORITY,
91             ConnectionRecordProto.IMPORTANT,
92             ConnectionRecordProto.ADJUST_WITH_ACTIVITY,
93             ConnectionRecordProto.FG_SERVICE_WHILE_AWAKE,
94             ConnectionRecordProto.FG_SERVICE,
95             ConnectionRecordProto.TREAT_LIKE_ACTIVITY,
96             ConnectionRecordProto.VISIBLE,
97             ConnectionRecordProto.SHOWING_UI,
98             ConnectionRecordProto.NOT_VISIBLE,
99             ConnectionRecordProto.NOT_PERCEPTIBLE,
100             ConnectionRecordProto.INCLUDE_CAPABILITIES,
101             ConnectionRecordProto.ALLOW_ACTIVITY_STARTS,
102     };
103 
dump(PrintWriter pw, String prefix)104     void dump(PrintWriter pw, String prefix) {
105         pw.println(prefix + "binding=" + binding);
106         if (activity != null) {
107             activity.dump(pw, prefix);
108         }
109         pw.println(prefix + "conn=" + conn.asBinder()
110                 + " flags=0x" + Long.toHexString(flags));
111     }
112 
ConnectionRecord(AppBindRecord _binding, ActivityServiceConnectionsHolder<ConnectionRecord> _activity, IServiceConnection _conn, long _flags, int _clientLabel, PendingIntent _clientIntent, int _clientUid, String _clientProcessName, String _clientPackageName, ComponentName _aliasComponent)113     ConnectionRecord(AppBindRecord _binding,
114             ActivityServiceConnectionsHolder<ConnectionRecord> _activity,
115             IServiceConnection _conn, long _flags,
116             int _clientLabel, PendingIntent _clientIntent,
117             int _clientUid, String _clientProcessName, String _clientPackageName,
118             ComponentName _aliasComponent) {
119         binding = _binding;
120         activity = _activity;
121         conn = _conn;
122         flags = _flags;
123         clientLabel = _clientLabel;
124         clientIntent = _clientIntent;
125         clientUid = _clientUid;
126         clientProcessName = _clientProcessName;
127         clientPackageName = _clientPackageName;
128         aliasComponent = _aliasComponent;
129     }
130 
131     @Override
computeHostOomAdjLSP(OomAdjuster oomAdjuster, ProcessRecord host, ProcessRecord client, long now, ProcessRecord topApp, boolean doingAll, int oomAdjReason, int cachedAdj)132     public void computeHostOomAdjLSP(OomAdjuster oomAdjuster, ProcessRecord host,
133             ProcessRecord client, long now, ProcessRecord topApp, boolean doingAll,
134             int oomAdjReason, int cachedAdj) {
135         oomAdjuster.computeServiceHostOomAdjLSP(this, host, client, now, topApp, doingAll, false,
136                 false, oomAdjReason, UNKNOWN_ADJ, false, false);
137     }
138 
139     @Override
canAffectCapabilities()140     public boolean canAffectCapabilities() {
141         return hasFlag(Context.BIND_INCLUDE_CAPABILITIES
142                 | Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS);
143     }
144 
145     @Override
transmitsCpuTime()146     public boolean transmitsCpuTime() {
147         return !hasFlag(Context.BIND_ALLOW_FREEZE);
148     }
149 
getFlags()150     public long getFlags() {
151         return flags;
152     }
153 
hasFlag(final int flag)154     public boolean hasFlag(final int flag) {
155         return (flags & Integer.toUnsignedLong(flag)) != 0;
156     }
157 
hasFlag(final long flag)158     public boolean hasFlag(final long flag) {
159         return (flags & flag) != 0;
160     }
161 
notHasFlag(final int flag)162     public boolean notHasFlag(final int flag) {
163         return !hasFlag(flag);
164     }
165 
notHasFlag(final long flag)166     public boolean notHasFlag(final long flag) {
167         return !hasFlag(flag);
168     }
169 
startAssociationIfNeeded()170     public void startAssociationIfNeeded() {
171         // If we don't already have an active association, create one...  but only if this
172         // is an association between two different processes.
173         if (ActivityManagerService.TRACK_PROCSTATS_ASSOCIATIONS
174                 && association == null && binding.service.app != null
175                 && (binding.service.appInfo.uid != clientUid
176                         || !binding.service.processName.equals(clientProcessName))) {
177             ProcessStats.ProcessStateHolder holder = binding.service.app.getPkgList().get(
178                     binding.service.instanceName.getPackageName());
179             if (holder == null) {
180                 Slog.wtf(TAG_AM, "No package in referenced service "
181                         + binding.service.shortInstanceName + ": proc=" + binding.service.app);
182             } else if (holder.pkg == null) {
183                 Slog.wtf(TAG_AM, "Inactive holder in referenced service "
184                         + binding.service.shortInstanceName + ": proc=" + binding.service.app);
185             } else {
186                 mProcStatsLock = binding.service.app.mService.mProcessStats.mLock;
187                 synchronized (mProcStatsLock) {
188                     association = holder.pkg.getAssociationStateLocked(holder.state,
189                             binding.service.instanceName.getClassName()).startSource(clientUid,
190                             clientProcessName, clientPackageName);
191                 }
192             }
193         }
194     }
195 
trackProcState(int procState, int seq)196     public void trackProcState(int procState, int seq) {
197         if (association != null) {
198             synchronized (mProcStatsLock) {
199                 association.trackProcState(procState, seq, SystemClock.uptimeMillis());
200             }
201         }
202     }
203 
stopAssociation()204     public void stopAssociation() {
205         if (association != null) {
206             synchronized (mProcStatsLock) {
207                 association.stop();
208             }
209             association = null;
210         }
211     }
212 
toString()213     public String toString() {
214         if (stringName != null) {
215             return stringName;
216         }
217         StringBuilder sb = new StringBuilder(128);
218         sb.append("ConnectionRecord{");
219         sb.append(Integer.toHexString(System.identityHashCode(this)));
220         sb.append(" u");
221         sb.append(binding.client.userId);
222         sb.append(' ');
223         if (hasFlag(Context.BIND_AUTO_CREATE)) {
224             sb.append("CR ");
225         }
226         if (hasFlag(Context.BIND_DEBUG_UNBIND)) {
227             sb.append("DBG ");
228         }
229         if (hasFlag(Context.BIND_NOT_FOREGROUND)) {
230             sb.append("!FG ");
231         }
232         if (hasFlag(Context.BIND_IMPORTANT_BACKGROUND)) {
233             sb.append("IMPB ");
234         }
235         if (hasFlag(Context.BIND_ABOVE_CLIENT)) {
236             sb.append("ABCLT ");
237         }
238         if (hasFlag(Context.BIND_ALLOW_OOM_MANAGEMENT)) {
239             sb.append("OOM ");
240         }
241         if (hasFlag(Context.BIND_WAIVE_PRIORITY)) {
242             sb.append("WPRI ");
243         }
244         if (hasFlag(Context.BIND_IMPORTANT)) {
245             sb.append("IMP ");
246         }
247         if (hasFlag(Context.BIND_ADJUST_WITH_ACTIVITY)) {
248             sb.append("WACT ");
249         }
250         if (hasFlag(Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)) {
251             sb.append("FGSA ");
252         }
253         if (hasFlag(Context.BIND_FOREGROUND_SERVICE)) {
254             sb.append("FGS ");
255         }
256         if (hasFlag(Context.BIND_TREAT_LIKE_ACTIVITY)) {
257             sb.append("LACT ");
258         }
259         if (hasFlag(Context.BIND_SCHEDULE_LIKE_TOP_APP)) {
260             sb.append("SLTA ");
261         }
262         if (hasFlag(Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE)) {
263             sb.append("VFGS ");
264         }
265         if (hasFlag(Context.BIND_SHOWING_UI)) {
266             sb.append("UI ");
267         }
268         if (hasFlag(Context.BIND_NOT_VISIBLE)) {
269             sb.append("!VIS ");
270         }
271         if (hasFlag(Context.BIND_NOT_PERCEPTIBLE)) {
272             sb.append("!PRCP ");
273         }
274         if (hasFlag(Context.BIND_ALLOW_ACTIVITY_STARTS)) {
275             sb.append("BALF ");
276         }
277         if (hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
278             sb.append("CAPS ");
279         }
280         if (hasFlag(Context.BIND_ALLOW_FREEZE)) {
281             sb.append("!CPU ");
282         }
283         if (serviceDead) {
284             sb.append("DEAD ");
285         }
286         sb.append(binding.service.shortInstanceName);
287         sb.append(":@");
288         sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
289         sb.append(" flags=0x" + Long.toHexString(flags));
290         sb.append('}');
291         return stringName = sb.toString();
292     }
293 
dumpDebug(ProtoOutputStream proto, long fieldId)294     public void dumpDebug(ProtoOutputStream proto, long fieldId) {
295         if (binding == null) return; // if binding is null, don't write data, something is wrong.
296         long token = proto.start(fieldId);
297         proto.write(ConnectionRecordProto.HEX_HASH,
298                 Integer.toHexString(System.identityHashCode(this)));
299         if (binding.client != null) {
300             proto.write(ConnectionRecordProto.USER_ID, binding.client.userId);
301         }
302         ProtoUtils.writeBitWiseFlagsToProtoEnum(proto, ConnectionRecordProto.FLAGS,
303                 flags, BIND_ORIG_ENUMS, BIND_PROTO_ENUMS);
304         if (serviceDead) {
305             proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.DEAD);
306         }
307         if (binding.service != null) {
308             proto.write(ConnectionRecordProto.SERVICE_NAME, binding.service.shortInstanceName);
309         }
310         proto.end(token);
311     }
312 }
313