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