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