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