1742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani/*
2742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * Copyright (C) 2011 The Android Open Source Project
3742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani *
4742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * Licensed under the Apache License, Version 2.0 (the "License");
5742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * you may not use this file except in compliance with the License.
6742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * You may obtain a copy of the License at
7742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani *
8742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani *      http://www.apache.org/licenses/LICENSE-2.0
9742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani *
10742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * Unless required by applicable law or agreed to in writing, software
11742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * distributed under the License is distributed on an "AS IS" BASIS,
12742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * See the License for the specific language governing permissions and
14742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * limitations under the License.
15742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani */
16742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
17742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasanipackage com.android.server.am;
18742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
19742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.content.ComponentName;
20742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.os.Binder;
21de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissenimport android.os.RemoteException;
22f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle;
23742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.Slog;
24742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport android.util.SparseArray;
25cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackbornimport com.android.internal.os.TransferPipe;
26742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
27de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissenimport java.io.FileDescriptor;
28de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissenimport java.io.IOException;
29742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.io.PrintWriter;
30de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissenimport java.util.ArrayList;
31742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.HashMap;
32742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.Iterator;
33742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasaniimport java.util.Map;
34742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
35742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani/**
36742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * Keeps track of content providers by authority (name) and class. It separates the mapping by
37742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani * user and ones that are not user-specific (system providers).
38742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani */
39be4e6aaa0252dd7da28b7aa85beba982538efa46Dianne Hackbornpublic final class ProviderMap {
40742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
41742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private static final String TAG = "ProviderMap";
42742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
43742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private static final boolean DBG = false;
44742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
452d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn    private final ActivityManagerService mAm;
462d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn
477d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn    private final HashMap<String, ContentProviderRecord> mSingletonByName
48742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            = new HashMap<String, ContentProviderRecord>();
497d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn    private final HashMap<ComponentName, ContentProviderRecord> mSingletonByClass
50742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            = new HashMap<ComponentName, ContentProviderRecord>();
51742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
52742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private final SparseArray<HashMap<String, ContentProviderRecord>> mProvidersByNamePerUser
53742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            = new SparseArray<HashMap<String, ContentProviderRecord>>();
54742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    private final SparseArray<HashMap<ComponentName, ContentProviderRecord>> mProvidersByClassPerUser
55742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            = new SparseArray<HashMap<ComponentName, ContentProviderRecord>>();
56742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
572d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn    ProviderMap(ActivityManagerService am) {
582d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn        mAm = am;
592d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn    }
602d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn
61742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    ContentProviderRecord getProviderByName(String name) {
62742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return getProviderByName(name, -1);
63742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
64742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
65742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    ContentProviderRecord getProviderByName(String name, int userId) {
66742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (DBG) {
67742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.i(TAG, "getProviderByName: " + name + " , callingUid = " + Binder.getCallingUid());
68742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
69742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // Try to find it in the global list
707d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn        ContentProviderRecord record = mSingletonByName.get(name);
71742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (record != null) {
72742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return record;
73742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
74742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
75742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // Check the current user's list
76742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return getProvidersByName(userId).get(name);
77742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
78742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
79742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    ContentProviderRecord getProviderByClass(ComponentName name) {
80742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return getProviderByClass(name, -1);
81742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
82742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
83742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    ContentProviderRecord getProviderByClass(ComponentName name, int userId) {
84742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (DBG) {
85742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.i(TAG, "getProviderByClass: " + name + ", callingUid = " + Binder.getCallingUid());
86742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
87742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // Try to find it in the global list
887d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn        ContentProviderRecord record = mSingletonByClass.get(name);
89742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (record != null) {
90742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return record;
91742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
92742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
93742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        // Check the current user's list
94742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        return getProvidersByClass(userId).get(name);
95742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
96742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
97742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void putProviderByName(String name, ContentProviderRecord record) {
98742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (DBG) {
99742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.i(TAG, "putProviderByName: " + name + " , callingUid = " + Binder.getCallingUid()
100742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                + ", record uid = " + record.appInfo.uid);
101742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1027d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn        if (record.singleton) {
1037d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn            mSingletonByName.put(name, record);
104742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } else {
105f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn            final int userId = UserHandle.getUserId(record.appInfo.uid);
106742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            getProvidersByName(userId).put(name, record);
107742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
108742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
109742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
110742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    void putProviderByClass(ComponentName name, ContentProviderRecord record) {
111742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (DBG) {
112742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Slog.i(TAG, "putProviderByClass: " + name + " , callingUid = " + Binder.getCallingUid()
113742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                + ", record uid = " + record.appInfo.uid);
114742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
1157d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn        if (record.singleton) {
1167d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn            mSingletonByClass.put(name, record);
117742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } else {
118f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn            final int userId = UserHandle.getUserId(record.appInfo.uid);
119742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            getProvidersByClass(userId).put(name, record);
120742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
121742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
122742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1234120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn    void removeProviderByName(String name, int userId) {
1247d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn        if (mSingletonByName.containsKey(name)) {
125742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (DBG)
126742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Slog.i(TAG, "Removing from globalByName name=" + name);
1277d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn            mSingletonByName.remove(name);
128742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } else {
1294120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn            if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
130742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (DBG)
131742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Slog.i(TAG,
1324120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                        "Removing from providersByName name=" + name + " user=" + userId);
1334120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn            HashMap<String, ContentProviderRecord> map = getProvidersByName(userId);
1348809004bc5125d48a1bbfc292509514374cc4fceVairavan Srinivasan            // map returned by getProvidersByName wouldn't be null
1358809004bc5125d48a1bbfc292509514374cc4fceVairavan Srinivasan            map.remove(name);
1368809004bc5125d48a1bbfc292509514374cc4fceVairavan Srinivasan            if (map.size() == 0) {
1374120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                mProvidersByNamePerUser.remove(userId);
1388809004bc5125d48a1bbfc292509514374cc4fceVairavan Srinivasan            }
139742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
140742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
141742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1424120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn    void removeProviderByClass(ComponentName name, int userId) {
1437d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn        if (mSingletonByClass.containsKey(name)) {
144742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (DBG)
145742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Slog.i(TAG, "Removing from globalByClass name=" + name);
1467d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn            mSingletonByClass.remove(name);
147742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } else {
1484120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn            if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
149742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            if (DBG)
150742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani                Slog.i(TAG,
1514120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                        "Removing from providersByClass name=" + name + " user=" + userId);
1524120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn            HashMap<ComponentName, ContentProviderRecord> map = getProvidersByClass(userId);
1538809004bc5125d48a1bbfc292509514374cc4fceVairavan Srinivasan            // map returned by getProvidersByClass wouldn't be null
1548809004bc5125d48a1bbfc292509514374cc4fceVairavan Srinivasan            map.remove(name);
1558809004bc5125d48a1bbfc292509514374cc4fceVairavan Srinivasan            if (map.size() == 0) {
1564120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                mProvidersByClassPerUser.remove(userId);
1578809004bc5125d48a1bbfc292509514374cc4fceVairavan Srinivasan            }
158742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
159742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
160742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1614120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn    private HashMap<String, ContentProviderRecord> getProvidersByName(int userId) {
1624120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn        if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
163742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        final HashMap<String, ContentProviderRecord> map = mProvidersByNamePerUser.get(userId);
164742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (map == null) {
165742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            HashMap<String, ContentProviderRecord> newMap = new HashMap<String, ContentProviderRecord>();
166742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            mProvidersByNamePerUser.put(userId, newMap);
167742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return newMap;
168742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } else {
169742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return map;
170742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
171742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
172742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1734120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn    HashMap<ComponentName, ContentProviderRecord> getProvidersByClass(int userId) {
1744120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn        if (userId < 0) throw new IllegalArgumentException("Bad user " + userId);
1754120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn        final HashMap<ComponentName, ContentProviderRecord> map
1764120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                = mProvidersByClassPerUser.get(userId);
177742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (map == null) {
1784120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn            HashMap<ComponentName, ContentProviderRecord> newMap
1794120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                    = new HashMap<ComponentName, ContentProviderRecord>();
180742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            mProvidersByClassPerUser.put(userId, newMap);
181742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return newMap;
182742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        } else {
183742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            return map;
184742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
185742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
186742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
1875e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn    private boolean collectForceStopProvidersLocked(String name, int appId,
1885e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn            boolean doit, boolean evenPersistent, int userId,
1895e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn            HashMap<ComponentName, ContentProviderRecord> providers,
1905e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn            ArrayList<ContentProviderRecord> result) {
1915e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn        boolean didSomething = false;
1925e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn        for (ContentProviderRecord provider : providers.values()) {
1935e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn            if ((name == null || provider.info.packageName.equals(name))
1945e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                    && (provider.proc == null || evenPersistent || !provider.proc.persistent)) {
1955e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                if (!doit) {
1965e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                    return true;
1975e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                }
1985e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                didSomething = true;
1995e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                result.add(provider);
2005e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn            }
2015e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn        }
2025e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn        return didSomething;
2035e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn    }
2045e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn
2055e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn    boolean collectForceStopProviders(String name, int appId,
2065e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn            boolean doit, boolean evenPersistent, int userId,
2075e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn            ArrayList<ContentProviderRecord> result) {
2085e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn        boolean didSomething = collectForceStopProvidersLocked(name, appId, doit,
2095e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                evenPersistent, userId, mSingletonByClass, result);
2105e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn        if (!doit && didSomething) {
2115e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn            return true;
2125e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn        }
2135e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn        if (userId == UserHandle.USER_ALL) {
2145e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn            for (int i=0; i<mProvidersByClassPerUser.size(); i++) {
2155e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                if (collectForceStopProvidersLocked(name, appId, doit, evenPersistent,
2165e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                        userId, mProvidersByClassPerUser.valueAt(i), result)) {
2175e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                    if (!doit) {
2185e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                        return true;
2195e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                    }
2205e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                    didSomething = true;
2215e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn                }
2225e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn            }
2235e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn        } else {
2242d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn            HashMap<ComponentName, ContentProviderRecord> items
2252d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                    = getProvidersByClass(userId);
2262d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn            if (items != null) {
2272d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                didSomething |= collectForceStopProvidersLocked(name, appId, doit,
2282d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                        evenPersistent, userId, items, result);
2292d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn            }
2305e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn        }
2315e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn        return didSomething;
2325e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn    }
2335e03e2ca7d25b899b129baad2dd5eca6bf99d88aDianne Hackborn
234390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn    private boolean dumpProvidersByClassLocked(PrintWriter pw, boolean dumpAll, String dumpPackage,
235390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            String header, boolean needSep, HashMap<ComponentName, ContentProviderRecord> map) {
236742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it = map.entrySet().iterator();
237390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn        boolean written = false;
238742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        while (it.hasNext()) {
239742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Map.Entry<ComponentName, ContentProviderRecord> e = it.next();
240742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ContentProviderRecord r = e.getValue();
241390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
242390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                continue;
243390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            }
244390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            if (needSep) {
245390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                pw.println("");
246390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                needSep = false;
247390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            }
248390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            if (header != null) {
249390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                pw.println(header);
250390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                header = null;
251390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            }
252390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            written = true;
2536ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            pw.print("  * ");
2546ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            pw.println(r);
2556ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            r.dump(pw, "    ", dumpAll);
256742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
257390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn        return written;
258742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
259742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
260390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn    private boolean dumpProvidersByNameLocked(PrintWriter pw, String dumpPackage,
261390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            String header, boolean needSep, HashMap<String, ContentProviderRecord> map) {
262742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        Iterator<Map.Entry<String, ContentProviderRecord>> it = map.entrySet().iterator();
263390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn        boolean written = false;
264742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        while (it.hasNext()) {
265742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            Map.Entry<String, ContentProviderRecord> e = it.next();
266742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            ContentProviderRecord r = e.getValue();
267390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            if (dumpPackage != null && !dumpPackage.equals(r.appInfo.packageName)) {
268390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                continue;
269390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            }
270390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            if (needSep) {
271390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                pw.println("");
272390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                needSep = false;
273390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            }
274390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            if (header != null) {
275390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                pw.println(header);
276390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                header = null;
277390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            }
278390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            written = true;
279742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.print("  ");
280742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.print(e.getKey());
281742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            pw.print(": ");
2826ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn            pw.println(r.toShortString());
283742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
284390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn        return written;
285742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
286742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
287390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn    boolean dumpProvidersLocked(PrintWriter pw, boolean dumpAll, String dumpPackage) {
288390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn        boolean needSep = false;
289390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn
2907d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn        if (mSingletonByClass.size() > 0) {
2917ad34e5fb2bc8eda0a64377cedf8a8e899644dd9Dianne Hackborn            needSep |= dumpProvidersByClassLocked(pw, dumpAll, dumpPackage,
292390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                    "  Published single-user content providers (by class):", needSep,
293390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                    mSingletonByClass);
294742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
295742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
2967d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn        for (int i = 0; i < mProvidersByClassPerUser.size(); i++) {
2977d19e0242faac8017033dabb872cdf1542fa184cDianne Hackborn            HashMap<ComponentName, ContentProviderRecord> map = mProvidersByClassPerUser.valueAt(i);
298390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            needSep |= dumpProvidersByClassLocked(pw, dumpAll, dumpPackage,
299390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                    "  Published user " + mProvidersByClassPerUser.keyAt(i)
300390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                            + " content providers (by class):", needSep, map);
301742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
302742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
303742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        if (dumpAll) {
304390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn            needSep |= dumpProvidersByNameLocked(pw, dumpPackage,
305390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                    "  Single-user authority to provider mappings:", needSep, mSingletonByName);
306742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani
307742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            for (int i = 0; i < mProvidersByNamePerUser.size(); i++) {
308390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                needSep |= dumpProvidersByNameLocked(pw, dumpPackage,
309390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                        "  User " + mProvidersByNamePerUser.keyAt(i)
310390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                                + " authority to provider mappings:", needSep,
311390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn                        mProvidersByNamePerUser.valueAt(i));
312742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani            }
313742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani        }
314390517be2d60dd6e6264150c190c372d89bb331aDianne Hackborn        return needSep;
315742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani    }
316de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen
317de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen    protected boolean dumpProvider(FileDescriptor fd, PrintWriter pw, String name, String[] args,
318de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            int opti, boolean dumpAll) {
3192d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn        ArrayList<ContentProviderRecord> allProviders = new ArrayList<ContentProviderRecord>();
320de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen        ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
321de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen
3222d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn        synchronized (mAm) {
3232d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn            allProviders.addAll(mSingletonByClass.values());
3242d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn            for (int i=0; i<mProvidersByClassPerUser.size(); i++) {
3252d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                allProviders.addAll(mProvidersByClassPerUser.valueAt(i).values());
326de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            }
3272d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn
3282d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn            if ("all".equals(name)) {
3292d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                providers.addAll(allProviders);
3302d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn            } else {
3312d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                ComponentName componentName = name != null
3322d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                        ? ComponentName.unflattenFromString(name) : null;
3332d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                int objectId = 0;
3342d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                if (componentName == null) {
3352d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                    // Not a '/' separated full component name; maybe an object ID?
3362d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                    try {
3372d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                        objectId = Integer.parseInt(name, 16);
3382d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                        name = null;
3392d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                        componentName = null;
3402d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                    } catch (RuntimeException e) {
3412d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                    }
342de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                }
343de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen
3442d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                for (int i=0; i<allProviders.size(); i++) {
3452d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn                    ContentProviderRecord r1 = allProviders.get(i);
346de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    if (componentName != null) {
347de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                        if (r1.name.equals(componentName)) {
348de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                            providers.add(r1);
349de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                        }
350de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    } else if (name != null) {
351de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                        if (r1.name.flattenToString().contains(name)) {
352de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                            providers.add(r1);
353de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                        }
354de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    } else if (System.identityHashCode(r1) == objectId) {
355de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                        providers.add(r1);
356de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    }
357de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                }
358de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            }
359de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen        }
360de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen
361de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen        if (providers.size() <= 0) {
362de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            return false;
363de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen        }
364de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen
365de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen        boolean needSep = false;
366de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen        for (int i=0; i<providers.size(); i++) {
367de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            if (needSep) {
368de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                pw.println();
369de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            }
370de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            needSep = true;
371de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            dumpProvider("", fd, pw, providers.get(i), args, dumpAll);
372de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen        }
373de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen        return true;
374de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen    }
375de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen
376de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen    /**
377de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen     * Invokes IApplicationThread.dumpProvider() on the thread of the specified provider if
378de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen     * there is a thread associated with the provider.
379de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen     */
380de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen    private void dumpProvider(String prefix, FileDescriptor fd, PrintWriter pw,
381de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            final ContentProviderRecord r, String[] args, boolean dumpAll) {
382de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen        String innerPrefix = prefix + "  ";
3832d1b37819112274f538d1886c379ff337eb0d9edDianne Hackborn        synchronized (mAm) {
384de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            pw.print(prefix); pw.print("PROVIDER ");
385de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    pw.print(r);
386de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    pw.print(" pid=");
387de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    if (r.proc != null) pw.println(r.proc.pid);
388de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    else pw.println("(not running)");
389de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            if (dumpAll) {
3906ae8d1821822296df0606c9cd1c46708cc21cb58Dianne Hackborn                r.dump(pw, innerPrefix, true);
391de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            }
392de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen        }
393de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen        if (r.proc != null && r.proc.thread != null) {
394de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            pw.println("    Client:");
395de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            pw.flush();
396de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            try {
397de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                TransferPipe tp = new TransferPipe();
398de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                try {
399de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    r.proc.thread.dumpProvider(
400de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                            tp.getWriteFd().getFileDescriptor(), r.provider.asBinder(), args);
401de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    tp.setBufferPrefix("      ");
402de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    // Short timeout, since blocking here can
403de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    // deadlock with the application.
404de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    tp.go(fd, 2000);
405de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                } finally {
406de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                    tp.kill();
407de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                }
408de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            } catch (IOException ex) {
409de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                pw.println("      Failure while dumping the provider: " + ex);
410de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            } catch (RemoteException ex) {
411de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen                pw.println("      Got a RemoteException while dumping the service");
412de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen            }
413de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen        }
414de7408c94e09a34fe0779ee894c64b4315aec17cMarco Nelissen    }
415742a67127366c376fdf188ff99ba30b27d3bf90cAmith Yamasani}
416