1 /*
2  * Copyright (C) 2020 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.dex;
18 
19 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
20 
21 import android.content.pm.IPackageManager;
22 import android.os.RemoteException;
23 import android.util.Log;
24 import android.util.Slog;
25 
26 import dalvik.system.BaseDexClassLoader;
27 import dalvik.system.VMRuntime;
28 
29 import java.util.Map;
30 
31 /**
32  * Reports dex file use to the package manager on behalf of system server.
33  */
34 public class SystemServerDexLoadReporter implements BaseDexClassLoader.Reporter {
35     private static final String TAG = "SystemServerDexLoadReporter";
36 
37     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
38 
39     private final IPackageManager mPackageManager;
40 
SystemServerDexLoadReporter(IPackageManager pm)41     private SystemServerDexLoadReporter(IPackageManager pm) {
42         mPackageManager = pm;
43     }
44 
45     @Override
report(Map<String, String> classLoaderContextMap)46     public void report(Map<String, String> classLoaderContextMap) {
47         if (DEBUG) {
48             Slog.i(TAG, "Reporting "  + classLoaderContextMap);
49         }
50         if (classLoaderContextMap.isEmpty()) {
51             Slog.wtf(TAG, "Bad call to DexLoadReporter: empty classLoaderContextMap");
52             return;
53         }
54 
55         try {
56             mPackageManager.notifyDexLoad(
57                     PLATFORM_PACKAGE_NAME,
58                     classLoaderContextMap,
59                     VMRuntime.getRuntime().vmInstructionSet());
60         } catch (RemoteException ignored) {
61             // We're in system server, it can't happen.
62         }
63     }
64 
65     /**
66      * Configures system server dex file reporting.
67      * <p>The method will install a reporter in the BaseDexClassLoader and also
68      * force the reporting of any dex files already loaded by the system server.
69      */
configureSystemServerDexReporter(IPackageManager pm)70     public static void configureSystemServerDexReporter(IPackageManager pm) {
71         Slog.i(TAG, "Configuring system server dex reporter");
72 
73         SystemServerDexLoadReporter reporter = new SystemServerDexLoadReporter(pm);
74         BaseDexClassLoader.setReporter(reporter);
75         ClassLoader currrentClassLoader = reporter.getClass().getClassLoader();
76         if (currrentClassLoader instanceof BaseDexClassLoader) {
77             ((BaseDexClassLoader) currrentClassLoader).reportClassLoaderChain();
78         } else {
79             Slog.wtf(TAG, "System server class loader is not a BaseDexClassLoader. type="
80                     + currrentClassLoader.getClass().getName());
81         }
82     }
83 }
84