Loading services/core/java/com/android/server/am/ActivityManagerService.java +7 −0 Original line number Diff line number Diff line Loading @@ -1475,6 +1475,7 @@ public final class ActivityManagerService extends ActivityManagerNative final ServiceThread mHandlerThread; final MainHandler mHandler; final UiHandler mUiHandler; final ProcessStartLogger mProcessStartLogger; PackageManagerInternal mPackageManagerInt; Loading Loading @@ -2452,6 +2453,8 @@ public final class ActivityManagerService extends ActivityManagerNative mHandler = new MainHandler(mHandlerThread.getLooper()); mUiHandler = new UiHandler(); mProcessStartLogger = new ProcessStartLogger(); mFgBroadcastQueue = new BroadcastQueue(this, mHandler, "foreground", BROADCAST_FG_TIMEOUT, false); mBgBroadcastQueue = new BroadcastQueue(this, mHandler, Loading Loading @@ -3552,6 +3555,8 @@ public final class ActivityManagerService extends ActivityManagerNative app.processName, hostingType, hostingNameStr != null ? hostingNameStr : ""); mProcessStartLogger.logIfNeededLocked(app, startResult); if (app.persistent) { Watchdog.getInstance().processStarted(app.processName, startResult.pid); } Loading Loading @@ -6634,6 +6639,8 @@ public final class ActivityManagerService extends ActivityManagerNative } }, dumpheapFilter); mProcessStartLogger.registerListener(mContext); // Let system services know. mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED); Loading services/core/java/com/android/server/am/ProcessStartLogger.java 0 → 100644 +151 −0 Original line number Diff line number Diff line package com.android.server.am; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import android.app.AppGlobals; import android.auditing.SecurityLog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; import android.os.RemoteException; import android.os.Process.ProcessStartResult; import android.util.Slog; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; /** * A class that logs process start information (including APK hash) to the security log. */ class ProcessStartLogger { private static final String CLASS_NAME = "ProcessStartLogger"; private static final String TAG = TAG_WITH_CLASS_NAME ? CLASS_NAME : TAG_AM; final HandlerThread mHandlerProcessLoggingThread; Handler mHandlerProcessLogging; // Should only access in mHandlerProcessLoggingThread final HashMap<String, String> mProcessLoggingApkHashes; ProcessStartLogger() { mHandlerProcessLoggingThread = new HandlerThread(CLASS_NAME, Process.THREAD_PRIORITY_BACKGROUND); mProcessLoggingApkHashes = new HashMap(); } void logIfNeededLocked(ProcessRecord app, ProcessStartResult startResult) { if (!SecurityLog.isLoggingEnabled()) { return; } if (!mHandlerProcessLoggingThread.isAlive()) { mHandlerProcessLoggingThread.start(); mHandlerProcessLogging = new Handler(mHandlerProcessLoggingThread.getLooper()); } mHandlerProcessLogging.post(new ProcessLoggingRunnable(app, startResult, System.currentTimeMillis())); } void registerListener(Context context) { IntentFilter packageChangedFilter = new IntentFilter(); packageChangedFilter.addAction(Intent.ACTION_PACKAGE_ADDED); packageChangedFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); context.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false) || Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) { int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()); String packageName = intent.getData().getSchemeSpecificPart(); try { ApplicationInfo info = AppGlobals.getPackageManager().getApplicationInfo( packageName, 0, userHandle); invaildateCache(info.sourceDir); } catch (RemoteException e) { } } } }, packageChangedFilter); } private void invaildateCache(final String apkPath) { if (mHandlerProcessLogging != null) { mHandlerProcessLogging.post(new Runnable() { @Override public void run() { mProcessLoggingApkHashes.remove(apkPath); } }); } } private class ProcessLoggingRunnable implements Runnable { private final ProcessRecord app; private final Process.ProcessStartResult startResult; private final long startTimestamp; public ProcessLoggingRunnable(ProcessRecord app, Process.ProcessStartResult startResult, long startTimestamp){ this.app = app; this.startResult = startResult; this.startTimestamp = startTimestamp; } @Override public void run() { String apkHash = computeStringHashOfApk(app); SecurityLog.writeEvent(SecurityLog.TAG_APP_PROCESS_START, app.processName, startTimestamp, app.uid, startResult.pid, app.info.seinfo, apkHash); } private String computeStringHashOfApk(ProcessRecord app){ final String apkFile = app.info.sourceDir; if(apkFile == null) { return "No APK"; } String apkHash = mProcessLoggingApkHashes.get(apkFile); if (apkHash == null) { try { byte[] hash = computeHashOfApkFile(apkFile); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hash.length; i++) { sb.append(String.format("%02x", hash[i])); } apkHash = sb.toString(); mProcessLoggingApkHashes.put(apkFile, apkHash); } catch (IOException | NoSuchAlgorithmException e) { Slog.w(TAG, "computeStringHashOfApk() failed", e); } } return apkHash != null ? apkHash : "Failed to count APK hash"; } private byte[] computeHashOfApkFile(String packageArchiveLocation) throws IOException, NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance("SHA-256"); FileInputStream input = new FileInputStream(new File(packageArchiveLocation)); byte[] buffer = new byte[65536]; int size; while((size = input.read(buffer)) > 0) { md.update(buffer, 0, size); } input.close(); return md.digest(); } } } No newline at end of file Loading
services/core/java/com/android/server/am/ActivityManagerService.java +7 −0 Original line number Diff line number Diff line Loading @@ -1475,6 +1475,7 @@ public final class ActivityManagerService extends ActivityManagerNative final ServiceThread mHandlerThread; final MainHandler mHandler; final UiHandler mUiHandler; final ProcessStartLogger mProcessStartLogger; PackageManagerInternal mPackageManagerInt; Loading Loading @@ -2452,6 +2453,8 @@ public final class ActivityManagerService extends ActivityManagerNative mHandler = new MainHandler(mHandlerThread.getLooper()); mUiHandler = new UiHandler(); mProcessStartLogger = new ProcessStartLogger(); mFgBroadcastQueue = new BroadcastQueue(this, mHandler, "foreground", BROADCAST_FG_TIMEOUT, false); mBgBroadcastQueue = new BroadcastQueue(this, mHandler, Loading Loading @@ -3552,6 +3555,8 @@ public final class ActivityManagerService extends ActivityManagerNative app.processName, hostingType, hostingNameStr != null ? hostingNameStr : ""); mProcessStartLogger.logIfNeededLocked(app, startResult); if (app.persistent) { Watchdog.getInstance().processStarted(app.processName, startResult.pid); } Loading Loading @@ -6634,6 +6639,8 @@ public final class ActivityManagerService extends ActivityManagerNative } }, dumpheapFilter); mProcessStartLogger.registerListener(mContext); // Let system services know. mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED); Loading
services/core/java/com/android/server/am/ProcessStartLogger.java 0 → 100644 +151 −0 Original line number Diff line number Diff line package com.android.server.am; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import android.app.AppGlobals; import android.auditing.SecurityLog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; import android.os.RemoteException; import android.os.Process.ProcessStartResult; import android.util.Slog; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; /** * A class that logs process start information (including APK hash) to the security log. */ class ProcessStartLogger { private static final String CLASS_NAME = "ProcessStartLogger"; private static final String TAG = TAG_WITH_CLASS_NAME ? CLASS_NAME : TAG_AM; final HandlerThread mHandlerProcessLoggingThread; Handler mHandlerProcessLogging; // Should only access in mHandlerProcessLoggingThread final HashMap<String, String> mProcessLoggingApkHashes; ProcessStartLogger() { mHandlerProcessLoggingThread = new HandlerThread(CLASS_NAME, Process.THREAD_PRIORITY_BACKGROUND); mProcessLoggingApkHashes = new HashMap(); } void logIfNeededLocked(ProcessRecord app, ProcessStartResult startResult) { if (!SecurityLog.isLoggingEnabled()) { return; } if (!mHandlerProcessLoggingThread.isAlive()) { mHandlerProcessLoggingThread.start(); mHandlerProcessLogging = new Handler(mHandlerProcessLoggingThread.getLooper()); } mHandlerProcessLogging.post(new ProcessLoggingRunnable(app, startResult, System.currentTimeMillis())); } void registerListener(Context context) { IntentFilter packageChangedFilter = new IntentFilter(); packageChangedFilter.addAction(Intent.ACTION_PACKAGE_ADDED); packageChangedFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); context.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false) || Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) { int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId()); String packageName = intent.getData().getSchemeSpecificPart(); try { ApplicationInfo info = AppGlobals.getPackageManager().getApplicationInfo( packageName, 0, userHandle); invaildateCache(info.sourceDir); } catch (RemoteException e) { } } } }, packageChangedFilter); } private void invaildateCache(final String apkPath) { if (mHandlerProcessLogging != null) { mHandlerProcessLogging.post(new Runnable() { @Override public void run() { mProcessLoggingApkHashes.remove(apkPath); } }); } } private class ProcessLoggingRunnable implements Runnable { private final ProcessRecord app; private final Process.ProcessStartResult startResult; private final long startTimestamp; public ProcessLoggingRunnable(ProcessRecord app, Process.ProcessStartResult startResult, long startTimestamp){ this.app = app; this.startResult = startResult; this.startTimestamp = startTimestamp; } @Override public void run() { String apkHash = computeStringHashOfApk(app); SecurityLog.writeEvent(SecurityLog.TAG_APP_PROCESS_START, app.processName, startTimestamp, app.uid, startResult.pid, app.info.seinfo, apkHash); } private String computeStringHashOfApk(ProcessRecord app){ final String apkFile = app.info.sourceDir; if(apkFile == null) { return "No APK"; } String apkHash = mProcessLoggingApkHashes.get(apkFile); if (apkHash == null) { try { byte[] hash = computeHashOfApkFile(apkFile); StringBuilder sb = new StringBuilder(); for (int i = 0; i < hash.length; i++) { sb.append(String.format("%02x", hash[i])); } apkHash = sb.toString(); mProcessLoggingApkHashes.put(apkFile, apkHash); } catch (IOException | NoSuchAlgorithmException e) { Slog.w(TAG, "computeStringHashOfApk() failed", e); } } return apkHash != null ? apkHash : "Failed to count APK hash"; } private byte[] computeHashOfApkFile(String packageArchiveLocation) throws IOException, NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance("SHA-256"); FileInputStream input = new FileInputStream(new File(packageArchiveLocation)); byte[] buffer = new byte[65536]; int size; while((size = input.read(buffer)) > 0) { md.update(buffer, 0, size); } input.close(); return md.digest(); } } } No newline at end of file