1 /* 2 * Copyright (C) 2012 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.DEBUG_PROVIDER; 20 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 21 import static com.android.server.am.ProcessList.UNKNOWN_ADJ; 22 23 import android.annotation.UserIdInt; 24 import android.os.Binder; 25 import android.os.SystemClock; 26 import android.util.Slog; 27 import android.util.TimeUtils; 28 29 import com.android.internal.annotations.GuardedBy; 30 import com.android.internal.app.procstats.AssociationState; 31 import com.android.internal.app.procstats.ProcessStats; 32 33 /** 34 * Represents a link between a content provider and client. 35 */ 36 public final class ContentProviderConnection extends Binder implements 37 OomAdjusterModernImpl.Connection { 38 public final ContentProviderRecord provider; 39 public final ProcessRecord client; 40 public final String clientPackage; 41 public AssociationState.SourceState association; 42 public final long createTime; 43 private volatile Object mProcStatsLock; // Internal lock for accessing AssociationState 44 45 /** 46 * Internal lock that guards access to the two counters. 47 */ 48 private final Object mLock = new Object(); 49 @GuardedBy("mLock") 50 private int mStableCount; 51 @GuardedBy("mLock") 52 private int mUnstableCount; 53 // The client of this connection is currently waiting for the provider to appear. 54 // Protected by the provider lock. 55 public boolean waiting; 56 // The provider of this connection is now dead. 57 public boolean dead; 58 59 // The original user id when this connection was requested, it could be different from 60 // the client's user id because the client could request to access a content provider 61 // living in a different user if it has the permission. 62 @UserIdInt final int mExpectedUserId; 63 64 // For debugging. 65 private int mNumStableIncs; 66 private int mNumUnstableIncs; 67 ContentProviderConnection(ContentProviderRecord _provider, ProcessRecord _client, String _clientPackage, @UserIdInt int _expectedUserId)68 public ContentProviderConnection(ContentProviderRecord _provider, ProcessRecord _client, 69 String _clientPackage, @UserIdInt int _expectedUserId) { 70 provider = _provider; 71 client = _client; 72 clientPackage = _clientPackage; 73 mExpectedUserId = _expectedUserId; 74 createTime = SystemClock.elapsedRealtime(); 75 } 76 77 @Override computeHostOomAdjLSP(OomAdjuster oomAdjuster, ProcessRecord host, ProcessRecord client, long now, ProcessRecord topApp, boolean doingAll, int oomAdjReason, int cachedAdj)78 public void computeHostOomAdjLSP(OomAdjuster oomAdjuster, ProcessRecord host, 79 ProcessRecord client, long now, ProcessRecord topApp, boolean doingAll, 80 int oomAdjReason, int cachedAdj) { 81 oomAdjuster.computeProviderHostOomAdjLSP(this, host, client, now, topApp, doingAll, false, 82 false, oomAdjReason, UNKNOWN_ADJ, false, false); 83 } 84 85 @Override canAffectCapabilities()86 public boolean canAffectCapabilities() { 87 return false; 88 } 89 90 startAssociationIfNeeded()91 public void startAssociationIfNeeded() { 92 // If we don't already have an active association, create one... but only if this 93 // is an association between two different processes. 94 if (ActivityManagerService.TRACK_PROCSTATS_ASSOCIATIONS 95 && association == null && provider.proc != null 96 && (provider.appInfo.uid != client.uid 97 || !provider.info.processName.equals(client.processName))) { 98 ProcessStats.ProcessStateHolder holder = provider.proc.getPkgList().get( 99 provider.name.getPackageName()); 100 if (holder == null) { 101 Slog.wtf(TAG_AM, "No package in referenced provider " 102 + provider.name.toShortString() + ": proc=" + provider.proc); 103 } else if (holder.pkg == null) { 104 Slog.wtf(TAG_AM, "Inactive holder in referenced provider " 105 + provider.name.toShortString() + ": proc=" + provider.proc); 106 } else { 107 mProcStatsLock = provider.proc.mService.mProcessStats.mLock; 108 synchronized (mProcStatsLock) { 109 association = holder.pkg.getAssociationStateLocked(holder.state, 110 provider.name.getClassName()).startSource(client.uid, 111 client.processName, clientPackage); 112 } 113 } 114 } 115 } 116 117 /** 118 * Track the given proc state change. 119 */ trackProcState(int procState, int seq)120 public void trackProcState(int procState, int seq) { 121 if (association == null) { 122 return; // early exit to optimize on oomadj cycles 123 } 124 synchronized (mProcStatsLock) { 125 if (association != null) { // due to race-conditions, association may have become null 126 association.trackProcState(procState, seq, SystemClock.uptimeMillis()); 127 } 128 } 129 } 130 stopAssociation()131 public void stopAssociation() { 132 if (association == null) { 133 return; // early exit to optimize on oomadj cycles 134 } 135 synchronized (mProcStatsLock) { 136 if (association != null) { // due to race-conditions, association may have become null 137 association.stop(); 138 association = null; 139 } 140 } 141 } 142 toString()143 public String toString() { 144 StringBuilder sb = new StringBuilder(128); 145 sb.append("ContentProviderConnection{"); 146 toShortString(sb); 147 sb.append('}'); 148 return sb.toString(); 149 } 150 toShortString()151 public String toShortString() { 152 StringBuilder sb = new StringBuilder(128); 153 toShortString(sb); 154 return sb.toString(); 155 } 156 toClientString()157 public String toClientString() { 158 StringBuilder sb = new StringBuilder(128); 159 toClientString(sb); 160 return sb.toString(); 161 } 162 toShortString(StringBuilder sb)163 public void toShortString(StringBuilder sb) { 164 sb.append(provider.toShortString()); 165 sb.append("->"); 166 toClientString(sb); 167 } 168 toClientString(StringBuilder sb)169 public void toClientString(StringBuilder sb) { 170 sb.append(client.toShortString()); 171 synchronized (mLock) { 172 sb.append(" s"); 173 sb.append(mStableCount); 174 sb.append("/"); 175 sb.append(mNumStableIncs); 176 sb.append(" u"); 177 sb.append(mUnstableCount); 178 sb.append("/"); 179 sb.append(mNumUnstableIncs); 180 } 181 if (waiting) { 182 sb.append(" WAITING"); 183 } 184 if (dead) { 185 sb.append(" DEAD"); 186 } 187 long nowReal = SystemClock.elapsedRealtime(); 188 sb.append(" "); 189 TimeUtils.formatDuration(nowReal-createTime, sb); 190 } 191 192 /** 193 * Initializes the reference counts. Either the stable or unstable count 194 * is set to 1; the other reference count is set to zero. 195 */ initializeCount(boolean stable)196 public void initializeCount(boolean stable) { 197 synchronized (mLock) { 198 if (stable) { 199 mStableCount = 1; 200 mNumStableIncs = 1; 201 mUnstableCount = 0; 202 mNumUnstableIncs = 0; 203 } else { 204 mStableCount = 0; 205 mNumStableIncs = 0; 206 mUnstableCount = 1; 207 mNumUnstableIncs = 1; 208 } 209 } 210 } 211 212 /** 213 * Increments the stable or unstable reference count and return the total 214 * number of references. 215 */ incrementCount(boolean stable)216 public int incrementCount(boolean stable) { 217 synchronized (mLock) { 218 if (DEBUG_PROVIDER) { 219 final ContentProviderRecord cpr = provider; 220 Slog.v(TAG_AM, 221 "Adding provider requested by " 222 + client.processName + " from process " 223 + cpr.info.processName + ": " + cpr.name.flattenToShortString() 224 + " scnt=" + mStableCount + " uscnt=" + mUnstableCount); 225 } 226 if (stable) { 227 mStableCount++; 228 mNumStableIncs++; 229 } else { 230 mUnstableCount++; 231 mNumUnstableIncs++; 232 } 233 return mStableCount + mUnstableCount; 234 } 235 } 236 237 /** 238 * Decrements either the stable or unstable count and return the total 239 * number of references. 240 */ decrementCount(boolean stable)241 public int decrementCount(boolean stable) { 242 synchronized (mLock) { 243 if (DEBUG_PROVIDER) { 244 final ContentProviderRecord cpr = provider; 245 Slog.v(TAG_AM, 246 "Removing provider requested by " 247 + client.processName + " from process " 248 + cpr.info.processName + ": " + cpr.name.flattenToShortString() 249 + " scnt=" + mStableCount + " uscnt=" + mUnstableCount); 250 } 251 if (stable) { 252 mStableCount--; 253 } else { 254 mUnstableCount--; 255 } 256 return mStableCount + mUnstableCount; 257 } 258 } 259 260 /** 261 * Adjusts the reference counts up or down (the inputs may be positive, 262 * zero, or negative. This method does not return a total count because 263 * a return is not needed for the current use case. 264 */ adjustCounts(int stableIncrement, int unstableIncrement)265 public void adjustCounts(int stableIncrement, int unstableIncrement) { 266 synchronized (mLock) { 267 if (stableIncrement > 0) { 268 mNumStableIncs += stableIncrement; 269 } 270 final int stable = mStableCount + stableIncrement; 271 if (stable < 0) { 272 throw new IllegalStateException("stableCount < 0: " + stable); 273 } 274 if (unstableIncrement > 0) { 275 mNumUnstableIncs += unstableIncrement; 276 } 277 final int unstable = mUnstableCount + unstableIncrement; 278 if (unstable < 0) { 279 throw new IllegalStateException("unstableCount < 0: " + unstable); 280 } 281 if ((stable + unstable) <= 0) { 282 throw new IllegalStateException("ref counts can't go to zero here: stable=" 283 + stable + " unstable=" + unstable); 284 } 285 mStableCount = stable; 286 mUnstableCount = unstable; 287 } 288 } 289 290 /** 291 * Returns the number of stable references. 292 */ stableCount()293 public int stableCount() { 294 synchronized (mLock) { 295 return mStableCount; 296 } 297 } 298 299 /** 300 * Returns the number of unstable references. 301 */ unstableCount()302 public int unstableCount() { 303 synchronized (mLock) { 304 return mUnstableCount; 305 } 306 } 307 308 /** 309 * Returns the total number of stable and unstable references. 310 */ totalRefCount()311 int totalRefCount() { 312 synchronized (mLock) { 313 return mStableCount + mUnstableCount; 314 } 315 } 316 } 317