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 trackProcState(int procState, int seq, long now)101 public void trackProcState(int procState, int seq, long now) { 102 if (association != null) { 103 synchronized (mProcStatsLock) { 104 association.trackProcState(procState, seq, now); 105 } 106 } 107 } 108 stopAssociation()109 public void stopAssociation() { 110 if (association != null) { 111 synchronized (mProcStatsLock) { 112 association.stop(); 113 } 114 association = null; 115 } 116 } 117 toString()118 public String toString() { 119 StringBuilder sb = new StringBuilder(128); 120 sb.append("ContentProviderConnection{"); 121 toShortString(sb); 122 sb.append('}'); 123 return sb.toString(); 124 } 125 toShortString()126 public String toShortString() { 127 StringBuilder sb = new StringBuilder(128); 128 toShortString(sb); 129 return sb.toString(); 130 } 131 toClientString()132 public String toClientString() { 133 StringBuilder sb = new StringBuilder(128); 134 toClientString(sb); 135 return sb.toString(); 136 } 137 toShortString(StringBuilder sb)138 public void toShortString(StringBuilder sb) { 139 sb.append(provider.toShortString()); 140 sb.append("->"); 141 toClientString(sb); 142 } 143 toClientString(StringBuilder sb)144 public void toClientString(StringBuilder sb) { 145 sb.append(client.toShortString()); 146 synchronized (mLock) { 147 sb.append(" s"); 148 sb.append(mStableCount); 149 sb.append("/"); 150 sb.append(mNumStableIncs); 151 sb.append(" u"); 152 sb.append(mUnstableCount); 153 sb.append("/"); 154 sb.append(mNumUnstableIncs); 155 } 156 if (waiting) { 157 sb.append(" WAITING"); 158 } 159 if (dead) { 160 sb.append(" DEAD"); 161 } 162 long nowReal = SystemClock.elapsedRealtime(); 163 sb.append(" "); 164 TimeUtils.formatDuration(nowReal-createTime, sb); 165 } 166 167 /** 168 * Initializes the reference counts. Either the stable or unstable count 169 * is set to 1; the other reference count is set to zero. 170 */ initializeCount(boolean stable)171 public void initializeCount(boolean stable) { 172 synchronized (mLock) { 173 if (stable) { 174 mStableCount = 1; 175 mNumStableIncs = 1; 176 mUnstableCount = 0; 177 mNumUnstableIncs = 0; 178 } else { 179 mStableCount = 0; 180 mNumStableIncs = 0; 181 mUnstableCount = 1; 182 mNumUnstableIncs = 1; 183 } 184 } 185 } 186 187 /** 188 * Increments the stable or unstable reference count and return the total 189 * number of references. 190 */ incrementCount(boolean stable)191 public int incrementCount(boolean stable) { 192 synchronized (mLock) { 193 if (DEBUG_PROVIDER) { 194 final ContentProviderRecord cpr = provider; 195 Slog.v(TAG_AM, 196 "Adding provider requested by " 197 + client.processName + " from process " 198 + cpr.info.processName + ": " + cpr.name.flattenToShortString() 199 + " scnt=" + mStableCount + " uscnt=" + mUnstableCount); 200 } 201 if (stable) { 202 mStableCount++; 203 mNumStableIncs++; 204 } else { 205 mUnstableCount++; 206 mNumUnstableIncs++; 207 } 208 return mStableCount + mUnstableCount; 209 } 210 } 211 212 /** 213 * Decrements either the stable or unstable count and return the total 214 * number of references. 215 */ decrementCount(boolean stable)216 public int decrementCount(boolean stable) { 217 synchronized (mLock) { 218 if (DEBUG_PROVIDER) { 219 final ContentProviderRecord cpr = provider; 220 Slog.v(TAG_AM, 221 "Removing 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 } else { 229 mUnstableCount--; 230 } 231 return mStableCount + mUnstableCount; 232 } 233 } 234 235 /** 236 * Adjusts the reference counts up or down (the inputs may be positive, 237 * zero, or negative. This method does not return a total count because 238 * a return is not needed for the current use case. 239 */ adjustCounts(int stableIncrement, int unstableIncrement)240 public void adjustCounts(int stableIncrement, int unstableIncrement) { 241 synchronized (mLock) { 242 if (stableIncrement > 0) { 243 mNumStableIncs += stableIncrement; 244 } 245 final int stable = mStableCount + stableIncrement; 246 if (stable < 0) { 247 throw new IllegalStateException("stableCount < 0: " + stable); 248 } 249 if (unstableIncrement > 0) { 250 mNumUnstableIncs += unstableIncrement; 251 } 252 final int unstable = mUnstableCount + unstableIncrement; 253 if (unstable < 0) { 254 throw new IllegalStateException("unstableCount < 0: " + unstable); 255 } 256 if ((stable + unstable) <= 0) { 257 throw new IllegalStateException("ref counts can't go to zero here: stable=" 258 + stable + " unstable=" + unstable); 259 } 260 mStableCount = stable; 261 mUnstableCount = unstable; 262 } 263 } 264 265 /** 266 * Returns the number of stable references. 267 */ stableCount()268 public int stableCount() { 269 synchronized (mLock) { 270 return mStableCount; 271 } 272 } 273 274 /** 275 * Returns the number of unstable references. 276 */ unstableCount()277 public int unstableCount() { 278 synchronized (mLock) { 279 return mUnstableCount; 280 } 281 } 282 283 /** 284 * Returns the total number of stable and unstable references. 285 */ totalRefCount()286 int totalRefCount() { 287 synchronized (mLock) { 288 return mStableCount + mUnstableCount; 289 } 290 } 291 } 292