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