Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 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 | |
| 17 | package com.android.server.pm.dex; |
| 18 | |
| 19 | import android.Manifest; |
Calin Juravle | 3621be7 | 2018-01-18 15:17:29 -0800 | [diff] [blame] | 20 | import android.annotation.UserIdInt; |
| 21 | import android.content.pm.ApplicationInfo; |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 22 | import android.content.pm.PackageInfo; |
| 23 | import android.content.pm.PackageManager; |
Calin Juravle | 3621be7 | 2018-01-18 15:17:29 -0800 | [diff] [blame] | 24 | import android.content.pm.PackageParser; |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 25 | import android.content.pm.dex.ArtManager; |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 26 | import android.content.pm.dex.ArtManager.ProfileType; |
Calin Juravle | 3621be7 | 2018-01-18 15:17:29 -0800 | [diff] [blame] | 27 | import android.content.pm.dex.DexMetadataHelper; |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 28 | import android.os.Binder; |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 29 | import android.os.Build; |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 30 | import android.os.Handler; |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 31 | import android.os.ParcelFileDescriptor; |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 32 | import android.os.RemoteException; |
| 33 | import android.content.pm.IPackageManager; |
| 34 | import android.content.pm.dex.ISnapshotRuntimeProfileCallback; |
| 35 | import android.os.SystemProperties; |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 36 | import android.os.UserHandle; |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 37 | import android.system.Os; |
Calin Juravle | 3621be7 | 2018-01-18 15:17:29 -0800 | [diff] [blame] | 38 | import android.util.ArrayMap; |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 39 | import android.util.Slog; |
| 40 | |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 41 | import com.android.internal.annotations.GuardedBy; |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 42 | import com.android.internal.os.BackgroundThread; |
Calin Juravle | 3621be7 | 2018-01-18 15:17:29 -0800 | [diff] [blame] | 43 | import com.android.internal.util.ArrayUtils; |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 44 | import com.android.internal.util.Preconditions; |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 45 | import com.android.server.pm.Installer; |
| 46 | import com.android.server.pm.Installer.InstallerException; |
| 47 | import java.io.File; |
| 48 | import java.io.FileNotFoundException; |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 49 | import libcore.io.IoUtils; |
| 50 | import libcore.util.NonNull; |
| 51 | import libcore.util.Nullable; |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 52 | |
| 53 | /** |
| 54 | * A system service that provides access to runtime and compiler artifacts. |
| 55 | * |
| 56 | * This service is not accessed by users directly, instead one uses an instance of |
| 57 | * {@link ArtManager}, which can be accessed via {@link PackageManager} as follows: |
| 58 | * <p/> |
| 59 | * {@code context().getPackageManager().getArtManager();} |
| 60 | * <p class="note"> |
| 61 | * Note: Accessing runtime artifacts may require extra permissions. For example querying the |
| 62 | * runtime profiles of apps requires {@link android.Manifest.permission#READ_RUNTIME_PROFILES} |
| 63 | * which is a system-level permission that will not be granted to normal apps. |
| 64 | */ |
| 65 | public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { |
| 66 | private static final String TAG = "ArtManagerService"; |
| 67 | |
| 68 | private static boolean DEBUG = false; |
| 69 | private static boolean DEBUG_IGNORE_PERMISSIONS = false; |
| 70 | |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 71 | // Package name used to create the profile directory layout when |
| 72 | // taking a snapshot of the boot image profile. |
| 73 | private static final String BOOT_IMAGE_ANDROID_PACKAGE = "android"; |
| 74 | // Profile name used for the boot image profile. |
| 75 | private static final String BOOT_IMAGE_PROFILE_NAME = "android.prof"; |
| 76 | |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 77 | private final IPackageManager mPackageManager; |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 78 | private final Object mInstallLock; |
| 79 | @GuardedBy("mInstallLock") |
| 80 | private final Installer mInstaller; |
| 81 | |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 82 | private final Handler mHandler; |
| 83 | |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 84 | public ArtManagerService(IPackageManager pm, Installer installer, Object installLock) { |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 85 | mPackageManager = pm; |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 86 | mInstaller = installer; |
| 87 | mInstallLock = installLock; |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 88 | mHandler = new Handler(BackgroundThread.getHandler().getLooper()); |
| 89 | } |
| 90 | |
| 91 | @Override |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 92 | public void snapshotRuntimeProfile(@ProfileType int profileType, @Nullable String packageName, |
| 93 | @Nullable String codePath, @NonNull ISnapshotRuntimeProfileCallback callback) { |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 94 | // Sanity checks on the arguments. |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 95 | Preconditions.checkNotNull(callback); |
| 96 | |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 97 | boolean bootImageProfile = profileType == ArtManager.PROFILE_BOOT_IMAGE; |
| 98 | if (!bootImageProfile) { |
| 99 | Preconditions.checkStringNotEmpty(codePath); |
| 100 | Preconditions.checkStringNotEmpty(packageName); |
| 101 | } |
| 102 | |
| 103 | // Verify that the caller has the right permissions and that the runtime profiling is |
| 104 | // enabled. The call to isRuntimePermissions will checkReadRuntimeProfilePermission. |
| 105 | if (!isRuntimeProfilingEnabled(profileType)) { |
| 106 | throw new IllegalStateException("Runtime profiling is not enabled for " + profileType); |
| 107 | } |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 108 | |
| 109 | if (DEBUG) { |
| 110 | Slog.d(TAG, "Requested snapshot for " + packageName + ":" + codePath); |
| 111 | } |
| 112 | |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 113 | if (bootImageProfile) { |
| 114 | snapshotBootImageProfile(callback); |
| 115 | } else { |
| 116 | snapshotAppProfile(packageName, codePath, callback); |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | private void snapshotAppProfile(String packageName, String codePath, |
| 121 | ISnapshotRuntimeProfileCallback callback) { |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 122 | PackageInfo info = null; |
| 123 | try { |
| 124 | // Note that we use the default user 0 to retrieve the package info. |
| 125 | // This doesn't really matter because for user 0 we always get a package back (even if |
| 126 | // it's not installed for the user 0). It is ok because we only care about the code |
| 127 | // paths and not if the package is enabled or not for the user. |
| 128 | |
| 129 | // TODO(calin): consider adding an API to PMS which can retrieve the |
| 130 | // PackageParser.Package. |
| 131 | info = mPackageManager.getPackageInfo(packageName, /*flags*/ 0, /*userId*/ 0); |
| 132 | } catch (RemoteException ignored) { |
| 133 | // Should not happen. |
| 134 | } |
| 135 | if (info == null) { |
| 136 | postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_PACKAGE_NOT_FOUND); |
| 137 | return; |
| 138 | } |
| 139 | |
| 140 | boolean pathFound = info.applicationInfo.getBaseCodePath().equals(codePath); |
Calin Juravle | 6ae39fc | 2018-01-19 20:32:47 -0800 | [diff] [blame] | 141 | String splitName = null; |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 142 | String[] splitCodePaths = info.applicationInfo.getSplitCodePaths(); |
| 143 | if (!pathFound && (splitCodePaths != null)) { |
Calin Juravle | 6ae39fc | 2018-01-19 20:32:47 -0800 | [diff] [blame] | 144 | for (int i = splitCodePaths.length - 1; i >= 0; i--) { |
| 145 | if (splitCodePaths[i].equals(codePath)) { |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 146 | pathFound = true; |
Calin Juravle | 6ae39fc | 2018-01-19 20:32:47 -0800 | [diff] [blame] | 147 | splitName = info.applicationInfo.splitNames[i]; |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 148 | break; |
| 149 | } |
| 150 | } |
| 151 | } |
| 152 | if (!pathFound) { |
| 153 | postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_CODE_PATH_NOT_FOUND); |
| 154 | return; |
| 155 | } |
| 156 | |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 157 | // All good, create the profile snapshot. |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 158 | int appId = UserHandle.getAppId(info.applicationInfo.uid); |
| 159 | if (appId < 0) { |
| 160 | postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); |
| 161 | Slog.wtf(TAG, "AppId is -1 for package: " + packageName); |
| 162 | return; |
| 163 | } |
| 164 | |
| 165 | createProfileSnapshot(packageName, ArtManager.getProfileName(splitName), codePath, |
| 166 | appId, callback); |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 167 | // Destroy the snapshot, we no longer need it. |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 168 | destroyProfileSnapshot(packageName, ArtManager.getProfileName(splitName)); |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 169 | } |
| 170 | |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 171 | private void createProfileSnapshot(String packageName, String profileName, String classpath, |
| 172 | int appId, ISnapshotRuntimeProfileCallback callback) { |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 173 | // Ask the installer to snapshot the profile. |
| 174 | synchronized (mInstallLock) { |
| 175 | try { |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 176 | if (!mInstaller.createProfileSnapshot(appId, packageName, profileName, classpath)) { |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 177 | postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); |
| 178 | return; |
| 179 | } |
| 180 | } catch (InstallerException e) { |
| 181 | postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); |
| 182 | return; |
| 183 | } |
| 184 | } |
| 185 | |
| 186 | // Open the snapshot and invoke the callback. |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 187 | File snapshotProfile = ArtManager.getProfileSnapshotFileForName(packageName, profileName); |
| 188 | |
| 189 | ParcelFileDescriptor fd = null; |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 190 | try { |
| 191 | fd = ParcelFileDescriptor.open(snapshotProfile, ParcelFileDescriptor.MODE_READ_ONLY); |
| 192 | postSuccess(packageName, fd, callback); |
| 193 | } catch (FileNotFoundException e) { |
Calin Juravle | 6ae39fc | 2018-01-19 20:32:47 -0800 | [diff] [blame] | 194 | Slog.w(TAG, "Could not open snapshot profile for " + packageName + ":" |
| 195 | + snapshotProfile, e); |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 196 | postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR); |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 197 | } finally { |
| 198 | IoUtils.closeQuietly(fd); |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 199 | } |
| 200 | } |
| 201 | |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 202 | private void destroyProfileSnapshot(String packageName, String profileName) { |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 203 | if (DEBUG) { |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 204 | Slog.d(TAG, "Destroying profile snapshot for" + packageName + ":" + profileName); |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 205 | } |
| 206 | |
| 207 | synchronized (mInstallLock) { |
| 208 | try { |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 209 | mInstaller.destroyProfileSnapshot(packageName, profileName); |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 210 | } catch (InstallerException e) { |
| 211 | Slog.e(TAG, "Failed to destroy profile snapshot for " + |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 212 | packageName + ":" + profileName, e); |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 213 | } |
| 214 | } |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 215 | } |
| 216 | |
| 217 | @Override |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 218 | public boolean isRuntimeProfilingEnabled(@ProfileType int profileType) { |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 219 | // Verify that the caller has the right permissions. |
| 220 | checkReadRuntimeProfilePermission(); |
| 221 | |
Calin Juravle | fcbb74a | 2018-01-21 21:39:18 -0800 | [diff] [blame] | 222 | switch (profileType) { |
| 223 | case ArtManager.PROFILE_APPS : |
| 224 | return SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false); |
| 225 | case ArtManager.PROFILE_BOOT_IMAGE: |
| 226 | return (Build.IS_USERDEBUG || Build.IS_ENG) && |
| 227 | SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false) && |
| 228 | SystemProperties.getBoolean("dalvik.vm.profilebootimage", false); |
| 229 | default: |
| 230 | throw new IllegalArgumentException("Invalid profile type:" + profileType); |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | private void snapshotBootImageProfile(ISnapshotRuntimeProfileCallback callback) { |
| 235 | // Combine the profiles for boot classpath and system server classpath. |
| 236 | // This avoids having yet another type of profiles and simplifies the processing. |
| 237 | String classpath = String.join(":", Os.getenv("BOOTCLASSPATH"), |
| 238 | Os.getenv("SYSTEMSERVERCLASSPATH")); |
| 239 | |
| 240 | // Create the snapshot. |
| 241 | createProfileSnapshot(BOOT_IMAGE_ANDROID_PACKAGE, BOOT_IMAGE_PROFILE_NAME, classpath, |
| 242 | /*appId*/ -1, callback); |
| 243 | // Destroy the snapshot, we no longer need it. |
| 244 | destroyProfileSnapshot(BOOT_IMAGE_ANDROID_PACKAGE, BOOT_IMAGE_PROFILE_NAME); |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 245 | } |
| 246 | |
| 247 | /** |
| 248 | * Post {@link ISnapshotRuntimeProfileCallback#onError(int)} with the given error message |
| 249 | * on the internal {@code mHandler}. |
| 250 | */ |
| 251 | private void postError(ISnapshotRuntimeProfileCallback callback, String packageName, |
| 252 | int errCode) { |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 253 | if (DEBUG) { |
| 254 | Slog.d(TAG, "Failed to snapshot profile for " + packageName + " with error: " + |
| 255 | errCode); |
| 256 | } |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 257 | mHandler.post(() -> { |
| 258 | try { |
| 259 | callback.onError(errCode); |
| 260 | } catch (RemoteException e) { |
| 261 | Slog.w(TAG, "Failed to callback after profile snapshot for " + packageName, e); |
| 262 | } |
| 263 | }); |
| 264 | } |
| 265 | |
Calin Juravle | fd9f8ae | 2017-11-29 18:26:55 -0800 | [diff] [blame] | 266 | private void postSuccess(String packageName, ParcelFileDescriptor fd, |
| 267 | ISnapshotRuntimeProfileCallback callback) { |
| 268 | if (DEBUG) { |
| 269 | Slog.d(TAG, "Successfully snapshot profile for " + packageName); |
| 270 | } |
| 271 | mHandler.post(() -> { |
| 272 | try { |
| 273 | callback.onSuccess(fd); |
| 274 | } catch (RemoteException e) { |
| 275 | Slog.w(TAG, |
| 276 | "Failed to call onSuccess after profile snapshot for " + packageName, e); |
| 277 | } |
| 278 | }); |
| 279 | } |
| 280 | |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 281 | /** |
| 282 | * Verify that the binder calling uid has {@code android.permission.READ_RUNTIME_PROFILE}. |
| 283 | * If not, it throws a {@link SecurityException}. |
| 284 | */ |
| 285 | private void checkReadRuntimeProfilePermission() { |
| 286 | if (DEBUG_IGNORE_PERMISSIONS) { |
| 287 | return; |
| 288 | } |
| 289 | try { |
| 290 | int result = mPackageManager.checkUidPermission( |
| 291 | Manifest.permission.READ_RUNTIME_PROFILES, Binder.getCallingUid()); |
| 292 | if (result != PackageManager.PERMISSION_GRANTED) { |
| 293 | throw new SecurityException("You need " |
| 294 | + Manifest.permission.READ_RUNTIME_PROFILES |
| 295 | + " permission to snapshot profiles."); |
| 296 | } |
| 297 | } catch (RemoteException e) { |
| 298 | // Should not happen. |
| 299 | } |
| 300 | } |
Calin Juravle | 3621be7 | 2018-01-18 15:17:29 -0800 | [diff] [blame] | 301 | |
| 302 | /** |
| 303 | * Prepare the application profiles. |
| 304 | * For all code paths: |
| 305 | * - create the current primary profile to save time at app startup time. |
| 306 | * - copy the profiles from the associated dex metadata file to the reference profile. |
| 307 | */ |
| 308 | public void prepareAppProfiles(PackageParser.Package pkg, @UserIdInt int user) { |
| 309 | final int appId = UserHandle.getAppId(pkg.applicationInfo.uid); |
Calin Juravle | 5bbe26e | 2018-01-24 14:43:24 -0800 | [diff] [blame] | 310 | if (user < 0) { |
| 311 | Slog.wtf(TAG, "Invalid user id: " + user); |
| 312 | return; |
| 313 | } |
| 314 | if (appId < 0) { |
| 315 | Slog.wtf(TAG, "Invalid app id: " + appId); |
| 316 | return; |
| 317 | } |
Calin Juravle | 3621be7 | 2018-01-18 15:17:29 -0800 | [diff] [blame] | 318 | try { |
| 319 | ArrayMap<String, String> codePathsProfileNames = getPackageProfileNames(pkg); |
| 320 | for (int i = codePathsProfileNames.size() - 1; i >= 0; i--) { |
| 321 | String codePath = codePathsProfileNames.keyAt(i); |
| 322 | String profileName = codePathsProfileNames.valueAt(i); |
| 323 | File dexMetadata = DexMetadataHelper.findDexMetadataForFile(new File(codePath)); |
| 324 | String dexMetadataPath = dexMetadata == null ? null : dexMetadata.getAbsolutePath(); |
| 325 | synchronized (mInstaller) { |
| 326 | boolean result = mInstaller.prepareAppProfile(pkg.packageName, user, appId, |
| 327 | profileName, codePath, dexMetadataPath); |
| 328 | if (!result) { |
| 329 | Slog.e(TAG, "Failed to prepare profile for " + |
| 330 | pkg.packageName + ":" + codePath); |
| 331 | } |
| 332 | } |
| 333 | } |
| 334 | } catch (InstallerException e) { |
| 335 | Slog.e(TAG, "Failed to prepare profile for " + pkg.packageName, e); |
| 336 | } |
| 337 | } |
| 338 | |
| 339 | /** |
Calin Juravle | 5bbe26e | 2018-01-24 14:43:24 -0800 | [diff] [blame] | 340 | * Prepares the app profiles for a set of users. {@see ArtManagerService#prepareAppProfiles}. |
| 341 | */ |
| 342 | public void prepareAppProfiles(PackageParser.Package pkg, int[] user) { |
| 343 | for (int i = 0; i < user.length; i++) { |
| 344 | prepareAppProfiles(pkg, user[i]); |
| 345 | } |
| 346 | } |
| 347 | |
| 348 | /** |
Calin Juravle | 6ae39fc | 2018-01-19 20:32:47 -0800 | [diff] [blame] | 349 | * Clear the profiles for the given package. |
| 350 | */ |
| 351 | public void clearAppProfiles(PackageParser.Package pkg) { |
| 352 | try { |
| 353 | ArrayMap<String, String> packageProfileNames = getPackageProfileNames(pkg); |
| 354 | for (int i = packageProfileNames.size() - 1; i >= 0; i--) { |
| 355 | String profileName = packageProfileNames.valueAt(i); |
| 356 | mInstaller.clearAppProfiles(pkg.packageName, profileName); |
| 357 | } |
| 358 | } catch (InstallerException e) { |
| 359 | Slog.w(TAG, String.valueOf(e)); |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | /** |
| 364 | * Dumps the profiles for the given package. |
| 365 | */ |
| 366 | public void dumpProfiles(PackageParser.Package pkg) { |
| 367 | final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); |
| 368 | try { |
| 369 | ArrayMap<String, String> packageProfileNames = getPackageProfileNames(pkg); |
| 370 | for (int i = packageProfileNames.size() - 1; i >= 0; i--) { |
| 371 | String codePath = packageProfileNames.keyAt(i); |
| 372 | String profileName = packageProfileNames.valueAt(i); |
| 373 | synchronized (mInstallLock) { |
| 374 | mInstaller.dumpProfiles(sharedGid, pkg.packageName, profileName, codePath); |
| 375 | } |
| 376 | } |
| 377 | } catch (InstallerException e) { |
| 378 | Slog.w(TAG, "Failed to dump profiles", e); |
| 379 | } |
| 380 | } |
| 381 | |
| 382 | /** |
Calin Juravle | 3621be7 | 2018-01-18 15:17:29 -0800 | [diff] [blame] | 383 | * Build the profiles names for all the package code paths (excluding resource only paths). |
| 384 | * Return the map [code path -> profile name]. |
| 385 | */ |
| 386 | private ArrayMap<String, String> getPackageProfileNames(PackageParser.Package pkg) { |
| 387 | ArrayMap<String, String> result = new ArrayMap<>(); |
| 388 | if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) { |
| 389 | result.put(pkg.baseCodePath, ArtManager.getProfileName(null)); |
| 390 | } |
| 391 | if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { |
| 392 | for (int i = 0; i < pkg.splitCodePaths.length; i++) { |
| 393 | if ((pkg.splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) { |
| 394 | result.put(pkg.splitCodePaths[i], ArtManager.getProfileName(pkg.splitNames[i])); |
| 395 | } |
| 396 | } |
| 397 | } |
| 398 | return result; |
| 399 | } |
Calin Juravle | 45f8b29 | 2017-11-07 18:49:43 -0800 | [diff] [blame] | 400 | } |