blob: 7b9b6595d7cfdc28c9932755c8771d7ff9825dcc [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 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
17package com.android.server.am;
18
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070019import android.app.ContentProviderHolder;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070020import android.content.ComponentName;
Dianne Hackborn6ae8d182012-05-23 13:12:42 -070021import android.content.IContentProvider;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.content.pm.ApplicationInfo;
23import android.content.pm.ProviderInfo;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080024import android.os.IBinder;
25import android.os.IBinder.DeathRecipient;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.os.Process;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080027import android.os.RemoteException;
Dianne Hackbornb12e1352012-09-26 11:39:20 -070028import android.os.UserHandle;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080029import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
31import java.io.PrintWriter;
Dianne Hackborn6ae8d182012-05-23 13:12:42 -070032import java.util.ArrayList;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080033import java.util.HashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070035final class ContentProviderRecord {
Dianne Hackborn6ae8d182012-05-23 13:12:42 -070036 final ActivityManagerService service;
37 public final ProviderInfo info;
38 final int uid;
39 final ApplicationInfo appInfo;
40 final ComponentName name;
Dianne Hackborn7d19e022012-08-07 19:12:33 -070041 final boolean singleton;
Dianne Hackborn6ae8d182012-05-23 13:12:42 -070042 public IContentProvider provider;
43 public boolean noReleaseNeeded;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044 // All attached clients
Dianne Hackborn6ae8d182012-05-23 13:12:42 -070045 final ArrayList<ContentProviderConnection> connections
46 = new ArrayList<ContentProviderConnection>();
47 //final HashSet<ProcessRecord> clients = new HashSet<ProcessRecord>();
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080048 // Handles for non-framework processes supported by this provider
49 HashMap<IBinder, ExternalProcessHandle> externalProcessTokenToHandle;
50 // Count for external process for which we have no handles.
51 int externalProcessNoHandleCount;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070052 ProcessRecord proc; // if non-null, hosting process.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 ProcessRecord launchingApp; // if non-null, waiting for this app to be launched.
Dianne Hackbornf210d6b2009-04-13 18:42:49 -070054 String stringName;
Dianne Hackborn6ae8d182012-05-23 13:12:42 -070055 String shortStringName;
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080056
57 public ContentProviderRecord(ActivityManagerService _service, ProviderInfo _info,
Dianne Hackborn7d19e022012-08-07 19:12:33 -070058 ApplicationInfo ai, ComponentName _name, boolean _singleton) {
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080059 service = _service;
Dianne Hackborn6ae8d182012-05-23 13:12:42 -070060 info = _info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 uid = ai.uid;
62 appInfo = ai;
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -070063 name = _name;
Dianne Hackborn7d19e022012-08-07 19:12:33 -070064 singleton = _singleton;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 noReleaseNeeded = uid == 0 || uid == Process.SYSTEM_UID;
66 }
67
68 public ContentProviderRecord(ContentProviderRecord cpr) {
Dianne Hackborn6ae8d182012-05-23 13:12:42 -070069 service = cpr.service;
70 info = cpr.info;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071 uid = cpr.uid;
72 appInfo = cpr.appInfo;
Dianne Hackbornb7bb3b32010-06-06 22:47:50 -070073 name = cpr.name;
Dianne Hackborn7d19e022012-08-07 19:12:33 -070074 singleton = cpr.singleton;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 noReleaseNeeded = cpr.noReleaseNeeded;
Dianne Hackborn6ae8d182012-05-23 13:12:42 -070076 }
77
78 public ContentProviderHolder newHolder(ContentProviderConnection conn) {
79 ContentProviderHolder holder = new ContentProviderHolder(info);
80 holder.provider = provider;
81 holder.noReleaseNeeded = noReleaseNeeded;
82 holder.connection = conn;
83 return holder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 }
85
86 public boolean canRunHere(ProcessRecord app) {
87 return (info.multiprocess || info.processName.equals(app.processName))
Dianne Hackborn11941fd2012-09-07 15:35:17 -070088 && uid == app.info.uid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089 }
90
Svetoslav Ganov25872aa2012-02-03 19:19:09 -080091 public void addExternalProcessHandleLocked(IBinder token) {
92 if (token == null) {
93 externalProcessNoHandleCount++;
94 } else {
95 if (externalProcessTokenToHandle == null) {
96 externalProcessTokenToHandle = new HashMap<IBinder, ExternalProcessHandle>();
97 }
98 ExternalProcessHandle handle = externalProcessTokenToHandle.get(token);
99 if (handle == null) {
100 handle = new ExternalProcessHandle(token);
101 externalProcessTokenToHandle.put(token, handle);
102 }
103 handle.mAcquisitionCount++;
104 }
105 }
106
107 public boolean removeExternalProcessHandleLocked(IBinder token) {
108 if (hasExternalProcessHandles()) {
109 boolean hasHandle = false;
110 if (externalProcessTokenToHandle != null) {
111 ExternalProcessHandle handle = externalProcessTokenToHandle.get(token);
112 if (handle != null) {
113 hasHandle = true;
114 handle.mAcquisitionCount--;
115 if (handle.mAcquisitionCount == 0) {
116 removeExternalProcessHandleInternalLocked(token);
117 return true;
118 }
119 }
120 }
121 if (!hasHandle) {
122 externalProcessNoHandleCount--;
123 return true;
124 }
125 }
126 return false;
127 }
128
129 private void removeExternalProcessHandleInternalLocked(IBinder token) {
130 ExternalProcessHandle handle = externalProcessTokenToHandle.get(token);
131 handle.unlinkFromOwnDeathLocked();
132 externalProcessTokenToHandle.remove(token);
133 if (externalProcessTokenToHandle.size() == 0) {
134 externalProcessTokenToHandle = null;
135 }
136 }
137
138 public boolean hasExternalProcessHandles() {
139 return (externalProcessTokenToHandle != null || externalProcessNoHandleCount > 0);
140 }
141
riddle_hsu691a1732015-05-13 18:59:03 +0800142 public boolean hasConnectionOrHandle() {
143 return !connections.isEmpty() || hasExternalProcessHandles();
144 }
145
Dianne Hackborn6ae8d182012-05-23 13:12:42 -0700146 void dump(PrintWriter pw, String prefix, boolean full) {
147 if (full) {
148 pw.print(prefix); pw.print("package=");
149 pw.print(info.applicationInfo.packageName);
150 pw.print(" process="); pw.println(info.processName);
151 }
Dianne Hackborn2a6bcda2011-09-21 15:07:05 -0700152 pw.print(prefix); pw.print("proc="); pw.println(proc);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700153 if (launchingApp != null) {
154 pw.print(prefix); pw.print("launchingApp="); pw.println(launchingApp);
155 }
Dianne Hackborn6ae8d182012-05-23 13:12:42 -0700156 if (full) {
157 pw.print(prefix); pw.print("uid="); pw.print(uid);
158 pw.print(" provider="); pw.println(provider);
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700159 }
Dianne Hackborn7d19e022012-08-07 19:12:33 -0700160 if (singleton) {
161 pw.print(prefix); pw.print("singleton="); pw.println(singleton);
162 }
Dianne Hackborn6ae8d182012-05-23 13:12:42 -0700163 pw.print(prefix); pw.print("authority="); pw.println(info.authority);
164 if (full) {
165 if (info.isSyncable || info.multiprocess || info.initOrder != 0) {
166 pw.print(prefix); pw.print("isSyncable="); pw.print(info.isSyncable);
167 pw.print(" multiprocess="); pw.print(info.multiprocess);
168 pw.print(" initOrder="); pw.println(info.initOrder);
169 }
Dianne Hackbornd8c98fe2011-11-15 11:29:38 -0800170 }
Dianne Hackborn6ae8d182012-05-23 13:12:42 -0700171 if (full) {
172 if (hasExternalProcessHandles()) {
Dianne Hackborn3133c402014-08-29 12:53:07 -0700173 pw.print(prefix); pw.print("externals:");
174 if (externalProcessTokenToHandle != null) {
175 pw.print(" w/token=");
176 pw.print(externalProcessTokenToHandle.size());
177 }
178 if (externalProcessNoHandleCount > 0) {
179 pw.print(" notoken=");
180 pw.print(externalProcessNoHandleCount);
181 }
182 pw.println();
Dianne Hackborn6ae8d182012-05-23 13:12:42 -0700183 }
184 } else {
185 if (connections.size() > 0 || externalProcessNoHandleCount > 0) {
186 pw.print(prefix); pw.print(connections.size());
187 pw.print(" connections, "); pw.print(externalProcessNoHandleCount);
188 pw.println(" external handles");
189 }
190 }
191 if (connections.size() > 0) {
192 if (full) {
193 pw.print(prefix); pw.println("Connections:");
194 }
195 for (int i=0; i<connections.size(); i++) {
196 ContentProviderConnection conn = connections.get(i);
197 pw.print(prefix); pw.print(" -> "); pw.println(conn.toClientString());
198 if (conn.provider != this) {
199 pw.print(prefix); pw.print(" *** WRONG PROVIDER: ");
200 pw.println(conn.provider);
201 }
Dianne Hackborn8ec8d412011-11-14 18:27:24 -0800202 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700203 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 }
205
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800206 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 public String toString() {
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700208 if (stringName != null) {
209 return stringName;
210 }
211 StringBuilder sb = new StringBuilder(128);
212 sb.append("ContentProviderRecord{");
213 sb.append(Integer.toHexString(System.identityHashCode(this)));
Dianne Hackbornb12e1352012-09-26 11:39:20 -0700214 sb.append(" u");
215 sb.append(UserHandle.getUserId(uid));
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700216 sb.append(' ');
Dianne Hackborn9da2d402012-03-15 13:43:08 -0700217 sb.append(name.flattenToShortString());
Dianne Hackbornf210d6b2009-04-13 18:42:49 -0700218 sb.append('}');
219 return stringName = sb.toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 }
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800221
Dianne Hackborn6ae8d182012-05-23 13:12:42 -0700222 public String toShortString() {
223 if (shortStringName != null) {
224 return shortStringName;
225 }
226 StringBuilder sb = new StringBuilder(128);
227 sb.append(Integer.toHexString(System.identityHashCode(this)));
228 sb.append('/');
229 sb.append(name.flattenToShortString());
230 return shortStringName = sb.toString();
231 }
232
Svetoslav Ganov25872aa2012-02-03 19:19:09 -0800233 // This class represents a handle from an external process to a provider.
234 private class ExternalProcessHandle implements DeathRecipient {
235 private static final String LOG_TAG = "ExternalProcessHanldle";
236
237 private final IBinder mToken;
238 private int mAcquisitionCount;
239
240 public ExternalProcessHandle(IBinder token) {
241 mToken = token;
242 try {
243 token.linkToDeath(this, 0);
244 } catch (RemoteException re) {
245 Slog.e(LOG_TAG, "Couldn't register for death for token: " + mToken, re);
246 }
247 }
248
249 public void unlinkFromOwnDeathLocked() {
250 mToken.unlinkToDeath(this, 0);
251 }
252
253 @Override
254 public void binderDied() {
255 synchronized (service) {
256 if (hasExternalProcessHandles() &&
257 externalProcessTokenToHandle.get(mToken) != null) {
258 removeExternalProcessHandleInternalLocked(mToken);
259 }
260 }
261 }
262 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263}