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