blob: 259200b92597bba3b01db968ce56bd4b0990c816 [file] [log] [blame]
Patrick Baumannf62817e2019-05-31 10:46:53 -07001/*
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
17package com.android.server.pm;
18
19import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
20import static android.content.pm.PackageParser.isApkFile;
21import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
22
23import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
24import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
25import static com.android.server.pm.InstructionSets.getPreferredInstructionSet;
26import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet;
27
28import android.annotation.Nullable;
29import android.content.pm.ApplicationInfo;
30import android.content.pm.PackageManager;
31import android.content.pm.PackageParser;
32import android.os.Build;
33import android.os.Environment;
34import android.os.FileUtils;
35import android.os.Trace;
36import android.text.TextUtils;
Patrick Baumann235e52e2019-07-25 16:28:45 -070037import android.util.Pair;
Patrick Baumannf62817e2019-05-31 10:46:53 -070038import android.util.Slog;
39
40import com.android.internal.content.NativeLibraryHelper;
41import com.android.internal.util.ArrayUtils;
42
43import dalvik.system.VMRuntime;
44
45import libcore.io.IoUtils;
46
47import java.io.File;
48import java.io.IOException;
Patrick Baumannf62817e2019-05-31 10:46:53 -070049import java.util.Set;
50
51final class PackageAbiHelperImpl implements PackageAbiHelper {
52
Patrick Baumannf62817e2019-05-31 10:46:53 -070053 private static String calculateBundledApkRoot(final String codePathString) {
54 final File codePath = new File(codePathString);
55 final File codeRoot;
56 if (FileUtils.contains(Environment.getRootDirectory(), codePath)) {
57 codeRoot = Environment.getRootDirectory();
58 } else if (FileUtils.contains(Environment.getOemDirectory(), codePath)) {
59 codeRoot = Environment.getOemDirectory();
60 } else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) {
61 codeRoot = Environment.getVendorDirectory();
62 } else if (FileUtils.contains(Environment.getOdmDirectory(), codePath)) {
63 codeRoot = Environment.getOdmDirectory();
64 } else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) {
65 codeRoot = Environment.getProductDirectory();
66 } else if (FileUtils.contains(Environment.getSystemExtDirectory(), codePath)) {
67 codeRoot = Environment.getSystemExtDirectory();
68 } else if (FileUtils.contains(Environment.getOdmDirectory(), codePath)) {
69 codeRoot = Environment.getOdmDirectory();
Dario Freni7d038cd2019-10-09 15:43:38 +010070 } else if (FileUtils.contains(Environment.getApexDirectory(), codePath)) {
71 String fullPath = codePath.getAbsolutePath();
72 String[] parts = fullPath.split(File.separator);
73 if (parts.length > 2) {
74 codeRoot = new File(parts[1] + File.separator + parts[2]);
75 } else {
76 Slog.w(PackageManagerService.TAG, "Can't canonicalize code path " + codePath);
77 codeRoot = Environment.getApexDirectory();
78 }
Patrick Baumannf62817e2019-05-31 10:46:53 -070079 } else {
80 // Unrecognized code path; take its top real segment as the apk root:
81 // e.g. /something/app/blah.apk => /something
82 try {
83 File f = codePath.getCanonicalFile();
84 File parent = f.getParentFile(); // non-null because codePath is a file
85 File tmp;
86 while ((tmp = parent.getParentFile()) != null) {
87 f = parent;
88 parent = tmp;
89 }
90 codeRoot = f;
91 Slog.w(PackageManagerService.TAG, "Unrecognized code path "
92 + codePath + " - using " + codeRoot);
93 } catch (IOException e) {
94 // Can't canonicalize the code path -- shenanigans?
95 Slog.w(PackageManagerService.TAG, "Can't canonicalize code path " + codePath);
96 return Environment.getRootDirectory().getPath();
97 }
98 }
99 return codeRoot.getPath();
100 }
101
102 // Utility method that returns the relative package path with respect
103 // to the installation directory. Like say for /data/data/com.test-1.apk
104 // string com.test-1 is returned.
105 private static String deriveCodePathName(String codePath) {
106 if (codePath == null) {
107 return null;
108 }
109 final File codeFile = new File(codePath);
110 final String name = codeFile.getName();
111 if (codeFile.isDirectory()) {
112 return name;
113 } else if (name.endsWith(".apk") || name.endsWith(".tmp")) {
114 final int lastDot = name.lastIndexOf('.');
115 return name.substring(0, lastDot);
116 } else {
117 Slog.w(PackageManagerService.TAG, "Odd, " + codePath + " doesn't look like an APK");
118 return null;
119 }
120 }
121
122 private static void maybeThrowExceptionForMultiArchCopy(String message, int copyRet) throws
123 PackageManagerException {
124 if (copyRet < 0) {
125 if (copyRet != PackageManager.NO_NATIVE_LIBRARIES
126 && copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
127 throw new PackageManagerException(copyRet, message);
128 }
129 }
130 }
131
Patrick Baumann235e52e2019-07-25 16:28:45 -0700132 @Override
133 public NativeLibraryPaths getNativeLibraryPaths(
134 PackageParser.Package pkg, File appLib32InstallDir) {
135 return getNativeLibraryPaths(new Abis(pkg), appLib32InstallDir, pkg.codePath,
136 pkg.applicationInfo.sourceDir, pkg.applicationInfo.isSystemApp(),
137 pkg.applicationInfo.isUpdatedSystemApp());
138 }
139
140 private static NativeLibraryPaths getNativeLibraryPaths(final Abis abis,
141 final File appLib32InstallDir, final String codePath, final String sourceDir,
142 final boolean isSystemApp, final boolean isUpdatedSystemApp) {
143 final File codeFile = new File(codePath);
144 final boolean bundledApp = isSystemApp && !isUpdatedSystemApp;
145
146 final String nativeLibraryRootDir;
147 final boolean nativeLibraryRootRequiresIsa;
148 final String nativeLibraryDir;
149 final String secondaryNativeLibraryDir;
150
151 if (isApkFile(codeFile)) {
152 // Monolithic install
153 if (bundledApp) {
154 // If "/system/lib64/apkname" exists, assume that is the per-package
155 // native library directory to use; otherwise use "/system/lib/apkname".
156 final String apkRoot = calculateBundledApkRoot(sourceDir);
157 final boolean is64Bit = VMRuntime.is64BitInstructionSet(
158 getPrimaryInstructionSet(abis));
159
160 // This is a bundled system app so choose the path based on the ABI.
161 // if it's a 64 bit abi, use lib64 otherwise use lib32. Note that this
162 // is just the default path.
163 final String apkName = deriveCodePathName(codePath);
164 final String libDir = is64Bit ? LIB64_DIR_NAME : LIB_DIR_NAME;
165 nativeLibraryRootDir = Environment.buildPath(new File(apkRoot), libDir,
166 apkName).getAbsolutePath();
167
168 if (abis.secondary != null) {
169 final String secondaryLibDir = is64Bit ? LIB_DIR_NAME : LIB64_DIR_NAME;
170 secondaryNativeLibraryDir = Environment.buildPath(new File(apkRoot),
171 secondaryLibDir, apkName).getAbsolutePath();
172 } else {
173 secondaryNativeLibraryDir = null;
174 }
175 } else {
176 final String apkName = deriveCodePathName(codePath);
177 nativeLibraryRootDir = new File(appLib32InstallDir, apkName)
178 .getAbsolutePath();
179 secondaryNativeLibraryDir = null;
180 }
181
182 nativeLibraryRootRequiresIsa = false;
183 nativeLibraryDir = nativeLibraryRootDir;
184 } else {
185 // Cluster install
186 nativeLibraryRootDir = new File(codeFile, LIB_DIR_NAME).getAbsolutePath();
187 nativeLibraryRootRequiresIsa = true;
188
189 nativeLibraryDir = new File(nativeLibraryRootDir,
190 getPrimaryInstructionSet(abis)).getAbsolutePath();
191
192 if (abis.secondary != null) {
193 secondaryNativeLibraryDir = new File(nativeLibraryRootDir,
194 VMRuntime.getInstructionSet(abis.secondary)).getAbsolutePath();
195 } else {
196 secondaryNativeLibraryDir = null;
197 }
198 }
199 return new NativeLibraryPaths(nativeLibraryRootDir, nativeLibraryRootRequiresIsa,
200 nativeLibraryDir, secondaryNativeLibraryDir);
201 }
202
203 @Override
204 public Abis getBundledAppAbis(PackageParser.Package pkg) {
205 final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath());
206
207 // If "/system/lib64/apkname" exists, assume that is the per-package
208 // native library directory to use; otherwise use "/system/lib/apkname".
209 final String apkRoot = calculateBundledApkRoot(pkg.applicationInfo.sourceDir);
210 final Abis abis = getBundledAppAbi(pkg, apkRoot, apkName);
211 return abis;
212 }
213
214 /**
215 * Deduces the ABI of a bundled app and sets the relevant fields on the
216 * parsed pkg object.
217 *
218 * @param apkRoot the root of the installed apk, something like {@code /system} or
219 * {@code /oem} under which system libraries are installed.
220 * @param apkName the name of the installed package.
221 */
222 private Abis getBundledAppAbi(PackageParser.Package pkg, String apkRoot, String apkName) {
223 final File codeFile = new File(pkg.codePath);
224
225 final boolean has64BitLibs;
226 final boolean has32BitLibs;
227
228 final String primaryCpuAbi;
229 final String secondaryCpuAbi;
230 if (isApkFile(codeFile)) {
231 // Monolithic install
232 has64BitLibs =
233 (new File(apkRoot, new File(LIB64_DIR_NAME, apkName).getPath())).exists();
234 has32BitLibs = (new File(apkRoot, new File(LIB_DIR_NAME, apkName).getPath())).exists();
235 } else {
236 // Cluster install
237 final File rootDir = new File(codeFile, LIB_DIR_NAME);
238 if (!ArrayUtils.isEmpty(Build.SUPPORTED_64_BIT_ABIS)
239 && !TextUtils.isEmpty(Build.SUPPORTED_64_BIT_ABIS[0])) {
240 final String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_64_BIT_ABIS[0]);
241 has64BitLibs = (new File(rootDir, isa)).exists();
242 } else {
243 has64BitLibs = false;
244 }
245 if (!ArrayUtils.isEmpty(Build.SUPPORTED_32_BIT_ABIS)
246 && !TextUtils.isEmpty(Build.SUPPORTED_32_BIT_ABIS[0])) {
247 final String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_32_BIT_ABIS[0]);
248 has32BitLibs = (new File(rootDir, isa)).exists();
249 } else {
250 has32BitLibs = false;
251 }
252 }
253
254 if (has64BitLibs && !has32BitLibs) {
255 // The package has 64 bit libs, but not 32 bit libs. Its primary
256 // ABI should be 64 bit. We can safely assume here that the bundled
257 // native libraries correspond to the most preferred ABI in the list.
258
259 primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
260 secondaryCpuAbi = null;
261 } else if (has32BitLibs && !has64BitLibs) {
262 // The package has 32 bit libs but not 64 bit libs. Its primary
263 // ABI should be 32 bit.
264
265 primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
266 secondaryCpuAbi = null;
267 } else if (has32BitLibs && has64BitLibs) {
268 // The application has both 64 and 32 bit bundled libraries. We check
269 // here that the app declares multiArch support, and warn if it doesn't.
270 //
271 // We will be lenient here and record both ABIs. The primary will be the
272 // ABI that's higher on the list, i.e, a device that's configured to prefer
273 // 64 bit apps will see a 64 bit primary ABI,
274
275 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) == 0) {
276 Slog.e(PackageManagerService.TAG,
277 "Package " + pkg + " has multiple bundled libs, but is not multiarch.");
278 }
279
280 if (VMRuntime.is64BitInstructionSet(getPreferredInstructionSet())) {
281 primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
282 secondaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
283 } else {
284 primaryCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
285 secondaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
286 }
287 } else {
288 primaryCpuAbi = null;
289 secondaryCpuAbi = null;
290 }
291 return new Abis(primaryCpuAbi, secondaryCpuAbi);
292 }
293
294 @Override
295 public Pair<Abis, NativeLibraryPaths> derivePackageAbi(
296 PackageParser.Package pkg, String cpuAbiOverride, boolean extractLibs)
297 throws PackageManagerException {
298 // Give ourselves some initial paths; we'll come back for another
299 // pass once we've determined ABI below.
300 final NativeLibraryPaths initialLibraryPaths = getNativeLibraryPaths(new Abis(pkg),
301 PackageManagerService.sAppLib32InstallDir, pkg.codePath,
302 pkg.applicationInfo.sourceDir, pkg.applicationInfo.isSystemApp(),
303 pkg.applicationInfo.isUpdatedSystemApp());
304
305 // We shouldn't attempt to extract libs from system app when it was not updated.
306 if (PackageManagerService.isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) {
307 extractLibs = false;
308 }
309
310 final String nativeLibraryRootStr = initialLibraryPaths.nativeLibraryRootDir;
311 final boolean useIsaSpecificSubdirs = initialLibraryPaths.nativeLibraryRootRequiresIsa;
312
313 String primaryCpuAbi = null;
314 String secondaryCpuAbi = null;
315
316 NativeLibraryHelper.Handle handle = null;
317 try {
318 handle = NativeLibraryHelper.Handle.create(pkg);
319 // TODO(multiArch): This can be null for apps that didn't go through the
320 // usual installation process. We can calculate it again, like we
321 // do during install time.
322 //
323 // TODO(multiArch): Why do we need to rescan ASEC apps again ? It seems totally
324 // unnecessary.
325 final File nativeLibraryRoot = new File(nativeLibraryRootStr);
326
327 // Null out the abis so that they can be recalculated.
328 primaryCpuAbi = null;
329 secondaryCpuAbi = null;
330 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0) {
331 // Warn if we've set an abiOverride for multi-lib packages..
332 // By definition, we need to copy both 32 and 64 bit libraries for
333 // such packages.
334 if (pkg.cpuAbiOverride != null
335 && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) {
336 Slog.w(PackageManagerService.TAG,
337 "Ignoring abiOverride for multi arch application.");
338 }
339
340 int abi32 = PackageManager.NO_NATIVE_LIBRARIES;
341 int abi64 = PackageManager.NO_NATIVE_LIBRARIES;
342 if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
343 if (extractLibs) {
344 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries");
345 abi32 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
346 nativeLibraryRoot, Build.SUPPORTED_32_BIT_ABIS,
347 useIsaSpecificSubdirs);
348 } else {
349 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi");
350 abi32 = NativeLibraryHelper.findSupportedAbi(
351 handle, Build.SUPPORTED_32_BIT_ABIS);
352 }
353 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
354 }
355
356 // Shared library native code should be in the APK zip aligned
357 if (abi32 >= 0 && pkg.isLibrary() && extractLibs) {
358 throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
359 "Shared library native lib extraction not supported");
360 }
361
362 maybeThrowExceptionForMultiArchCopy(
363 "Error unpackaging 32 bit native libs for multiarch app.", abi32);
364
365 if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
366 if (extractLibs) {
367 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries");
368 abi64 = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
369 nativeLibraryRoot, Build.SUPPORTED_64_BIT_ABIS,
370 useIsaSpecificSubdirs);
371 } else {
372 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi");
373 abi64 = NativeLibraryHelper.findSupportedAbi(
374 handle, Build.SUPPORTED_64_BIT_ABIS);
375 }
376 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
377 }
378
379 maybeThrowExceptionForMultiArchCopy(
380 "Error unpackaging 64 bit native libs for multiarch app.", abi64);
381
382 if (abi64 >= 0) {
383 // Shared library native libs should be in the APK zip aligned
384 if (extractLibs && pkg.isLibrary()) {
385 throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
386 "Shared library native lib extraction not supported");
387 }
388 primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
389 }
390
391 if (abi32 >= 0) {
392 final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32];
393 if (abi64 >= 0) {
394 if (pkg.use32bitAbi) {
395 secondaryCpuAbi = primaryCpuAbi;
396 primaryCpuAbi = abi;
397 } else {
398 secondaryCpuAbi = abi;
399 }
400 } else {
401 primaryCpuAbi = abi;
402 }
403 }
404 } else {
405 String[] abiList = (cpuAbiOverride != null)
406 ? new String[]{cpuAbiOverride} : Build.SUPPORTED_ABIS;
407
408 // Enable gross and lame hacks for apps that are built with old
409 // SDK tools. We must scan their APKs for renderscript bitcode and
410 // not launch them if it's present. Don't bother checking on devices
411 // that don't have 64 bit support.
412 boolean needsRenderScriptOverride = false;
413 if (Build.SUPPORTED_64_BIT_ABIS.length > 0 && cpuAbiOverride == null
414 && NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
415 abiList = Build.SUPPORTED_32_BIT_ABIS;
416 needsRenderScriptOverride = true;
417 }
418
419 final int copyRet;
420 if (extractLibs) {
421 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyNativeBinaries");
422 copyRet = NativeLibraryHelper.copyNativeBinariesForSupportedAbi(handle,
423 nativeLibraryRoot, abiList, useIsaSpecificSubdirs);
424 } else {
425 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "findSupportedAbi");
426 copyRet = NativeLibraryHelper.findSupportedAbi(handle, abiList);
427 }
428 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
429
430 if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
431 throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
432 "Error unpackaging native libs for app, errorCode=" + copyRet);
433 }
434
435 if (copyRet >= 0) {
436 // Shared libraries that have native libs must be multi-architecture
437 if (pkg.isLibrary()) {
438 throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
439 "Shared library with native libs must be multiarch");
440 }
441 primaryCpuAbi = abiList[copyRet];
442 } else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES
443 && cpuAbiOverride != null) {
444 primaryCpuAbi = cpuAbiOverride;
445 } else if (needsRenderScriptOverride) {
446 primaryCpuAbi = abiList[0];
447 }
448 }
449 } catch (IOException ioe) {
450 Slog.e(PackageManagerService.TAG, "Unable to get canonical file " + ioe.toString());
451 } finally {
452 IoUtils.closeQuietly(handle);
453 }
454
455 // Now that we've calculated the ABIs and determined if it's an internal app,
456 // we will go ahead and populate the nativeLibraryPath.
457
458 final Abis abis = new Abis(primaryCpuAbi, secondaryCpuAbi);
459 return new Pair<>(abis,
460 getNativeLibraryPaths(abis, PackageManagerService.sAppLib32InstallDir,
461 pkg.codePath, pkg.applicationInfo.sourceDir,
462 pkg.applicationInfo.isSystemApp(),
463 pkg.applicationInfo.isUpdatedSystemApp()));
464 }
465
466 /**
467 * Adjusts ABIs for a set of packages belonging to a shared user so that they all match.
468 * i.e, so that all packages can be run inside a single process if required.
469 *
470 * Optionally, callers can pass in a parsed package via {@code newPackage} in which case
471 * this function will either try and make the ABI for all packages in
472 * {@code packagesForUser} match {@code scannedPackage} or will update the ABI of
473 * {@code scannedPackage} to match the ABI selected for {@code packagesForUser}. This
474 * variant is used when installing or updating a package that belongs to a shared user.
475 *
476 * NOTE: We currently only match for the primary CPU abi string. Matching the secondary
477 * adds unnecessary complexity.
478 */
479 @Override
480 @Nullable
481 public String getAdjustedAbiForSharedUser(
482 Set<PackageSetting> packagesForUser, PackageParser.Package scannedPackage) {
483 String requiredInstructionSet = null;
484 if (scannedPackage != null && scannedPackage.applicationInfo.primaryCpuAbi != null) {
485 requiredInstructionSet = VMRuntime.getInstructionSet(
486 scannedPackage.applicationInfo.primaryCpuAbi);
487 }
488
489 PackageSetting requirer = null;
490 for (PackageSetting ps : packagesForUser) {
491 // If packagesForUser contains scannedPackage, we skip it. This will happen
492 // when scannedPackage is an update of an existing package. Without this check,
493 // we will never be able to change the ABI of any package belonging to a shared
494 // user, even if it's compatible with other packages.
495 if (scannedPackage != null && scannedPackage.packageName.equals(ps.name)) {
496 continue;
497 }
498 if (ps.primaryCpuAbiString == null) {
499 continue;
500 }
501
502 final String instructionSet =
503 VMRuntime.getInstructionSet(ps.primaryCpuAbiString);
504 if (requiredInstructionSet != null && !requiredInstructionSet.equals(instructionSet)) {
505 // We have a mismatch between instruction sets (say arm vs arm64) warn about
506 // this but there's not much we can do.
507 String errorMessage = "Instruction set mismatch, "
508 + ((requirer == null) ? "[caller]" : requirer)
509 + " requires " + requiredInstructionSet + " whereas " + ps
510 + " requires " + instructionSet;
511 Slog.w(PackageManagerService.TAG, errorMessage);
512 }
513
514 if (requiredInstructionSet == null) {
515 requiredInstructionSet = instructionSet;
516 requirer = ps;
517 }
518 }
519
520 if (requiredInstructionSet == null) {
521 return null;
522 }
523 final String adjustedAbi;
524 if (requirer != null) {
525 // requirer != null implies that either scannedPackage was null or that
526 // scannedPackage did not require an ABI, in which case we have to adjust
527 // scannedPackage to match the ABI of the set (which is the same as
528 // requirer's ABI)
529 adjustedAbi = requirer.primaryCpuAbiString;
530 } else {
531 // requirer == null implies that we're updating all ABIs in the set to
532 // match scannedPackage.
533 adjustedAbi = scannedPackage.applicationInfo.primaryCpuAbi;
534 }
535 return adjustedAbi;
536 }
Patrick Baumannf62817e2019-05-31 10:46:53 -0700537}