1 /*
2  * Copyright (C) 2022 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.pm.resolution;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.UserIdInt;
22 import android.content.ComponentName;
23 import android.content.Intent;
24 import android.content.pm.ApplicationInfo;
25 import android.content.pm.ProviderInfo;
26 import android.content.pm.ResolveInfo;
27 import android.os.UserHandle;
28 import android.util.ArrayMap;
29 import android.util.Pair;
30 
31 import com.android.internal.pm.pkg.component.ParsedActivity;
32 import com.android.internal.pm.pkg.component.ParsedIntentInfo;
33 import com.android.internal.pm.pkg.component.ParsedMainComponent;
34 import com.android.internal.pm.pkg.component.ParsedProvider;
35 import com.android.internal.pm.pkg.component.ParsedService;
36 import com.android.server.pm.Computer;
37 import com.android.server.pm.DumpState;
38 import com.android.server.pm.UserManagerService;
39 import com.android.server.pm.parsing.PackageInfoUtils;
40 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
41 import com.android.server.pm.pkg.AndroidPackage;
42 import com.android.server.pm.pkg.PackageStateInternal;
43 import com.android.server.pm.pkg.PackageUserStateInternal;
44 import com.android.server.utils.WatchableImpl;
45 
46 import java.io.PrintWriter;
47 import java.util.ArrayList;
48 import java.util.Iterator;
49 import java.util.List;
50 import java.util.Map;
51 
52 public abstract class ComponentResolverBase extends WatchableImpl implements ComponentResolverApi {
53 
54     @NonNull
55     protected ComponentResolver.ActivityIntentResolver mActivities;
56 
57     @NonNull
58     protected ComponentResolver.ProviderIntentResolver mProviders;
59 
60     @NonNull
61     protected ComponentResolver.ReceiverIntentResolver mReceivers;
62 
63     @NonNull
64     protected ComponentResolver.ServiceIntentResolver mServices;
65 
66     /** Mapping from provider authority [first directory in content URI codePath) to provider. */
67     @NonNull
68     protected ArrayMap<String, ParsedProvider> mProvidersByAuthority;
69 
70     @NonNull
71     protected final UserManagerService mUserManager;
72 
ComponentResolverBase(@onNull UserManagerService userManager)73     protected ComponentResolverBase(@NonNull UserManagerService userManager) {
74         mUserManager = userManager;
75     }
76 
77     @Override
componentExists(@onNull ComponentName componentName)78     public boolean componentExists(@NonNull ComponentName componentName) {
79         ParsedMainComponent component = mActivities.mActivities.get(componentName);
80         if (component != null) {
81             return true;
82         }
83         component = mReceivers.mActivities.get(componentName);
84         if (component != null) {
85             return true;
86         }
87         component = mServices.mServices.get(componentName);
88         if (component != null) {
89             return true;
90         }
91         return mProviders.mProviders.get(componentName) != null;
92     }
93 
94     @Nullable
95     @Override
getActivity(@onNull ComponentName component)96     public ParsedActivity getActivity(@NonNull ComponentName component) {
97         return mActivities.mActivities.get(component);
98     }
99 
100     @Nullable
101     @Override
getProvider(@onNull ComponentName component)102     public ParsedProvider getProvider(@NonNull ComponentName component) {
103         return mProviders.mProviders.get(component);
104     }
105 
106     @Nullable
107     @Override
getReceiver(@onNull ComponentName component)108     public ParsedActivity getReceiver(@NonNull ComponentName component) {
109         return mReceivers.mActivities.get(component);
110     }
111 
112     @Nullable
113     @Override
getService(@onNull ComponentName component)114     public ParsedService getService(@NonNull ComponentName component) {
115         return mServices.mServices.get(component);
116     }
117 
118     /**
119      * Returns {@code true} if the given activity is defined by some package
120      */
121     @Override
isActivityDefined(@onNull ComponentName component)122     public boolean isActivityDefined(@NonNull ComponentName component) {
123         return mActivities.mActivities.get(component) != null;
124     }
125 
126     @Nullable
127     @Override
queryActivities(@onNull Computer computer, @NonNull Intent intent, @Nullable String resolvedType, long flags, int userId)128     public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
129             @Nullable String resolvedType, long flags, int userId) {
130         return mActivities.queryIntent(computer, intent, resolvedType, flags, userId);
131     }
132 
133     @Nullable
134     @Override
queryActivities(@onNull Computer computer, @NonNull Intent intent, @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities, int userId)135     public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
136             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities,
137             int userId) {
138         return mActivities.queryIntentForPackage(computer, intent, resolvedType, flags, activities,
139                 userId);
140     }
141 
142     @Nullable
143     @Override
queryProvider(@onNull Computer computer, @NonNull String authority, long flags, int userId)144     public ProviderInfo queryProvider(@NonNull Computer computer, @NonNull String authority,
145             long flags, int userId) {
146         final ParsedProvider p = mProvidersByAuthority.get(authority);
147         if (p == null) {
148             return null;
149         }
150         PackageStateInternal packageState = computer.getPackageStateInternal(p.getPackageName());
151         if (packageState == null) {
152             return null;
153         }
154         final AndroidPackage pkg = packageState.getPkg();
155         if (pkg == null) {
156             return null;
157         }
158         final PackageUserStateInternal state = packageState.getUserStateOrDefault(userId);
159         ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo(
160                 pkg, flags, state, userId, packageState);
161         if (appInfo == null) {
162             return null;
163         }
164         return PackageInfoUtils.generateProviderInfo(pkg, p, flags, state, appInfo, userId,
165                 packageState);
166     }
167 
168     @Nullable
169     @Override
queryProviders(@onNull Computer computer, @NonNull Intent intent, @Nullable String resolvedType, long flags, int userId)170     public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
171             @Nullable String resolvedType, long flags, int userId) {
172         return mProviders.queryIntent(computer, intent, resolvedType, flags, userId);
173     }
174 
175     @Nullable
176     @Override
queryProviders(@onNull Computer computer, @NonNull Intent intent, @Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers, @UserIdInt int userId)177     public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
178             @Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers,
179             @UserIdInt int userId) {
180         return mProviders.queryIntentForPackage(computer, intent, resolvedType, flags, providers,
181                 userId);
182     }
183 
184     @Nullable
185     @Override
queryProviders(@onNull Computer computer, @Nullable String processName, @Nullable String metaDataKey, int uid, long flags, int userId)186     public List<ProviderInfo> queryProviders(@NonNull Computer computer,
187             @Nullable String processName, @Nullable String metaDataKey, int uid, long flags,
188             int userId) {
189         if (!mUserManager.exists(userId)) {
190             return null;
191         }
192         List<ProviderInfo> providerList = null;
193         PackageInfoUtils.CachedApplicationInfoGenerator appInfoGenerator = null;
194         for (int i = mProviders.mProviders.size() - 1; i >= 0; --i) {
195             final ParsedProvider p = mProviders.mProviders.valueAt(i);
196             if (p.getAuthority() == null) {
197                 continue;
198             }
199 
200             final PackageStateInternal ps = computer.getPackageStateInternal(p.getPackageName());
201             if (ps == null) {
202                 continue;
203             }
204 
205             AndroidPackage pkg = ps.getPkg();
206             if (pkg == null) {
207                 continue;
208             }
209 
210             if (processName != null && (!p.getProcessName().equals(processName)
211                     || !UserHandle.isSameApp(pkg.getUid(), uid))) {
212                 continue;
213             }
214             // See PM.queryContentProviders()'s javadoc for why we have the metaData parameter.
215             if (metaDataKey != null && !p.getMetaData().containsKey(metaDataKey)) {
216                 continue;
217             }
218             if (appInfoGenerator == null) {
219                 appInfoGenerator = new PackageInfoUtils.CachedApplicationInfoGenerator();
220             }
221             final PackageUserStateInternal state = ps.getUserStateOrDefault(userId);
222             final ApplicationInfo appInfo =
223                     appInfoGenerator.generate(pkg, flags, state, userId, ps);
224             if (appInfo == null) {
225                 continue;
226             }
227 
228             final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
229                     pkg, p, flags, state, appInfo, userId, ps);
230             if (info == null) {
231                 continue;
232             }
233             if (providerList == null) {
234                 providerList = new ArrayList<>(i + 1);
235             }
236             providerList.add(info);
237         }
238         return providerList;
239     }
240 
241     @Nullable
242     @Override
queryReceivers(@onNull Computer computer, @NonNull Intent intent, @Nullable String resolvedType, long flags, int userId)243     public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
244             @Nullable String resolvedType, long flags, int userId) {
245         return mReceivers.queryIntent(computer, intent, resolvedType, flags, userId);
246     }
247 
248     @Nullable
249     @Override
queryReceivers(@onNull Computer computer, @NonNull Intent intent, @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers, @UserIdInt int userId)250     public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
251             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers,
252             @UserIdInt int userId) {
253         return mReceivers.queryIntentForPackage(computer, intent, resolvedType, flags, receivers,
254                 userId);
255     }
256 
257     @Nullable
258     @Override
queryServices(@onNull Computer computer, @NonNull Intent intent, @Nullable String resolvedType, long flags, @UserIdInt int userId)259     public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
260             @Nullable String resolvedType, long flags, @UserIdInt int userId) {
261         return mServices.queryIntent(computer, intent, resolvedType, flags, userId);
262     }
263 
264     @Nullable
265     @Override
queryServices(@onNull Computer computer, @NonNull Intent intent, @Nullable String resolvedType, long flags, @NonNull List<ParsedService> services, @UserIdInt int userId)266     public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
267             @Nullable String resolvedType, long flags, @NonNull List<ParsedService> services,
268             @UserIdInt int userId) {
269         return mServices.queryIntentForPackage(computer, intent, resolvedType, flags, services,
270                 userId);
271     }
272 
273     @Override
querySyncProviders(@onNull Computer computer, @NonNull List<String> outNames, @NonNull List<ProviderInfo> outInfo, boolean safeMode, int userId)274     public void querySyncProviders(@NonNull Computer computer, @NonNull List<String> outNames,
275             @NonNull List<ProviderInfo> outInfo, boolean safeMode, int userId) {
276         PackageInfoUtils.CachedApplicationInfoGenerator appInfoGenerator = null;
277         for (int i = mProvidersByAuthority.size() - 1; i >= 0; --i) {
278             final ParsedProvider p = mProvidersByAuthority.valueAt(i);
279             if (!p.isSyncable()) {
280                 continue;
281             }
282 
283             final PackageStateInternal ps = computer.getPackageStateInternal(p.getPackageName());
284             if (ps == null) {
285                 continue;
286             }
287 
288             final AndroidPackage pkg = ps.getPkg();
289             if (pkg == null) {
290                 continue;
291             }
292 
293             if (safeMode && !ps.isSystem()) {
294                 continue;
295             }
296             if (appInfoGenerator == null) {
297                 appInfoGenerator = new PackageInfoUtils.CachedApplicationInfoGenerator();
298             }
299             final PackageUserStateInternal state = ps.getUserStateOrDefault(userId);
300             final ApplicationInfo appInfo =
301                     appInfoGenerator.generate(pkg, 0, state, userId, ps);
302             if (appInfo == null) {
303                 continue;
304             }
305 
306             final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
307                     pkg, p, 0, state, appInfo, userId, ps);
308             if (info == null) {
309                 continue;
310             }
311             outNames.add(mProvidersByAuthority.keyAt(i));
312             outInfo.add(info);
313         }
314     }
315 
316     @Override
dumpActivityResolvers(@onNull PrintWriter pw, @NonNull DumpState dumpState, @NonNull String packageName)317     public void dumpActivityResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
318             @NonNull String packageName) {
319         if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
320                         : "Activity Resolver Table:", "  ", packageName,
321                 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
322             dumpState.setTitlePrinted(true);
323         }
324     }
325 
326     @Override
dumpProviderResolvers(@onNull PrintWriter pw, @NonNull DumpState dumpState, @NonNull String packageName)327     public void dumpProviderResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
328             @NonNull String packageName) {
329         if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:"
330                         : "Provider Resolver Table:", "  ", packageName,
331                 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
332             dumpState.setTitlePrinted(true);
333         }
334     }
335 
336     @Override
dumpReceiverResolvers(@onNull PrintWriter pw, @NonNull DumpState dumpState, @NonNull String packageName)337     public void dumpReceiverResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
338             @NonNull String packageName) {
339         if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
340                         : "Receiver Resolver Table:", "  ", packageName,
341                 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
342             dumpState.setTitlePrinted(true);
343         }
344     }
345 
346     @Override
dumpServiceResolvers(@onNull PrintWriter pw, @NonNull DumpState dumpState, @NonNull String packageName)347     public void dumpServiceResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
348             @NonNull String packageName) {
349         if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
350                         : "Service Resolver Table:", "  ", packageName,
351                 dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
352             dumpState.setTitlePrinted(true);
353         }
354     }
355 
356     @Override
dumpContentProviders(@onNull Computer computer, @NonNull PrintWriter pw, @NonNull DumpState dumpState, @NonNull String packageName)357     public void dumpContentProviders(@NonNull Computer computer, @NonNull PrintWriter pw,
358             @NonNull DumpState dumpState, @NonNull String packageName) {
359         boolean printedSomething = false;
360         for (ParsedProvider p : mProviders.mProviders.values()) {
361             if (packageName != null && !packageName.equals(p.getPackageName())) {
362                 continue;
363             }
364             if (!printedSomething) {
365                 if (dumpState.onTitlePrinted()) {
366                     pw.println();
367                 }
368                 pw.println("Registered ContentProviders:");
369                 printedSomething = true;
370             }
371             pw.print("  ");
372             ComponentName.printShortString(pw, p.getPackageName(), p.getName());
373             pw.println(":");
374             pw.print("    ");
375             pw.println(p.toString());
376         }
377         printedSomething = false;
378         for (Map.Entry<String, ParsedProvider> entry :
379                 mProvidersByAuthority.entrySet()) {
380             ParsedProvider p = entry.getValue();
381             if (packageName != null && !packageName.equals(p.getPackageName())) {
382                 continue;
383             }
384             if (!printedSomething) {
385                 if (dumpState.onTitlePrinted()) {
386                     pw.println();
387                 }
388                 pw.println("ContentProvider Authorities:");
389                 printedSomething = true;
390             }
391             pw.print("  [");
392             pw.print(entry.getKey());
393             pw.println("]:");
394             pw.print("    ");
395             pw.println(p.toString());
396 
397             AndroidPackage pkg = computer.getPackage(p.getPackageName());
398 
399             if (pkg != null) {
400                 pw.print("      applicationInfo=");
401                 pw.println(AndroidPackageUtils.generateAppInfoWithoutState(pkg));
402             }
403         }
404     }
405 
406     @Override
dumpServicePermissions(@onNull PrintWriter pw, @NonNull DumpState dumpState)407     public void dumpServicePermissions(@NonNull PrintWriter pw, @NonNull DumpState dumpState) {
408         if (dumpState.onTitlePrinted()) pw.println();
409         pw.println("Service permissions:");
410 
411         final Iterator<Pair<ParsedService, ParsedIntentInfo>> filterIterator =
412                 mServices.filterIterator();
413         while (filterIterator.hasNext()) {
414             final Pair<ParsedService, ParsedIntentInfo> pair = filterIterator.next();
415             ParsedService service = pair.first;
416 
417             final String permission = service.getPermission();
418             if (permission != null) {
419                 pw.print("    ");
420                 pw.print(service.getComponentName().flattenToShortString());
421                 pw.print(": ");
422                 pw.println(permission);
423             }
424         }
425     }
426 
427 }
428