DexLogger.java revision a0023604ddaeef34049f1a245be7c42a66a7d0e8
1/* 2 * Copyright (C) 2017 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.dex; 18 19import android.content.pm.ApplicationInfo; 20import android.content.pm.IPackageManager; 21import android.os.RemoteException; 22 23import android.util.ArraySet; 24import android.util.ByteStringUtils; 25import android.util.EventLog; 26import android.util.PackageUtils; 27import android.util.Slog; 28 29import com.android.internal.annotations.GuardedBy; 30import com.android.server.pm.Installer; 31import com.android.server.pm.Installer.InstallerException; 32 33import java.io.File; 34import java.util.Set; 35 36import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo; 37 38/** 39 * This class is responsible for logging data about secondary dex files. 40 * The data logged includes hashes of the name and content of each file. 41 */ 42public class DexLogger implements DexManager.Listener { 43 private static final String TAG = "DexLogger"; 44 45 // Event log tag & subtag used for SafetyNet logging of dynamic 46 // code loading (DCL) - see b/63927552. 47 private static final int SNET_TAG = 0x534e4554; 48 private static final String DCL_SUBTAG = "dcl"; 49 50 private final IPackageManager mPackageManager; 51 private final Object mInstallLock; 52 @GuardedBy("mInstallLock") 53 private final Installer mInstaller; 54 55 public static DexManager.Listener getListener(IPackageManager pms, 56 Installer installer, Object installLock) { 57 return new DexLogger(pms, installer, installLock); 58 } 59 60 private DexLogger(IPackageManager pms, Installer installer, Object installLock) { 61 mPackageManager = pms; 62 mInstaller = installer; 63 mInstallLock = installLock; 64 } 65 66 /** 67 * Compute and log hashes of the name and content of a secondary dex file. 68 */ 69 @Override 70 public void onReconcileSecondaryDexFile(ApplicationInfo appInfo, DexUseInfo dexUseInfo, 71 String dexPath, int storageFlags) { 72 int ownerUid = appInfo.uid; 73 74 byte[] hash = null; 75 synchronized(mInstallLock) { 76 try { 77 hash = mInstaller.hashSecondaryDexFile(dexPath, appInfo.packageName, 78 ownerUid, appInfo.volumeUuid, storageFlags); 79 } catch (InstallerException e) { 80 Slog.e(TAG, "Got InstallerException when hashing dex " + dexPath + 81 " : " + e.getMessage()); 82 } 83 } 84 if (hash == null) { 85 return; 86 } 87 88 String dexFileName = new File(dexPath).getName(); 89 String message = PackageUtils.computeSha256Digest(dexFileName.getBytes()); 90 // Valid SHA256 will be 256 bits, 32 bytes. 91 if (hash.length == 32) { 92 message = message + ' ' + ByteStringUtils.toHexString(hash); 93 } 94 95 EventLog.writeEvent(SNET_TAG, DCL_SUBTAG, ownerUid, message); 96 97 if (dexUseInfo.isUsedByOtherApps()) { 98 Set<String> otherPackages = dexUseInfo.getLoadingPackages(); 99 Set<Integer> otherUids = new ArraySet<>(otherPackages.size()); 100 for (String otherPackageName : otherPackages) { 101 try { 102 int otherUid = mPackageManager.getPackageUid( 103 otherPackageName, /*flags*/0, dexUseInfo.getOwnerUserId()); 104 if (otherUid != -1 && otherUid != ownerUid) { 105 otherUids.add(otherUid); 106 } 107 } catch (RemoteException ignore) { 108 // Can't happen, we're local. 109 } 110 } 111 for (int otherUid : otherUids) { 112 EventLog.writeEvent(SNET_TAG, DCL_SUBTAG, otherUid, message); 113 } 114 } 115 } 116} 117