1 /*
2  * Copyright (C) 2024 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.sdksandbox.helpers;
18 
19 import android.annotation.NonNull;
20 import android.content.Context;
21 import android.content.pm.ApplicationInfo;
22 import android.content.pm.PackageManager;
23 import android.content.pm.SharedLibraryInfo;
24 import android.os.UserHandle;
25 import android.util.Log;
26 
27 import java.util.List;
28 import java.util.stream.Collectors;
29 
30 /**
31  * Helper class for operations involving {@link PackageManager}
32  *
33  * @hide
34  */
35 public class PackageManagerHelper {
36     private static final String TAG = "SdkSandboxManager";
37     private final PackageManager mPackageManager;
38 
PackageManagerHelper(Context context, int callingUid)39     public PackageManagerHelper(Context context, int callingUid) {
40         UserHandle userHandle = UserHandle.getUserHandleForUid(callingUid);
41         Context userContext = context.createContextAsUser(userHandle, /* flags= */ 0);
42         mPackageManager = userContext.getPackageManager();
43     }
44 
45     /** Returns {@link SharedLibraryInfo} object for the SDK belonging to the package */
46     @NonNull
getSdkSharedLibraryInfoForSdk( @onNull String packageName, @NonNull String sdkName)47     public SharedLibraryInfo getSdkSharedLibraryInfoForSdk(
48             @NonNull String packageName, @NonNull String sdkName)
49             throws PackageManager.NameNotFoundException {
50         List<SharedLibraryInfo> sharedLibraryInfos = getSdkSharedLibraryInfo(packageName);
51         sharedLibraryInfos =
52                 sharedLibraryInfos.stream()
53                         .filter(sharedLibraryInfo -> sharedLibraryInfo.getName().equals(sdkName))
54                         .collect(Collectors.toList());
55 
56         if (sharedLibraryInfos.size() == 0) {
57             throw new PackageManager.NameNotFoundException(sdkName);
58         }
59         return sharedLibraryInfos.get(0);
60     }
61 
62     /**
63      * Returns a list of {@link SharedLibraryInfo} object for all the SDKs belonging to the package
64      */
65     @NonNull
getSdkSharedLibraryInfo(@onNull String packageName)66     public List<SharedLibraryInfo> getSdkSharedLibraryInfo(@NonNull String packageName)
67             throws PackageManager.NameNotFoundException {
68         ApplicationInfo info =
69                 mPackageManager.getApplicationInfo(
70                         packageName,
71                         PackageManager.ApplicationInfoFlags.of(
72                                 PackageManager.GET_SHARED_LIBRARY_FILES));
73 
74         return info.getSharedLibraryInfos().stream()
75                 .filter(
76                         sharedLibraryInfo ->
77                                 (sharedLibraryInfo.getType() == SharedLibraryInfo.TYPE_SDK_PACKAGE))
78                 .collect(Collectors.toList());
79     }
80 
81     /** Returns {@link PackageManager.Property} object of the propertyName for the package */
82     @NonNull
getProperty( @onNull String propertyName, @NonNull String packageName)83     public PackageManager.Property getProperty(
84             @NonNull String propertyName, @NonNull String packageName)
85             throws PackageManager.NameNotFoundException {
86         return mPackageManager.getProperty(propertyName, packageName);
87     }
88 
89     /** Returns {@link ApplicationInfo} for the {@link SharedLibraryInfo} with certain flags */
90     @NonNull
getApplicationInfoForSharedLibrary( @onNull SharedLibraryInfo sharedLibrary, int flags)91     public ApplicationInfo getApplicationInfoForSharedLibrary(
92             @NonNull SharedLibraryInfo sharedLibrary, int flags)
93             throws PackageManager.NameNotFoundException {
94         return mPackageManager.getPackageInfo(sharedLibrary.getDeclaringPackage(), flags)
95                 .applicationInfo;
96     }
97 
98     /** Returns the packageNames for the UID */
99     @NonNull
getPackageNamesForUid(int callingUid)100     public List<String> getPackageNamesForUid(int callingUid)
101             throws PackageManager.NameNotFoundException {
102         String[] possibleAppPackages = mPackageManager.getPackagesForUid(callingUid);
103 
104         if (possibleAppPackages == null || possibleAppPackages.length == 0) {
105             throw new PackageManager.NameNotFoundException(
106                     "Could not find package for " + callingUid);
107         }
108         if (possibleAppPackages.length > 1) {
109             Log.d(
110                     TAG,
111                     "More than one package name available for UID "
112                             + callingUid
113                             + ". Count: "
114                             + possibleAppPackages.length);
115         }
116         return List.of(possibleAppPackages);
117     }
118 }
119