1 /*
2  * Copyright (C) 2020 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.media;
18 
19 import android.annotation.NonNull;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.pm.PackageManager;
24 import android.content.pm.PackageManagerInternal;
25 import android.content.pm.ResolveInfo;
26 import android.os.Binder;
27 import android.os.Process;
28 import android.os.UserHandle;
29 import android.text.TextUtils;
30 
31 import com.android.server.LocalServices;
32 
33 import java.io.PrintWriter;
34 import java.util.List;
35 
36 /** Util class for media server. */
37 /* package */ class MediaServerUtils {
38 
39     /**
40      * Returns whether the provided {@link ComponentName} and {@code action} resolve to a valid
41      * activity for the user defined by {@code userHandle}.
42      */
isValidActivityComponentName( @onNull Context context, @NonNull ComponentName componentName, @NonNull String action, @NonNull UserHandle userHandle)43     public static boolean isValidActivityComponentName(
44             @NonNull Context context,
45             @NonNull ComponentName componentName,
46             @NonNull String action,
47             @NonNull UserHandle userHandle) {
48         Intent intent = new Intent(action);
49         intent.setComponent(componentName);
50         List<ResolveInfo> resolveInfos =
51                 context.getPackageManager()
52                         .queryIntentActivitiesAsUser(intent, /* flags= */ 0, userHandle);
53         return !resolveInfos.isEmpty();
54     }
55 
56     /**
57      * Throws if the given {@code packageName} does not correspond to the given {@code uid}.
58      *
59      * <p>This method trusts calls from {@link Process#ROOT_UID} and {@link Process#SHELL_UID}.
60      *
61      * @param packageName A package name to verify (usually sent over binder by an app).
62      * @param uid The calling uid, obtained via {@link Binder#getCallingUid()}.
63      * @throws IllegalArgumentException If the given {@code packageName} does not correspond to the
64      *     given {@code uid}, and {@code uid} is not the root uid, or the shell uid.
65      */
enforcePackageName(String packageName, int uid)66     public static void enforcePackageName(String packageName, int uid) {
67         if (uid == Process.ROOT_UID || uid == Process.SHELL_UID) {
68             return;
69         }
70         if (TextUtils.isEmpty(packageName)) {
71             throw new IllegalArgumentException("packageName may not be empty");
72         }
73         final PackageManagerInternal packageManagerInternal =
74                 LocalServices.getService(PackageManagerInternal.class);
75         final int actualUid =
76                 packageManagerInternal.getPackageUid(
77                         packageName, 0 /* flags */, UserHandle.getUserId(uid));
78         if (!UserHandle.isSameApp(uid, actualUid)) {
79             throw new IllegalArgumentException(
80                     "packageName does not belong to the calling uid; "
81                             + "pkg="
82                             + packageName
83                             + ", uid="
84                             + uid);
85         }
86     }
87 
88     /**
89      * Verify that caller holds {@link android.Manifest.permission#DUMP}.
90      */
checkDumpPermission(Context context, String tag, PrintWriter pw)91     public static boolean checkDumpPermission(Context context, String tag, PrintWriter pw) {
92         if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
93                 != PackageManager.PERMISSION_GRANTED) {
94             pw.println("Permission Denial: can't dump " + tag + " from from pid="
95                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
96                     + " due to missing android.permission.DUMP permission");
97             return false;
98         } else {
99             return true;
100         }
101     }
102 }
103