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