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 android.os.Binder;
20 import android.os.SystemClock;
21 import android.util.Slog;
22 import android.util.TimeUtils;
23 
24 import com.android.internal.app.procstats.AssociationState;
25 import com.android.internal.app.procstats.ProcessStats;
26 
27 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
28 
29 /**
30  * Represents a link between a content provider and client.
31  */
32 public final class ContentProviderConnection extends Binder {
33     public final ContentProviderRecord provider;
34     public final ProcessRecord client;
35     public final String clientPackage;
36     public AssociationState.SourceState association;
37     public final long createTime;
38     public int stableCount;
39     public int unstableCount;
40     // The client of this connection is currently waiting for the provider to appear.
41     // Protected by the provider lock.
42     public boolean waiting;
43     // The provider of this connection is now dead.
44     public boolean dead;
45 
46     // For debugging.
47     public int numStableIncs;
48     public int numUnstableIncs;
49 
ContentProviderConnection(ContentProviderRecord _provider, ProcessRecord _client, String _clientPackage)50     public ContentProviderConnection(ContentProviderRecord _provider, ProcessRecord _client,
51             String _clientPackage) {
52         provider = _provider;
53         client = _client;
54         clientPackage = _clientPackage;
55         createTime = SystemClock.elapsedRealtime();
56     }
57 
startAssociationIfNeeded()58     public void startAssociationIfNeeded() {
59         // If we don't already have an active association, create one...  but only if this
60         // is an association between two different processes.
61         if (ActivityManagerService.TRACK_PROCSTATS_ASSOCIATIONS
62                 && association == null && provider.proc != null
63                 && (provider.appInfo.uid != client.uid
64                         || !provider.info.processName.equals(client.processName))) {
65             ProcessStats.ProcessStateHolder holder = provider.proc.pkgList.get(
66                     provider.name.getPackageName());
67             if (holder == null) {
68                 Slog.wtf(TAG_AM, "No package in referenced provider "
69                         + provider.name.toShortString() + ": proc=" + provider.proc);
70             } else if (holder.pkg == null) {
71                 Slog.wtf(TAG_AM, "Inactive holder in referenced provider "
72                         + provider.name.toShortString() + ": proc=" + provider.proc);
73             } else {
74                 association = holder.pkg.getAssociationStateLocked(holder.state,
75                         provider.name.getClassName()).startSource(client.uid, client.processName,
76                         clientPackage);
77 
78             }
79         }
80     }
81 
trackProcState(int procState, int seq, long now)82     public void trackProcState(int procState, int seq, long now) {
83         if (association != null) {
84             association.trackProcState(procState, seq, now);
85         }
86     }
87 
stopAssociation()88     public void stopAssociation() {
89         if (association != null) {
90             association.stop();
91             association = null;
92         }
93     }
94 
toString()95     public String toString() {
96         StringBuilder sb = new StringBuilder(128);
97         sb.append("ContentProviderConnection{");
98         toShortString(sb);
99         sb.append('}');
100         return sb.toString();
101     }
102 
toShortString()103     public String toShortString() {
104         StringBuilder sb = new StringBuilder(128);
105         toShortString(sb);
106         return sb.toString();
107     }
108 
toClientString()109     public String toClientString() {
110         StringBuilder sb = new StringBuilder(128);
111         toClientString(sb);
112         return sb.toString();
113     }
114 
toShortString(StringBuilder sb)115     public void toShortString(StringBuilder sb) {
116         sb.append(provider.toShortString());
117         sb.append("->");
118         toClientString(sb);
119     }
120 
toClientString(StringBuilder sb)121     public void toClientString(StringBuilder sb) {
122         sb.append(client.toShortString());
123         sb.append(" s");
124         sb.append(stableCount);
125         sb.append("/");
126         sb.append(numStableIncs);
127         sb.append(" u");
128         sb.append(unstableCount);
129         sb.append("/");
130         sb.append(numUnstableIncs);
131         if (waiting) {
132             sb.append(" WAITING");
133         }
134         if (dead) {
135             sb.append(" DEAD");
136         }
137         long nowReal = SystemClock.elapsedRealtime();
138         sb.append(" ");
139         TimeUtils.formatDuration(nowReal-createTime, sb);
140     }
141 }
142