• 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 
getFlags()146     public long getFlags() {
147         return flags;
148     }
149 
hasFlag(final int flag)150     public boolean hasFlag(final int flag) {
151         return (flags & Integer.toUnsignedLong(flag)) != 0;
152     }
153 
hasFlag(final long flag)154     public boolean hasFlag(final long flag) {
155         return (flags & flag) != 0;
156     }
157 
notHasFlag(final int flag)158     public boolean notHasFlag(final int flag) {
159         return !hasFlag(flag);
160     }
161 
notHasFlag(final long flag)162     public boolean notHasFlag(final long flag) {
163         return !hasFlag(flag);
164     }
165 
startAssociationIfNeeded()166     public void startAssociationIfNeeded() {
167         // If we don't already have an active association, create one...  but only if this
168         // is an association between two different processes.
169         if (ActivityManagerService.TRACK_PROCSTATS_ASSOCIATIONS
170                 && association == null && binding.service.app != null
171                 && (binding.service.appInfo.uid != clientUid
172                         || !binding.service.processName.equals(clientProcessName))) {
173             ProcessStats.ProcessStateHolder holder = binding.service.app.getPkgList().get(
174                     binding.service.instanceName.getPackageName());
175             if (holder == null) {
176                 Slog.wtf(TAG_AM, "No package in referenced service "
177                         + binding.service.shortInstanceName + ": proc=" + binding.service.app);
178             } else if (holder.pkg == null) {
179                 Slog.wtf(TAG_AM, "Inactive holder in referenced service "
180                         + binding.service.shortInstanceName + ": proc=" + binding.service.app);
181             } else {
182                 mProcStatsLock = binding.service.app.mService.mProcessStats.mLock;
183                 synchronized (mProcStatsLock) {
184                     association = holder.pkg.getAssociationStateLocked(holder.state,
185                             binding.service.instanceName.getClassName()).startSource(clientUid,
186                             clientProcessName, clientPackageName);
187                 }
188             }
189         }
190     }
191 
trackProcState(int procState, int seq)192     public void trackProcState(int procState, int seq) {
193         if (association != null) {
194             synchronized (mProcStatsLock) {
195                 association.trackProcState(procState, seq, SystemClock.uptimeMillis());
196             }
197         }
198     }
199 
stopAssociation()200     public void stopAssociation() {
201         if (association != null) {
202             synchronized (mProcStatsLock) {
203                 association.stop();
204             }
205             association = null;
206         }
207     }
208 
toString()209     public String toString() {
210         if (stringName != null) {
211             return stringName;
212         }
213         StringBuilder sb = new StringBuilder(128);
214         sb.append("ConnectionRecord{");
215         sb.append(Integer.toHexString(System.identityHashCode(this)));
216         sb.append(" u");
217         sb.append(binding.client.userId);
218         sb.append(' ');
219         if (hasFlag(Context.BIND_AUTO_CREATE)) {
220             sb.append("CR ");
221         }
222         if (hasFlag(Context.BIND_DEBUG_UNBIND)) {
223             sb.append("DBG ");
224         }
225         if (hasFlag(Context.BIND_NOT_FOREGROUND)) {
226             sb.append("!FG ");
227         }
228         if (hasFlag(Context.BIND_IMPORTANT_BACKGROUND)) {
229             sb.append("IMPB ");
230         }
231         if (hasFlag(Context.BIND_ABOVE_CLIENT)) {
232             sb.append("ABCLT ");
233         }
234         if (hasFlag(Context.BIND_ALLOW_OOM_MANAGEMENT)) {
235             sb.append("OOM ");
236         }
237         if (hasFlag(Context.BIND_WAIVE_PRIORITY)) {
238             sb.append("WPRI ");
239         }
240         if (hasFlag(Context.BIND_IMPORTANT)) {
241             sb.append("IMP ");
242         }
243         if (hasFlag(Context.BIND_ADJUST_WITH_ACTIVITY)) {
244             sb.append("WACT ");
245         }
246         if (hasFlag(Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)) {
247             sb.append("FGSA ");
248         }
249         if (hasFlag(Context.BIND_FOREGROUND_SERVICE)) {
250             sb.append("FGS ");
251         }
252         if (hasFlag(Context.BIND_TREAT_LIKE_ACTIVITY)) {
253             sb.append("LACT ");
254         }
255         if (hasFlag(Context.BIND_SCHEDULE_LIKE_TOP_APP)) {
256             sb.append("SLTA ");
257         }
258         if (hasFlag(Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE)) {
259             sb.append("VFGS ");
260         }
261         if (hasFlag(Context.BIND_SHOWING_UI)) {
262             sb.append("UI ");
263         }
264         if (hasFlag(Context.BIND_NOT_VISIBLE)) {
265             sb.append("!VIS ");
266         }
267         if (hasFlag(Context.BIND_NOT_PERCEPTIBLE)) {
268             sb.append("!PRCP ");
269         }
270         if (hasFlag(Context.BIND_ALLOW_ACTIVITY_STARTS)) {
271             sb.append("BALF ");
272         }
273         if (hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
274             sb.append("CAPS ");
275         }
276         if (serviceDead) {
277             sb.append("DEAD ");
278         }
279         sb.append(binding.service.shortInstanceName);
280         sb.append(":@");
281         sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
282         sb.append(" flags=0x" + Long.toHexString(flags));
283         sb.append('}');
284         return stringName = sb.toString();
285     }
286 
dumpDebug(ProtoOutputStream proto, long fieldId)287     public void dumpDebug(ProtoOutputStream proto, long fieldId) {
288         if (binding == null) return; // if binding is null, don't write data, something is wrong.
289         long token = proto.start(fieldId);
290         proto.write(ConnectionRecordProto.HEX_HASH,
291                 Integer.toHexString(System.identityHashCode(this)));
292         if (binding.client != null) {
293             proto.write(ConnectionRecordProto.USER_ID, binding.client.userId);
294         }
295         ProtoUtils.writeBitWiseFlagsToProtoEnum(proto, ConnectionRecordProto.FLAGS,
296                 flags, BIND_ORIG_ENUMS, BIND_PROTO_ENUMS);
297         if (serviceDead) {
298             proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.DEAD);
299         }
300         if (binding.service != null) {
301             proto.write(ConnectionRecordProto.SERVICE_NAME, binding.service.shortInstanceName);
302         }
303         proto.end(token);
304     }
305 }
306