blob: 29c165733808aef76e57c5a950f8d238652d1150 [file] [log] [blame]
Amith Yamasani742a6712011-05-04 14:49:28 -07001/*
2 * Copyright (C) 2011 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
19import android.content.ComponentName;
Makoto Onuki0b575a32018-04-16 14:33:59 -070020import android.content.ComponentName.WithComponentName;
Amith Yamasani742a6712011-05-04 14:49:28 -070021import android.os.Binder;
Marco Nelissende7408c2012-02-08 14:57:38 -080022import android.os.RemoteException;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070023import android.os.UserHandle;
Amith Yamasani742a6712011-05-04 14:49:28 -070024import android.util.Slog;
25import android.util.SparseArray;
Dianne Hackborncbfd23e2013-06-11 14:26:53 -070026import com.android.internal.os.TransferPipe;
Makoto Onuki0b575a32018-04-16 14:33:59 -070027import com.android.internal.util.CollectionUtils;
28import com.android.internal.util.DumpUtils;
Amith Yamasani742a6712011-05-04 14:49:28 -070029
Marco Nelissende7408c2012-02-08 14:57:38 -080030import java.io.FileDescriptor;
31import java.io.IOException;
Amith Yamasani742a6712011-05-04 14:49:28 -070032import java.io.PrintWriter;
Marco Nelissende7408c2012-02-08 14:57:38 -080033import java.util.ArrayList;
Steven Timotiusfd55a942017-11-15 16:43:57 -080034import java.util.Arrays;
Makoto Onuki0b575a32018-04-16 14:33:59 -070035import java.util.Comparator;
Amith Yamasani742a6712011-05-04 14:49:28 -070036import java.util.HashMap;
37import java.util.Iterator;
38import java.util.Map;
Wale Ogunwale540e1232015-05-01 15:35:39 -070039import java.util.Set;
Makoto Onuki0b575a32018-04-16 14:33:59 -070040import java.util.function.Predicate;
Amith Yamasani742a6712011-05-04 14:49:28 -070041
42/**
43 * Keeps track of content providers by authority (name) and class. It separates the mapping by
44 * user and ones that are not user-specific (system providers).
45 */
Dianne Hackbornbe4e6aa2013-06-07 13:25:29 -070046public final class ProviderMap {
Amith Yamasani742a6712011-05-04 14:49:28 -070047
48 private static final String TAG = "ProviderMap";
49
50 private static final boolean DBG = false;
51
Dianne Hackborn2d1b3782012-09-09 17:49:39 -070052 private final ActivityManagerService mAm;
53
Dianne Hackborn7d19e022012-08-07 19:12:33 -070054 private final HashMap<String, ContentProviderRecord> mSingletonByName
Amith Yamasani742a6712011-05-04 14:49:28 -070055 = new HashMap<String, ContentProviderRecord>();
Dianne Hackborn7d19e022012-08-07 19:12:33 -070056 private final HashMap<ComponentName, ContentProviderRecord> mSingletonByClass
Amith Yamasani742a6712011-05-04 14:49:28 -070057 = new HashMap<ComponentName, ContentProviderRecord>();
58
59 private final SparseArray<HashMap<String, ContentProviderRecord>> mProvidersByNamePerUser
60 = new SparseArray<HashMap<String, ContentProviderRecord>>();
61 private final SparseArray<HashMap<ComponentName, ContentProviderRecord>> mProvidersByClassPerUser
62 = new SparseArray<HashMap<ComponentName, ContentProviderRecord>>();
63
Dianne Hackborn2d1b3782012-09-09 17:49:39 -070064 ProviderMap(ActivityManagerService am) {
65 mAm = am;
66 }
67
Amith Yamasani742a6712011-05-04 14:49:28 -070068 ContentProviderRecord getProviderByName(String name) {
69 return getProviderByName(name, -1);
70 }
71
72 ContentProviderRecord getProviderByName(String name, int userId) {
73 if (DBG) {
74 Slog.i(TAG, "getProviderByName: " + name + " , callingUid = " + Binder.getCallingUid());
75 }
76 // Try to find it in the global list
Dianne Hackborn7d19e022012-08-07 19:12:33 -070077 ContentProviderRecord record = mSingletonByName.get(name);
Amith Yamasani742a6712011-05-04 14:49:28 -070078 if (record != null) {
79 return record;
80 }
81
82 // Check the current user's list
83 return getProvidersByName(userId).get(name);
84 }
85
86 ContentProviderRecord getProviderByClass(ComponentName name) {
87 return getProviderByClass(name, -1);
88 }
89
90 ContentProviderRecord getProviderByClass(ComponentName name, int userId) {
91 if (DBG) {
92 Slog.i(TAG, "getProviderByClass: " + name + ", callingUid = " + Binder.getCallingUid());
93 }
94 // Try to find it in the global list
Dianne Hackborn7d19e022012-08-07 19:12:33 -070095 ContentProviderRecord record = mSingletonByClass.get(name);
Amith Yamasani742a6712011-05-04 14:49:28 -070096 if (record != null) {
97 return record;
98 }
99
100 // Check the current user's list
101 return getProvidersByClass(userId).get(name);
102 }
103
104 void putProviderByName(String name, ContentProviderRecord record) {
105 if (DBG) {
106 Slog.i(TAG, "putProviderByName: " + name + " , callingUid = " + Binder.getCallingUid()
107 + ", record uid = " + record.appInfo.uid);
108 }
Dianne Hackborn7d19e022012-08-07 19:12:33 -0700109 if (record.singleton) {
110 mSingletonByName.put(name, record);
Amith Yamasani742a6712011-05-04 14:49:28 -0700111 } else {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700112 final int userId = UserHandle.getUserId(record.appInfo.uid);
Amith Yamasani742a6712011-05-04 14:49:28 -0700113 getProvidersByName(userId).put(name, record);
114 }
115 }
116
117 void putProviderByClass(ComponentName name, ContentProviderRecord record) {
118 if (DBG) {
119 Slog.i(TAG, "putProviderByClass: " + name + " , callingUid = " + Binder.getCallingUid()
120 + ", record uid = " + record.appInfo.uid);
121 }
Dianne Hackborn7d19e022012-08-07 19:12:33 -0700122 if (record.singleton) {
123 mSingletonByClass.put(name, record);
Amith Yamasani742a6712011-05-04 14:49:28 -0700124 } else {
Dianne Hackbornf02b60a2012-08-16 10:48:27 -0700125 final int userId = UserHandle.getUserId(record.appInfo.uid);
Amith Yamasani742a6712011-05-04 14:49:28 -0700126 getProvidersByClass(userId).put(name, record);
127 }
128 }
129
Dianne Hackborn41203752012-08-31 14:05:51 -0700130 void removeProviderByName(String name, int userId) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -0700131 if (mSingletonByName.containsKey(name)) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700132 if (DBG)
133 Slog.i(TAG, "Removing from globalByName name=" + name);
Dianne Hackborn7d19e022012-08-07 19:12:33 -0700134 mSingletonByName.remove(name);
Amith Yamasani742a6712011-05-04 14:49:28 -0700135 } else {
Dianne Hackborn41203752012-08-31 14:05:51 -0700136 if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
Amith Yamasani742a6712011-05-04 14:49:28 -0700137 if (DBG)
138 Slog.i(TAG,
Dianne Hackborn41203752012-08-31 14:05:51 -0700139 "Removing from providersByName name=" + name + " user=" + userId);
140 HashMap<String, ContentProviderRecord> map = getProvidersByName(userId);
Vairavan Srinivasan88090042012-08-15 23:37:45 -0700141 // map returned by getProvidersByName wouldn't be null
142 map.remove(name);
143 if (map.size() == 0) {
Dianne Hackborn41203752012-08-31 14:05:51 -0700144 mProvidersByNamePerUser.remove(userId);
Vairavan Srinivasan88090042012-08-15 23:37:45 -0700145 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700146 }
147 }
148
Dianne Hackborn41203752012-08-31 14:05:51 -0700149 void removeProviderByClass(ComponentName name, int userId) {
Dianne Hackborn7d19e022012-08-07 19:12:33 -0700150 if (mSingletonByClass.containsKey(name)) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700151 if (DBG)
152 Slog.i(TAG, "Removing from globalByClass name=" + name);
Dianne Hackborn7d19e022012-08-07 19:12:33 -0700153 mSingletonByClass.remove(name);
Amith Yamasani742a6712011-05-04 14:49:28 -0700154 } else {
Dianne Hackborn41203752012-08-31 14:05:51 -0700155 if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
Amith Yamasani742a6712011-05-04 14:49:28 -0700156 if (DBG)
157 Slog.i(TAG,
Dianne Hackborn41203752012-08-31 14:05:51 -0700158 "Removing from providersByClass name=" + name + " user=" + userId);
159 HashMap<ComponentName, ContentProviderRecord> map = getProvidersByClass(userId);
Vairavan Srinivasan88090042012-08-15 23:37:45 -0700160 // map returned by getProvidersByClass wouldn't be null
161 map.remove(name);
162 if (map.size() == 0) {
Dianne Hackborn41203752012-08-31 14:05:51 -0700163 mProvidersByClassPerUser.remove(userId);
Vairavan Srinivasan88090042012-08-15 23:37:45 -0700164 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700165 }
166 }
167
Dianne Hackborn41203752012-08-31 14:05:51 -0700168 private HashMap<String, ContentProviderRecord> getProvidersByName(int userId) {
169 if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
Amith Yamasani742a6712011-05-04 14:49:28 -0700170 final HashMap<String, ContentProviderRecord> map = mProvidersByNamePerUser.get(userId);
171 if (map == null) {
172 HashMap<String, ContentProviderRecord> newMap = new HashMap<String, ContentProviderRecord>();
173 mProvidersByNamePerUser.put(userId, newMap);
174 return newMap;
175 } else {
176 return map;
177 }
178 }
179
Dianne Hackborn41203752012-08-31 14:05:51 -0700180 HashMap<ComponentName, ContentProviderRecord> getProvidersByClass(int userId) {
181 if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
182 final HashMap<ComponentName, ContentProviderRecord> map
183 = mProvidersByClassPerUser.get(userId);
Amith Yamasani742a6712011-05-04 14:49:28 -0700184 if (map == null) {
Dianne Hackborn41203752012-08-31 14:05:51 -0700185 HashMap<ComponentName, ContentProviderRecord> newMap
186 = new HashMap<ComponentName, ContentProviderRecord>();
Amith Yamasani742a6712011-05-04 14:49:28 -0700187 mProvidersByClassPerUser.put(userId, newMap);
188 return newMap;
189 } else {
190 return map;
191 }
192 }
193
Wale Ogunwale540e1232015-05-01 15:35:39 -0700194 private boolean collectPackageProvidersLocked(String packageName,
195 Set<String> filterByClasses, boolean doit, boolean evenPersistent,
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -0700196 HashMap<ComponentName, ContentProviderRecord> providers,
197 ArrayList<ContentProviderRecord> result) {
198 boolean didSomething = false;
199 for (ContentProviderRecord provider : providers.values()) {
Wale Ogunwale540e1232015-05-01 15:35:39 -0700200 final boolean sameComponent = packageName == null
201 || (provider.info.packageName.equals(packageName)
202 && (filterByClasses == null
203 || filterByClasses.contains(provider.name.getClassName())));
204 if (sameComponent
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700205 && (provider.proc == null || evenPersistent || !provider.proc.isPersistent())) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -0700206 if (!doit) {
207 return true;
208 }
209 didSomething = true;
210 result.add(provider);
211 }
212 }
213 return didSomething;
214 }
215
Wale Ogunwale540e1232015-05-01 15:35:39 -0700216 boolean collectPackageProvidersLocked(String packageName, Set<String> filterByClasses,
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -0700217 boolean doit, boolean evenPersistent, int userId,
218 ArrayList<ContentProviderRecord> result) {
riddle_hsu5ff8ba72015-05-15 11:33:03 +0800219 boolean didSomething = false;
Xiaohui Chen7c696362015-09-16 09:56:14 -0700220 if (userId == UserHandle.USER_ALL || userId == UserHandle.USER_SYSTEM) {
riddle_hsu5ff8ba72015-05-15 11:33:03 +0800221 didSomething = collectPackageProvidersLocked(packageName, filterByClasses,
222 doit, evenPersistent, mSingletonByClass, result);
223 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -0700224 if (!doit && didSomething) {
225 return true;
226 }
227 if (userId == UserHandle.USER_ALL) {
Wale Ogunwale540e1232015-05-01 15:35:39 -0700228 for (int i = 0; i < mProvidersByClassPerUser.size(); i++) {
229 if (collectPackageProvidersLocked(packageName, filterByClasses,
230 doit, evenPersistent, mProvidersByClassPerUser.valueAt(i), result)) {
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -0700231 if (!doit) {
232 return true;
233 }
234 didSomething = true;
235 }
236 }
237 } else {
Dianne Hackborn2d1b3782012-09-09 17:49:39 -0700238 HashMap<ComponentName, ContentProviderRecord> items
239 = getProvidersByClass(userId);
240 if (items != null) {
Wale Ogunwale540e1232015-05-01 15:35:39 -0700241 didSomething |= collectPackageProvidersLocked(packageName, filterByClasses,
242 doit, evenPersistent, items, result);
Dianne Hackborn2d1b3782012-09-09 17:49:39 -0700243 }
Dianne Hackborn5e03e2c2012-09-06 14:21:19 -0700244 }
245 return didSomething;
246 }
247
Dianne Hackborn390517b2013-05-30 15:03:32 -0700248 private boolean dumpProvidersByClassLocked(PrintWriter pw, boolean dumpAll, String dumpPackage,
249 String header, boolean needSep, HashMap<ComponentName, ContentProviderRecord> map) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700250 Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it = map.entrySet().iterator();
Dianne Hackborn390517b2013-05-30 15:03:32 -0700251 boolean written = false;
Amith Yamasani742a6712011-05-04 14:49:28 -0700252 while (it.hasNext()) {
253 Map.Entry<ComponentName, ContentProviderRecord> e = it.next();
254 ContentProviderRecord r = e.getValue();
Dianne Hackborn390517b2013-05-30 15:03:32 -0700255 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
256 continue;
257 }
258 if (needSep) {
259 pw.println("");
260 needSep = false;
261 }
262 if (header != null) {
263 pw.println(header);
264 header = null;
265 }
266 written = true;
Dianne Hackborn6ae8d182012-05-23 13:12:42 -0700267 pw.print(" * ");
268 pw.println(r);
269 r.dump(pw, " ", dumpAll);
Amith Yamasani742a6712011-05-04 14:49:28 -0700270 }
Dianne Hackborn390517b2013-05-30 15:03:32 -0700271 return written;
Amith Yamasani742a6712011-05-04 14:49:28 -0700272 }
273
Dianne Hackborn390517b2013-05-30 15:03:32 -0700274 private boolean dumpProvidersByNameLocked(PrintWriter pw, String dumpPackage,
275 String header, boolean needSep, HashMap<String, ContentProviderRecord> map) {
Amith Yamasani742a6712011-05-04 14:49:28 -0700276 Iterator<Map.Entry<String, ContentProviderRecord>> it = map.entrySet().iterator();
Dianne Hackborn390517b2013-05-30 15:03:32 -0700277 boolean written = false;
Amith Yamasani742a6712011-05-04 14:49:28 -0700278 while (it.hasNext()) {
279 Map.Entry<String, ContentProviderRecord> e = it.next();
280 ContentProviderRecord r = e.getValue();
Dianne Hackborn390517b2013-05-30 15:03:32 -0700281 if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
282 continue;
283 }
284 if (needSep) {
285 pw.println("");
286 needSep = false;
287 }
288 if (header != null) {
289 pw.println(header);
290 header = null;
291 }
292 written = true;
Amith Yamasani742a6712011-05-04 14:49:28 -0700293 pw.print(" ");
294 pw.print(e.getKey());
295 pw.print(": ");
Dianne Hackborn6ae8d182012-05-23 13:12:42 -0700296 pw.println(r.toShortString());
Amith Yamasani742a6712011-05-04 14:49:28 -0700297 }
Dianne Hackborn390517b2013-05-30 15:03:32 -0700298 return written;
Amith Yamasani742a6712011-05-04 14:49:28 -0700299 }
300
Dianne Hackborn390517b2013-05-30 15:03:32 -0700301 boolean dumpProvidersLocked(PrintWriter pw, boolean dumpAll, String dumpPackage) {
302 boolean needSep = false;
303
Dianne Hackborn7d19e022012-08-07 19:12:33 -0700304 if (mSingletonByClass.size() > 0) {
Dianne Hackborn7ad34e52013-06-05 18:41:45 -0700305 needSep |= dumpProvidersByClassLocked(pw, dumpAll, dumpPackage,
Dianne Hackborn390517b2013-05-30 15:03:32 -0700306 " Published single-user content providers (by class):", needSep,
307 mSingletonByClass);
Amith Yamasani742a6712011-05-04 14:49:28 -0700308 }
309
Dianne Hackborn7d19e022012-08-07 19:12:33 -0700310 for (int i = 0; i < mProvidersByClassPerUser.size(); i++) {
311 HashMap<ComponentName, ContentProviderRecord> map = mProvidersByClassPerUser.valueAt(i);
Dianne Hackborn390517b2013-05-30 15:03:32 -0700312 needSep |= dumpProvidersByClassLocked(pw, dumpAll, dumpPackage,
313 " Published user " + mProvidersByClassPerUser.keyAt(i)
314 + " content providers (by class):", needSep, map);
Amith Yamasani742a6712011-05-04 14:49:28 -0700315 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700316
317 if (dumpAll) {
Dianne Hackborn390517b2013-05-30 15:03:32 -0700318 needSep |= dumpProvidersByNameLocked(pw, dumpPackage,
319 " Single-user authority to provider mappings:", needSep, mSingletonByName);
Amith Yamasani742a6712011-05-04 14:49:28 -0700320
321 for (int i = 0; i < mProvidersByNamePerUser.size(); i++) {
Dianne Hackborn390517b2013-05-30 15:03:32 -0700322 needSep |= dumpProvidersByNameLocked(pw, dumpPackage,
323 " User " + mProvidersByNamePerUser.keyAt(i)
324 + " authority to provider mappings:", needSep,
325 mProvidersByNamePerUser.valueAt(i));
Amith Yamasani742a6712011-05-04 14:49:28 -0700326 }
327 }
Dianne Hackborn390517b2013-05-30 15:03:32 -0700328 return needSep;
Amith Yamasani742a6712011-05-04 14:49:28 -0700329 }
Marco Nelissende7408c2012-02-08 14:57:38 -0800330
Steven Timotiusfd55a942017-11-15 16:43:57 -0800331 private ArrayList<ContentProviderRecord> getProvidersForName(String name) {
Dianne Hackborn2d1b3782012-09-09 17:49:39 -0700332 ArrayList<ContentProviderRecord> allProviders = new ArrayList<ContentProviderRecord>();
Makoto Onuki0b575a32018-04-16 14:33:59 -0700333 final ArrayList<ContentProviderRecord> ret = new ArrayList<>();
334
335 final Predicate<ContentProviderRecord> filter = DumpUtils.filterRecord(name);
Marco Nelissende7408c2012-02-08 14:57:38 -0800336
Dianne Hackborn2d1b3782012-09-09 17:49:39 -0700337 synchronized (mAm) {
338 allProviders.addAll(mSingletonByClass.values());
339 for (int i=0; i<mProvidersByClassPerUser.size(); i++) {
340 allProviders.addAll(mProvidersByClassPerUser.valueAt(i).values());
Marco Nelissende7408c2012-02-08 14:57:38 -0800341 }
342
Makoto Onuki0b575a32018-04-16 14:33:59 -0700343 CollectionUtils.addIf(allProviders, ret, filter);
Marco Nelissende7408c2012-02-08 14:57:38 -0800344 }
Makoto Onuki0b575a32018-04-16 14:33:59 -0700345 // Sort by component name.
346 ret.sort(Comparator.comparing(WithComponentName::getComponentName));
347 return ret;
Steven Timotiusfd55a942017-11-15 16:43:57 -0800348 }
349
350 protected boolean dumpProvider(FileDescriptor fd, PrintWriter pw, String name, String[] args,
351 int opti, boolean dumpAll) {
352 ArrayList<ContentProviderRecord> providers = getProvidersForName(name);
Marco Nelissende7408c2012-02-08 14:57:38 -0800353
354 if (providers.size() <= 0) {
355 return false;
356 }
357
358 boolean needSep = false;
359 for (int i=0; i<providers.size(); i++) {
360 if (needSep) {
361 pw.println();
362 }
363 needSep = true;
364 dumpProvider("", fd, pw, providers.get(i), args, dumpAll);
365 }
366 return true;
367 }
368
369 /**
Hyunyoung Song9d56bc12017-05-24 16:48:41 -0700370 * Before invoking IApplicationThread.dumpProvider(), print meta information to the print
371 * writer and handle passed flags.
Marco Nelissende7408c2012-02-08 14:57:38 -0800372 */
373 private void dumpProvider(String prefix, FileDescriptor fd, PrintWriter pw,
374 final ContentProviderRecord r, String[] args, boolean dumpAll) {
Hyunyoung Song9d56bc12017-05-24 16:48:41 -0700375 for (String s: args) {
376 if (!dumpAll && s.contains("--proto")) {
377 if (r.proc != null && r.proc.thread != null) {
378 dumpToTransferPipe(null , fd, pw, r, args);
379 }
380 return;
381 }
382 }
Marco Nelissende7408c2012-02-08 14:57:38 -0800383 String innerPrefix = prefix + " ";
Dianne Hackborn2d1b3782012-09-09 17:49:39 -0700384 synchronized (mAm) {
Marco Nelissende7408c2012-02-08 14:57:38 -0800385 pw.print(prefix); pw.print("PROVIDER ");
Hyunyoung Song9d56bc12017-05-24 16:48:41 -0700386 pw.print(r);
387 pw.print(" pid=");
388 if (r.proc != null) {
389 pw.println(r.proc.pid);
390 } else {
391 pw.println("(not running)");
392 }
Marco Nelissende7408c2012-02-08 14:57:38 -0800393 if (dumpAll) {
Dianne Hackborn6ae8d182012-05-23 13:12:42 -0700394 r.dump(pw, innerPrefix, true);
Marco Nelissende7408c2012-02-08 14:57:38 -0800395 }
396 }
397 if (r.proc != null && r.proc.thread != null) {
398 pw.println(" Client:");
399 pw.flush();
Hyunyoung Song9d56bc12017-05-24 16:48:41 -0700400 dumpToTransferPipe(" ", fd, pw, r, args);
401 }
402 }
403
404 /**
Steven Timotiusfd55a942017-11-15 16:43:57 -0800405 * Similar to the dumpProvider, but only dumps the first matching provider.
406 * The provider is responsible for dumping as proto.
407 */
408 protected boolean dumpProviderProto(FileDescriptor fd, PrintWriter pw, String name,
409 String[] args) {
410 //add back the --proto arg, which was stripped out by PriorityDump
411 String[] newArgs = Arrays.copyOf(args, args.length + 1);
412 newArgs[args.length] = "--proto";
413
414 ArrayList<ContentProviderRecord> providers = getProvidersForName(name);
415
416 if (providers.size() <= 0) {
417 return false;
418 }
419
420 // Only dump the first provider, since we are dumping in proto format
421 for (int i = 0; i < providers.size(); i++) {
422 final ContentProviderRecord r = providers.get(i);
423 if (r.proc != null && r.proc.thread != null) {
424 dumpToTransferPipe(null, fd, pw, r, newArgs);
425 return true;
426 }
427 }
428 return false;
429 }
430
431 /**
Hyunyoung Song9d56bc12017-05-24 16:48:41 -0700432 * Invokes IApplicationThread.dumpProvider() on the thread of the specified provider without
433 * any meta string (e.g., provider info, indentation) written to the file descriptor.
434 */
435 private void dumpToTransferPipe(String prefix, FileDescriptor fd, PrintWriter pw,
436 final ContentProviderRecord r, String[] args) {
437 try {
438 TransferPipe tp = new TransferPipe();
Marco Nelissende7408c2012-02-08 14:57:38 -0800439 try {
Hyunyoung Song9d56bc12017-05-24 16:48:41 -0700440 r.proc.thread.dumpProvider(
441 tp.getWriteFd(), r.provider.asBinder(), args);
442 tp.setBufferPrefix(prefix);
443 // Short timeout, since blocking here can
444 // deadlock with the application.
445 tp.go(fd, 2000);
446 } finally {
447 tp.kill();
Marco Nelissende7408c2012-02-08 14:57:38 -0800448 }
Hyunyoung Song9d56bc12017-05-24 16:48:41 -0700449 } catch (IOException ex) {
450 pw.println(" Failure while dumping the provider: " + ex);
451 } catch (RemoteException ex) {
452 pw.println(" Got a RemoteException while dumping the service");
Marco Nelissende7408c2012-02-08 14:57:38 -0800453 }
454 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700455}