• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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