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.odp.module.common; 18 19 import static android.content.pm.PackageManager.GET_META_DATA; 20 import static android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES; 21 import static android.content.pm.PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES; 22 import static android.federatedcompute.common.ClientConstants.ODP_AOSP_BUILT_APEX_NAME; 23 import static android.federatedcompute.common.ClientConstants.ODP_APEX_KEYWORD; 24 import static android.federatedcompute.common.ClientConstants.ODP_MAINLINE_SIGNED_APEX_NAME; 25 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.content.Context; 29 import android.content.pm.ApplicationInfo; 30 import android.content.pm.PackageInfo; 31 import android.content.pm.PackageManager; 32 import android.content.pm.Signature; 33 import android.content.pm.SigningInfo; 34 35 import libcore.util.HexEncoding; 36 37 import java.security.MessageDigest; 38 import java.security.NoSuchAlgorithmException; 39 import java.util.List; 40 41 /** 42 * PackageUtils for OnDevicePersonalization module. 43 * 44 * @hide 45 */ 46 public class PackageUtils { PackageUtils()47 private PackageUtils() { 48 } 49 50 /** 51 * Computes the SHA256 digest of some data. 52 * 53 * @param data The data. 54 * @return The digest or null if an error occurs. 55 */ 56 @Nullable computeSha256DigestBytes(@onNull byte[] data)57 public static byte[] computeSha256DigestBytes(@NonNull byte[] data) { 58 MessageDigest messageDigest; 59 try { 60 messageDigest = MessageDigest.getInstance("SHA256"); 61 } catch (NoSuchAlgorithmException e) { 62 /* can't happen */ 63 return null; 64 } 65 66 messageDigest.update(data); 67 68 return messageDigest.digest(); 69 } 70 71 /** 72 * Retrieves the certDigest of the given packageName 73 * 74 * @param context Context of the calling service 75 * @param packageName Package name owning the certDigest 76 * @return certDigest of the given packageName 77 */ 78 @Nullable getCertDigest(@onNull Context context, @NonNull String packageName)79 public static String getCertDigest(@NonNull Context context, @NonNull String packageName) 80 throws PackageManager.NameNotFoundException { 81 PackageInfo sdkPackageInfo = 82 context.getPackageManager() 83 .getPackageInfo( 84 packageName, 85 PackageManager.PackageInfoFlags.of( 86 GET_SIGNING_CERTIFICATES 87 | MATCH_STATIC_SHARED_AND_SDK_LIBRARIES)); 88 SigningInfo signingInfo = sdkPackageInfo.signingInfo; 89 Signature[] signatures = 90 signingInfo != null ? signingInfo.getSigningCertificateHistory() : null; 91 byte[] digest = PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray()); 92 return new String(HexEncoding.encode(digest)); 93 } 94 95 /** 96 * Determines if a package is debuggable 97 * 98 * @return true if the package is debuggable, false otherwise 99 */ isPackageDebuggable(@onNull Context context, @NonNull String packageName)100 public static boolean isPackageDebuggable(@NonNull Context context, @NonNull String packageName) 101 throws PackageManager.NameNotFoundException { 102 ApplicationInfo sdkApplicationInfo = 103 context.getPackageManager() 104 .getApplicationInfo( 105 packageName, PackageManager.ApplicationInfoFlags.of(GET_META_DATA)); 106 return (sdkApplicationInfo.flags &= ApplicationInfo.FLAG_DEBUGGABLE) != 0; 107 } 108 109 /** 110 * Get the apex version of OnDevicePersonalization. 111 * 112 * @param context The context of the calling process. 113 * @return The long version code of OnDevicePersonalization apex. If there is no name match, 114 * then return -1L. 115 */ getApexVersion(Context context)116 public static long getApexVersion(Context context) { 117 try { 118 PackageInfo odpMainlineApexInfo = context.getPackageManager() 119 .getPackageInfo(ODP_MAINLINE_SIGNED_APEX_NAME, PackageManager.MATCH_APEX); 120 if (odpMainlineApexInfo != null && odpMainlineApexInfo.isApex) { 121 return odpMainlineApexInfo.getLongVersionCode(); 122 } 123 124 PackageInfo odpAospApexInfo = context.getPackageManager() 125 .getPackageInfo(ODP_AOSP_BUILT_APEX_NAME, PackageManager.MATCH_APEX); 126 if (odpAospApexInfo != null && odpAospApexInfo.isApex) { 127 return odpAospApexInfo.getLongVersionCode(); 128 } 129 } catch (PackageManager.NameNotFoundException e) { 130 } 131 132 List<PackageInfo> installedPackages = 133 context.getPackageManager().getInstalledPackages( 134 PackageManager.PackageInfoFlags.of(PackageManager.MATCH_APEX)); 135 for (PackageInfo pkg : installedPackages) { 136 if (pkg.packageName.contains(ODP_APEX_KEYWORD) && pkg.isApex) { 137 return pkg.getLongVersionCode(); 138 } 139 } 140 return -1L; 141 } 142 } 143