1 /*
2  * Copyright (C) 2019 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;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.util.Pair;
22 
23 import com.android.internal.annotations.VisibleForTesting;
24 import com.android.server.pm.parsing.pkg.AndroidPackage;
25 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
26 import com.android.server.pm.parsing.pkg.ParsedPackage;
27 
28 import java.io.File;
29 import java.util.Set;
30 
31 
32 
33 // TODO: Move to .parsing sub-package
34 @VisibleForTesting
35 public interface PackageAbiHelper {
36     /**
37      * Derive and get the location of native libraries for the given package,
38      * which varies depending on where and how the package was installed.
39      */
40     @NonNull
deriveNativeLibraryPaths(AndroidPackage pkg, boolean isUpdatedSystemApp, File appLib32InstallDir)41     NativeLibraryPaths deriveNativeLibraryPaths(AndroidPackage pkg, boolean isUpdatedSystemApp,
42             File appLib32InstallDir);
43 
44     /**
45      * Calculate the abis for a bundled app. These can uniquely be determined from the contents of
46      * the system partition, i.e whether it contains 64 or 32 bit shared libraries etc. We do not
47      * validate any of this information, and instead assume that the system was built sensibly.
48      */
getBundledAppAbis(AndroidPackage pkg)49     Abis getBundledAppAbis(AndroidPackage pkg);
50 
51     /**
52      * Derive the ABI of a non-system package located at {@code pkg}. This information
53      * is derived purely on the basis of the contents of {@code pkg} and {@code cpuAbiOverride}.
54      *
55      * If {@code extractLibs} is true, native libraries are extracted from the app if required.
56      */
derivePackageAbi(AndroidPackage pkg, boolean isUpdatedSystemApp, String cpuAbiOverride, File appLib32InstallDir)57     Pair<Abis, NativeLibraryPaths> derivePackageAbi(AndroidPackage pkg, boolean isUpdatedSystemApp,
58             String cpuAbiOverride, File appLib32InstallDir) throws PackageManagerException;
59 
60     /**
61      * Calculates adjusted ABIs for a set of packages belonging to a shared user so that they all
62      * match. i.e, so that all packages can be run inside a single process if required.
63      *
64      * Optionally, callers can pass in a parsed package via {@code scannedPackage} in which case
65      * this function will either try and make the ABI for all packages in
66      * {@code packagesForUser} match {@code scannedPackage} or will update the ABI of
67      * {@code scannedPackage} to match the ABI selected for {@code packagesForUser}. This
68      * variant is used when installing or updating a package that belongs to a shared user.
69      *
70      * NOTE: We currently only match for the primary CPU abi string. Matching the secondary
71      * adds unnecessary complexity.
72      *
73      * @return the calculated primary abi that should be set for all non-specified packages
74      *         belonging to the shared user.
75      */
76     @Nullable
getAdjustedAbiForSharedUser( Set<PackageSetting> packagesForUser, AndroidPackage scannedPackage)77     String getAdjustedAbiForSharedUser(
78             Set<PackageSetting> packagesForUser, AndroidPackage scannedPackage);
79 
80     /**
81      * The native library paths and related properties that should be set on a
82      * {@link ParsedPackage}.
83      */
84     final class NativeLibraryPaths {
85         public final String nativeLibraryRootDir;
86         public final boolean nativeLibraryRootRequiresIsa;
87         public final String nativeLibraryDir;
88         public final String secondaryNativeLibraryDir;
89 
90         @VisibleForTesting
NativeLibraryPaths(String nativeLibraryRootDir, boolean nativeLibraryRootRequiresIsa, String nativeLibraryDir, String secondaryNativeLibraryDir)91         NativeLibraryPaths(String nativeLibraryRootDir,
92                 boolean nativeLibraryRootRequiresIsa, String nativeLibraryDir,
93                 String secondaryNativeLibraryDir) {
94             this.nativeLibraryRootDir = nativeLibraryRootDir;
95             this.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa;
96             this.nativeLibraryDir = nativeLibraryDir;
97             this.secondaryNativeLibraryDir = secondaryNativeLibraryDir;
98         }
99 
applyTo(ParsedPackage pkg)100         public void applyTo(ParsedPackage pkg) {
101             pkg.setNativeLibraryRootDir(nativeLibraryRootDir)
102                     .setNativeLibraryRootRequiresIsa(nativeLibraryRootRequiresIsa)
103                     .setNativeLibraryDir(nativeLibraryDir)
104                     .setSecondaryNativeLibraryDir(secondaryNativeLibraryDir);
105         }
106     }
107 
108     /**
109      * The primary and secondary ABIs that should be set on a package and its package setting.
110      */
111     final class Abis {
112         public final String primary;
113         public final String secondary;
114 
115         @VisibleForTesting
Abis(String primary, String secondary)116         Abis(String primary, String secondary) {
117             this.primary = primary;
118             this.secondary = secondary;
119         }
120 
Abis(AndroidPackage pkg, PackageSetting pkgSetting)121         Abis(AndroidPackage pkg, PackageSetting pkgSetting)  {
122             this(AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting),
123                     AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting));
124         }
125 
applyTo(ParsedPackage pkg)126         public void applyTo(ParsedPackage pkg) {
127             pkg.setPrimaryCpuAbi(primary)
128                     .setSecondaryCpuAbi(secondary);
129         }
applyTo(PackageSetting pkgSetting)130         public void applyTo(PackageSetting pkgSetting) {
131             // pkgSetting might be null during rescan following uninstall of updates
132             // to a bundled app, so accommodate that possibility.  The settings in
133             // that case will be established later from the parsed package.
134             //
135             // If the settings aren't null, sync them up with what we've derived.
136             if (pkgSetting != null) {
137                 pkgSetting.primaryCpuAbiString = primary;
138                 pkgSetting.secondaryCpuAbiString = secondary;
139             }
140         }
141     }
142 }
143