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.ArraySet;
22 import android.util.Pair;
23 
24 import com.android.internal.annotations.VisibleForTesting;
25 import com.android.internal.pm.parsing.pkg.ParsedPackage;
26 import com.android.server.pm.pkg.AndroidPackage;
27 import com.android.server.pm.pkg.PackageStateInternal;
28 
29 import java.io.File;
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 isSystemApp, boolean isUpdatedSystemApp, File appLib32InstallDir)41     NativeLibraryPaths deriveNativeLibraryPaths(AndroidPackage pkg, boolean isSystemApp,
42             boolean isUpdatedSystemApp, 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 isSystemApp, boolean isUpdatedSystemApp, String cpuAbiOverride, File appLib32InstallDir)57     Pair<Abis, NativeLibraryPaths> derivePackageAbi(AndroidPackage pkg, boolean isSystemApp,
58             boolean isUpdatedSystemApp, String cpuAbiOverride, File appLib32InstallDir)
59             throws PackageManagerException;
60 
61     /**
62      * Calculates adjusted ABIs for a set of packages belonging to a shared user so that they all
63      * match. i.e, so that all packages can be run inside a single process if required.
64      *
65      * Optionally, callers can pass in a parsed package via {@code scannedPackage} in which case
66      * this function will either try and make the ABI for all packages in
67      * {@code packagesForUser} match {@code scannedPackage} or will update the ABI of
68      * {@code scannedPackage} to match the ABI selected for {@code packagesForUser}. This
69      * variant is used when installing or updating a package that belongs to a shared user.
70      *
71      * NOTE: We currently only match for the primary CPU abi string. Matching the secondary
72      * adds unnecessary complexity.
73      *
74      * @return the calculated primary abi that should be set for all non-specified packages
75      *         belonging to the shared user.
76      */
77     @Nullable
getAdjustedAbiForSharedUser(ArraySet<? extends PackageStateInternal> packagesForUser, AndroidPackage scannedPackage)78     String getAdjustedAbiForSharedUser(ArraySet<? extends PackageStateInternal> packagesForUser,
79             AndroidPackage scannedPackage);
80 
81     /**
82      * The native library paths and related properties that should be set on a
83      * {@link ParsedPackage}.
84      */
85     final class NativeLibraryPaths {
86         public final String nativeLibraryRootDir;
87         public final boolean nativeLibraryRootRequiresIsa;
88         public final String nativeLibraryDir;
89         public final String secondaryNativeLibraryDir;
90 
91         @VisibleForTesting
NativeLibraryPaths(String nativeLibraryRootDir, boolean nativeLibraryRootRequiresIsa, String nativeLibraryDir, String secondaryNativeLibraryDir)92         NativeLibraryPaths(String nativeLibraryRootDir,
93                 boolean nativeLibraryRootRequiresIsa, String nativeLibraryDir,
94                 String secondaryNativeLibraryDir) {
95             this.nativeLibraryRootDir = nativeLibraryRootDir;
96             this.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa;
97             this.nativeLibraryDir = nativeLibraryDir;
98             this.secondaryNativeLibraryDir = secondaryNativeLibraryDir;
99         }
100 
applyTo(ParsedPackage pkg)101         public void applyTo(ParsedPackage pkg) {
102             pkg.setNativeLibraryRootDir(nativeLibraryRootDir)
103                     .setNativeLibraryRootRequiresIsa(nativeLibraryRootRequiresIsa)
104                     .setNativeLibraryDir(nativeLibraryDir)
105                     .setSecondaryNativeLibraryDir(secondaryNativeLibraryDir);
106         }
107     }
108 
109     /**
110      * The primary and secondary ABIs that should be set on a package and its package setting.
111      */
112     final class Abis {
113         public final String primary;
114         public final String secondary;
115 
116         @VisibleForTesting
Abis(String primary, String secondary)117         Abis(String primary, String secondary) {
118             this.primary = primary;
119             this.secondary = secondary;
120         }
121 
applyTo(ParsedPackage pkg)122         public void applyTo(ParsedPackage pkg) {
123             pkg.setPrimaryCpuAbi(primary)
124                     .setSecondaryCpuAbi(secondary);
125         }
applyTo(PackageSetting pkgSetting)126         public void applyTo(PackageSetting pkgSetting) {
127             // pkgSetting might be null during rescan following uninstall of updates
128             // to a bundled app, so accommodate that possibility.  The settings in
129             // that case will be established later from the parsed package.
130             //
131             // If the settings aren't null, sync them up with what we've derived.
132             if (pkgSetting != null) {
133                 pkgSetting.setPrimaryCpuAbi(primary);
134                 pkgSetting.setSecondaryCpuAbi(secondary);
135             }
136         }
137     }
138 }
139