blob: dea78630e4fe1b48a78bd38285d3c7b8fbd33a7d [file] [log] [blame]
Andreas Gampea8908752015-11-10 08:58:14 -08001/*
2 * Copyright (C) 2016 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;
18
Andreas Gampeabcbe2f2016-02-26 11:25:36 -080019import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
20import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
21
Jeff Sharkeyc98c7bc2016-12-07 14:57:34 -070022import android.annotation.Nullable;
Andreas Gampea8908752015-11-10 08:58:14 -080023import android.content.Context;
Andreas Gampea8908752015-11-10 08:58:14 -080024import android.content.pm.IOtaDexopt;
25import android.content.pm.PackageParser;
Andreas Gampea8908752015-11-10 08:58:14 -080026import android.os.Environment;
27import android.os.RemoteException;
28import android.os.ResultReceiver;
29import android.os.ServiceManager;
Dianne Hackborn354736e2016-08-22 17:00:05 -070030import android.os.ShellCallback;
Andreas Gampea8908752015-11-10 08:58:14 -080031import android.os.storage.StorageManager;
Andreas Gampea8908752015-11-10 08:58:14 -080032import android.util.Log;
Andreas Gampeabcbe2f2016-02-26 11:25:36 -080033import android.util.Slog;
Jeff Sharkeyc98c7bc2016-12-07 14:57:34 -070034
Andreas Gampe77cc8172016-09-13 11:12:13 -070035import com.android.internal.logging.MetricsLogger;
Jeff Sharkey740f5232016-12-09 14:31:26 -070036import com.android.server.pm.Installer.InstallerException;
Calin Juravle1d0e83d2017-07-17 15:12:01 -070037import com.android.server.pm.dex.DexoptOptions;
Andreas Gampea8908752015-11-10 08:58:14 -080038
39import java.io.File;
40import java.io.FileDescriptor;
Andreas Gampecc241a52016-06-23 20:27:12 -070041import java.util.ArrayList;
Andreas Gampea8908752015-11-10 08:58:14 -080042import java.util.Collection;
Andreas Gampe069a91c2018-09-05 16:11:50 -070043import java.util.Collections;
Andreas Gampea8908752015-11-10 08:58:14 -080044import java.util.List;
Andreas Gampe77cc8172016-09-13 11:12:13 -070045import java.util.concurrent.TimeUnit;
Andreas Gampea8908752015-11-10 08:58:14 -080046
47/**
48 * A service for A/B OTA dexopting.
49 *
50 * {@hide}
51 */
52public class OtaDexoptService extends IOtaDexopt.Stub {
53 private final static String TAG = "OTADexopt";
54 private final static boolean DEBUG_DEXOPT = true;
Andreas Gampea8908752015-11-10 08:58:14 -080055
Andreas Gampedab38e02016-09-09 17:50:20 -070056 // The amount of "available" (free - low threshold) space necessary at the start of an OTA to
57 // not bulk-delete unused apps' odex files.
58 private final static long BULK_DELETE_THRESHOLD = 1024 * 1024 * 1024; // 1GB.
59
Andreas Gampea8908752015-11-10 08:58:14 -080060 private final Context mContext;
Andreas Gampea8908752015-11-10 08:58:14 -080061 private final PackageManagerService mPackageManagerService;
Andreas Gampe7bad8fd32018-09-15 11:27:58 -070062 private final MetricsLogger metricsLogger;
Andreas Gampea8908752015-11-10 08:58:14 -080063
64 // TODO: Evaluate the need for WeakReferences here.
Andreas Gampecc241a52016-06-23 20:27:12 -070065
66 /**
Andreas Gampe115514b2016-07-28 16:54:41 -070067 * The list of dexopt invocations for all work.
Andreas Gampecc241a52016-06-23 20:27:12 -070068 */
Andreas Gampe115514b2016-07-28 16:54:41 -070069 private List<String> mDexoptCommands;
Andreas Gampecc241a52016-06-23 20:27:12 -070070
Andreas Gampebf062322016-06-10 15:21:39 -070071 private int completeSize;
Andreas Gampea8908752015-11-10 08:58:14 -080072
Andreas Gampe77cc8172016-09-13 11:12:13 -070073 // MetricsLogger properties.
74
75 // Space before and after.
76 private long availableSpaceBefore;
77 private long availableSpaceAfterBulkDelete;
78 private long availableSpaceAfterDexopt;
79
80 // Packages.
81 private int importantPackageCount;
82 private int otherPackageCount;
83
84 // Number of dexopt commands. This may be different from the count of packages.
85 private int dexoptCommandCountTotal;
86 private int dexoptCommandCountExecuted;
87
88 // For spent time.
89 private long otaDexoptTimeStart;
90
91
Andreas Gampea8908752015-11-10 08:58:14 -080092 public OtaDexoptService(Context context, PackageManagerService packageManagerService) {
93 this.mContext = context;
94 this.mPackageManagerService = packageManagerService;
Andreas Gampe7bad8fd32018-09-15 11:27:58 -070095 metricsLogger = new MetricsLogger();
Andreas Gampea8908752015-11-10 08:58:14 -080096 }
97
98 public static OtaDexoptService main(Context context,
99 PackageManagerService packageManagerService) {
100 OtaDexoptService ota = new OtaDexoptService(context, packageManagerService);
101 ServiceManager.addService("otadexopt", ota);
102
Andreas Gampe3e1b6ad2017-04-10 15:48:50 -0700103 // Now it's time to check whether we need to move any A/B artifacts.
104 ota.moveAbArtifacts(packageManagerService.mInstaller);
105
Andreas Gampea8908752015-11-10 08:58:14 -0800106 return ota;
107 }
108
109 @Override
110 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
Dianne Hackborn354736e2016-08-22 17:00:05 -0700111 String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
Andreas Gampea8908752015-11-10 08:58:14 -0800112 (new OtaDexoptShellCommand(this)).exec(
Dianne Hackborn354736e2016-08-22 17:00:05 -0700113 this, in, out, err, args, callback, resultReceiver);
Andreas Gampea8908752015-11-10 08:58:14 -0800114 }
115
116 @Override
117 public synchronized void prepare() throws RemoteException {
Andreas Gampe115514b2016-07-28 16:54:41 -0700118 if (mDexoptCommands != null) {
Andreas Gampea8908752015-11-10 08:58:14 -0800119 throw new IllegalStateException("already called prepare()");
120 }
Todd Kennedya8d4f482016-08-18 11:22:52 -0700121 final List<PackageParser.Package> important;
122 final List<PackageParser.Package> others;
Andreas Gampea8908752015-11-10 08:58:14 -0800123 synchronized (mPackageManagerService.mPackages) {
Andreas Gampe115514b2016-07-28 16:54:41 -0700124 // Important: the packages we need to run with ab-ota compiler-reason.
Todd Kennedya8d4f482016-08-18 11:22:52 -0700125 important = PackageManagerServiceUtils.getPackagesForDexopt(
Andreas Gampe069a91c2018-09-05 16:11:50 -0700126 mPackageManagerService.mPackages.values(), mPackageManagerService,
127 DEBUG_DEXOPT);
Andreas Gampe115514b2016-07-28 16:54:41 -0700128 // Others: we should optimize this with the (first-)boot compiler-reason.
Todd Kennedya8d4f482016-08-18 11:22:52 -0700129 others = new ArrayList<>(mPackageManagerService.mPackages.values());
Andreas Gampe115514b2016-07-28 16:54:41 -0700130 others.removeAll(important);
131
132 // Pre-size the array list by over-allocating by a factor of 1.5.
133 mDexoptCommands = new ArrayList<>(3 * mPackageManagerService.mPackages.size() / 2);
Todd Kennedya8d4f482016-08-18 11:22:52 -0700134 }
Andreas Gampe115514b2016-07-28 16:54:41 -0700135
Todd Kennedya8d4f482016-08-18 11:22:52 -0700136 for (PackageParser.Package p : important) {
Nicolas Geoffray30f185872017-03-24 15:13:38 +0000137 mDexoptCommands.addAll(generatePackageDexopts(p, PackageManagerService.REASON_AB_OTA));
Todd Kennedya8d4f482016-08-18 11:22:52 -0700138 }
139 for (PackageParser.Package p : others) {
140 // We assume here that there are no core apps left.
141 if (p.coreApp) {
142 throw new IllegalStateException("Found a core app that's not important");
Andreas Gampe115514b2016-07-28 16:54:41 -0700143 }
Todd Kennedya8d4f482016-08-18 11:22:52 -0700144 mDexoptCommands.addAll(
145 generatePackageDexopts(p, PackageManagerService.REASON_FIRST_BOOT));
Andreas Gampea8908752015-11-10 08:58:14 -0800146 }
Andreas Gampe115514b2016-07-28 16:54:41 -0700147 completeSize = mDexoptCommands.size();
Andreas Gampedab38e02016-09-09 17:50:20 -0700148
Andreas Gampe77cc8172016-09-13 11:12:13 -0700149 long spaceAvailable = getAvailableSpace();
150 if (spaceAvailable < BULK_DELETE_THRESHOLD) {
Andreas Gampedab38e02016-09-09 17:50:20 -0700151 Log.i(TAG, "Low on space, deleting oat files in an attempt to free up space: "
152 + PackageManagerServiceUtils.packagesToString(others));
153 for (PackageParser.Package pkg : others) {
Shubham Ajmera246dccf2017-05-24 17:46:36 -0700154 mPackageManagerService.deleteOatArtifactsOfPackage(pkg.packageName);
Andreas Gampedab38e02016-09-09 17:50:20 -0700155 }
156 }
Andreas Gampe77cc8172016-09-13 11:12:13 -0700157 long spaceAvailableNow = getAvailableSpace();
158
159 prepareMetricsLogging(important.size(), others.size(), spaceAvailable, spaceAvailableNow);
Andreas Gampe069a91c2018-09-05 16:11:50 -0700160
161 if (DEBUG_DEXOPT) {
162 try {
163 // Output some data about the packages.
164 PackageParser.Package lastUsed = Collections.max(important,
165 (pkg1, pkg2) -> Long.compare(
166 pkg1.getLatestForegroundPackageUseTimeInMills(),
167 pkg2.getLatestForegroundPackageUseTimeInMills()));
168 Log.d(TAG, "A/B OTA: lastUsed time = "
169 + lastUsed.getLatestForegroundPackageUseTimeInMills());
170 Log.d(TAG, "A/B OTA: deprioritized packages:");
171 for (PackageParser.Package pkg : others) {
172 Log.d(TAG, " " + pkg.packageName + " - "
173 + pkg.getLatestForegroundPackageUseTimeInMills());
174 }
175 } catch (Exception ignored) {
176 }
177 }
Andreas Gampea8908752015-11-10 08:58:14 -0800178 }
179
180 @Override
181 public synchronized void cleanup() throws RemoteException {
182 if (DEBUG_DEXOPT) {
183 Log.i(TAG, "Cleaning up OTA Dexopt state.");
184 }
Andreas Gampe115514b2016-07-28 16:54:41 -0700185 mDexoptCommands = null;
Andreas Gampe8d1d2ab2016-09-19 15:18:46 -0700186 availableSpaceAfterDexopt = getAvailableSpace();
Andreas Gampe77cc8172016-09-13 11:12:13 -0700187
188 performMetricsLogging();
Andreas Gampea8908752015-11-10 08:58:14 -0800189 }
190
191 @Override
192 public synchronized boolean isDone() throws RemoteException {
Andreas Gampe115514b2016-07-28 16:54:41 -0700193 if (mDexoptCommands == null) {
Andreas Gampea8908752015-11-10 08:58:14 -0800194 throw new IllegalStateException("done() called before prepare()");
195 }
196
Andreas Gampe115514b2016-07-28 16:54:41 -0700197 return mDexoptCommands.isEmpty();
Andreas Gampea8908752015-11-10 08:58:14 -0800198 }
199
200 @Override
Andreas Gampebf062322016-06-10 15:21:39 -0700201 public synchronized float getProgress() throws RemoteException {
Andreas Gampe115514b2016-07-28 16:54:41 -0700202 // Approximate the progress by the amount of already completed commands.
Andreas Gampebf062322016-06-10 15:21:39 -0700203 if (completeSize == 0) {
204 return 1f;
205 }
Andreas Gampe115514b2016-07-28 16:54:41 -0700206 int commandsLeft = mDexoptCommands.size();
207 return (completeSize - commandsLeft) / ((float)completeSize);
Andreas Gampecc241a52016-06-23 20:27:12 -0700208 }
209
210 @Override
211 public synchronized String nextDexoptCommand() throws RemoteException {
Andreas Gampe115514b2016-07-28 16:54:41 -0700212 if (mDexoptCommands == null) {
Andreas Gampecc241a52016-06-23 20:27:12 -0700213 throw new IllegalStateException("dexoptNextPackage() called before prepare()");
214 }
215
Andreas Gampe115514b2016-07-28 16:54:41 -0700216 if (mDexoptCommands.isEmpty()) {
217 return "(all done)";
218 }
Andreas Gampecc241a52016-06-23 20:27:12 -0700219
Andreas Gampe115514b2016-07-28 16:54:41 -0700220 String next = mDexoptCommands.remove(0);
Andreas Gampecc241a52016-06-23 20:27:12 -0700221
Andreas Gampedab38e02016-09-09 17:50:20 -0700222 if (getAvailableSpace() > 0) {
Andreas Gampe77cc8172016-09-13 11:12:13 -0700223 dexoptCommandCountExecuted++;
224
Andreas Gampe332dd122017-03-17 13:59:08 -0700225 Log.d(TAG, "Next command: " + next);
Andreas Gampe115514b2016-07-28 16:54:41 -0700226 return next;
227 } else {
Andreas Gampedab38e02016-09-09 17:50:20 -0700228 if (DEBUG_DEXOPT) {
229 Log.w(TAG, "Not enough space for OTA dexopt, stopping with "
230 + (mDexoptCommands.size() + 1) + " commands left.");
231 }
Andreas Gampe115514b2016-07-28 16:54:41 -0700232 mDexoptCommands.clear();
233 return "(no free space)";
Andreas Gampecc241a52016-06-23 20:27:12 -0700234 }
235 }
236
Andreas Gampedab38e02016-09-09 17:50:20 -0700237 private long getMainLowSpaceThreshold() {
Andreas Gampecc241a52016-06-23 20:27:12 -0700238 File dataDir = Environment.getDataDirectory();
239 @SuppressWarnings("deprecation")
240 long lowThreshold = StorageManager.from(mContext).getStorageLowBytes(dataDir);
241 if (lowThreshold == 0) {
242 throw new IllegalStateException("Invalid low memory threshold");
243 }
Andreas Gampedab38e02016-09-09 17:50:20 -0700244 return lowThreshold;
245 }
246
247 /**
248 * Returns the difference of free space to the low-storage-space threshold. Positive values
249 * indicate free bytes.
250 */
251 private long getAvailableSpace() {
252 // TODO: If apps are not installed in the internal /data partition, we should compare
253 // against that storage's free capacity.
254 long lowThreshold = getMainLowSpaceThreshold();
255
256 File dataDir = Environment.getDataDirectory();
Andreas Gampecc241a52016-06-23 20:27:12 -0700257 long usableSpace = dataDir.getUsableSpace();
Andreas Gampedab38e02016-09-09 17:50:20 -0700258
259 return usableSpace - lowThreshold;
260 }
261
Andreas Gampe115514b2016-07-28 16:54:41 -0700262 /**
263 * Generate all dexopt commands for the given package.
264 */
265 private synchronized List<String> generatePackageDexopts(PackageParser.Package pkg,
266 int compilationReason) {
Jeff Sharkeyc98c7bc2016-12-07 14:57:34 -0700267 // Intercept and collect dexopt requests
268 final List<String> commands = new ArrayList<String>();
269 final Installer collectingInstaller = new Installer(mContext, true) {
Andreas Gampe37f190b2017-04-17 11:27:58 -0700270 /**
271 * Encode the dexopt command into a string.
272 *
273 * Note: If you have to change the signature of this function, increase the version
274 * number, and update the counterpart in
275 * frameworks/native/cmds/installd/otapreopt.cpp.
276 */
Jeff Sharkeyc98c7bc2016-12-07 14:57:34 -0700277 @Override
278 public void dexopt(String apkPath, int uid, @Nullable String pkgName,
279 String instructionSet, int dexoptNeeded, @Nullable String outputPath,
280 int dexFlags, String compilerFilter, @Nullable String volumeUuid,
David Brazdil3d44ed02018-01-16 20:01:47 +0000281 @Nullable String sharedLibraries, @Nullable String seInfo, boolean downgrade,
Calin Juravlecc651942018-02-01 17:20:51 +0000282 int targetSdkVersion, @Nullable String profileName,
Calin Juravle4bc8f4d2018-02-12 12:00:44 -0800283 @Nullable String dexMetadataPath, @Nullable String dexoptCompilationReason)
284 throws InstallerException {
Andreas Gampe37f190b2017-04-17 11:27:58 -0700285 final StringBuilder builder = new StringBuilder();
286
Andreas Gampee164b182018-09-18 10:37:59 -0700287 // The current version. For v10, see b/115993344.
288 builder.append("10 ");
Andreas Gampe37f190b2017-04-17 11:27:58 -0700289
290 builder.append("dexopt");
291
292 encodeParameter(builder, apkPath);
293 encodeParameter(builder, uid);
294 encodeParameter(builder, pkgName);
295 encodeParameter(builder, instructionSet);
296 encodeParameter(builder, dexoptNeeded);
297 encodeParameter(builder, outputPath);
298 encodeParameter(builder, dexFlags);
299 encodeParameter(builder, compilerFilter);
300 encodeParameter(builder, volumeUuid);
301 encodeParameter(builder, sharedLibraries);
302 encodeParameter(builder, seInfo);
Shubham Ajmera246dccf2017-05-24 17:46:36 -0700303 encodeParameter(builder, downgrade);
David Brazdil3d44ed02018-01-16 20:01:47 +0000304 encodeParameter(builder, targetSdkVersion);
Calin Juravle6ae39fc2018-01-19 20:32:47 -0800305 encodeParameter(builder, profileName);
Calin Juravlecc651942018-02-01 17:20:51 +0000306 encodeParameter(builder, dexMetadataPath);
Calin Juravle4bc8f4d2018-02-12 12:00:44 -0800307 encodeParameter(builder, dexoptCompilationReason);
Andreas Gampe37f190b2017-04-17 11:27:58 -0700308
309 commands.add(builder.toString());
310 }
311
312 /**
313 * Encode a parameter as necessary for the commands string.
314 */
315 private void encodeParameter(StringBuilder builder, Object arg) {
316 builder.append(' ');
317
318 if (arg == null) {
319 builder.append('!');
Andreas Gampef4eb8eb2017-05-09 23:03:19 -0700320 return;
Andreas Gampe37f190b2017-04-17 11:27:58 -0700321 }
322
323 String txt = String.valueOf(arg);
324 if (txt.indexOf('\0') != -1 || txt.indexOf(' ') != -1 || "!".equals(txt)) {
325 throw new IllegalArgumentException(
326 "Invalid argument while executing " + arg);
327 }
328 builder.append(txt);
Jeff Sharkeyc98c7bc2016-12-07 14:57:34 -0700329 }
330 };
Andreas Gampecc241a52016-06-23 20:27:12 -0700331
332 // Use the package manager install and install lock here for the OTA dex optimizer.
333 PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
334 collectingInstaller, mPackageManagerService.mInstallLock, mContext);
Calin Juravle56562132016-07-12 13:56:34 +0100335
Andreas Gampec7e02c12016-08-01 22:08:26 -0700336 String[] libraryDependencies = pkg.usesLibraryFiles;
Calin Juravle1d0e83d2017-07-17 15:12:01 -0700337
Andreas Gampec7e02c12016-08-01 22:08:26 -0700338 optimizer.performDexOpt(pkg, libraryDependencies,
Calin Juravle1d0e83d2017-07-17 15:12:01 -0700339 null /* ISAs */,
Calin Juravle07b6eab2017-03-01 19:55:35 -0800340 null /* CompilerStats.PackageStats */,
Calin Juravle3b74c412017-08-03 19:48:37 -0700341 mPackageManagerService.getDexManager().getPackageUseInfoOrDefault(pkg.packageName),
Calin Juravle1d0e83d2017-07-17 15:12:01 -0700342 new DexoptOptions(pkg.packageName, compilationReason,
343 DexoptOptions.DEXOPT_BOOT_COMPLETE));
Andreas Gampecc241a52016-06-23 20:27:12 -0700344
Jeff Sharkeyc98c7bc2016-12-07 14:57:34 -0700345 return commands;
Andreas Gampebf062322016-06-10 15:21:39 -0700346 }
347
348 @Override
Andreas Gampea8908752015-11-10 08:58:14 -0800349 public synchronized void dexoptNextPackage() throws RemoteException {
Andreas Gampe115514b2016-07-28 16:54:41 -0700350 throw new UnsupportedOperationException();
Andreas Gampea8908752015-11-10 08:58:14 -0800351 }
352
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800353 private void moveAbArtifacts(Installer installer) {
Andreas Gampe115514b2016-07-28 16:54:41 -0700354 if (mDexoptCommands != null) {
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800355 throw new IllegalStateException("Should not be ota-dexopting when trying to move.");
Andreas Gampea8908752015-11-10 08:58:14 -0800356 }
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800357
Andreas Gampe3e1b6ad2017-04-10 15:48:50 -0700358 if (!mPackageManagerService.isUpgrade()) {
359 Slog.d(TAG, "No upgrade, skipping A/B artifacts check.");
360 return;
361 }
362
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800363 // Look into all packages.
364 Collection<PackageParser.Package> pkgs = mPackageManagerService.getPackages();
Andreas Gampe3e1b6ad2017-04-10 15:48:50 -0700365 int packagePaths = 0;
366 int pathsSuccessful = 0;
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800367 for (PackageParser.Package pkg : pkgs) {
368 if (pkg == null) {
369 continue;
370 }
371
372 // Does the package have code? If not, there won't be any artifacts.
373 if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
374 continue;
375 }
376 if (pkg.codePath == null) {
377 Slog.w(TAG, "Package " + pkg + " can be optimized but has null codePath");
378 continue;
379 }
380
Jaekyun Seok1713d9e2018-01-12 21:47:26 +0900381 // If the path is in /system, /vendor or /product, ignore. It will have been
382 // ota-dexopted into /data/ota and moved into the dalvik-cache already.
383 if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")
384 || pkg.codePath.startsWith("/product")) {
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800385 continue;
386 }
387
388 final String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo);
389 final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
390 final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
391 for (String dexCodeInstructionSet : dexCodeInstructionSets) {
392 for (String path : paths) {
393 String oatDir = PackageDexOptimizer.getOatDir(new File(pkg.codePath)).
394 getAbsolutePath();
395
396 // TODO: Check first whether there is an artifact, to save the roundtrip time.
397
Andreas Gampe3e1b6ad2017-04-10 15:48:50 -0700398 packagePaths++;
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800399 try {
400 installer.moveAb(path, dexCodeInstructionSet, oatDir);
Andreas Gampe3e1b6ad2017-04-10 15:48:50 -0700401 pathsSuccessful++;
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800402 } catch (InstallerException e) {
403 }
404 }
Andreas Gampea8908752015-11-10 08:58:14 -0800405 }
406 }
Andreas Gampe3e1b6ad2017-04-10 15:48:50 -0700407 Slog.i(TAG, "Moved " + pathsSuccessful + "/" + packagePaths);
Andreas Gampea8908752015-11-10 08:58:14 -0800408 }
409
Andreas Gampe77cc8172016-09-13 11:12:13 -0700410 /**
411 * Initialize logging fields.
412 */
413 private void prepareMetricsLogging(int important, int others, long spaceBegin, long spaceBulk) {
414 availableSpaceBefore = spaceBegin;
415 availableSpaceAfterBulkDelete = spaceBulk;
416 availableSpaceAfterDexopt = 0;
417
418 importantPackageCount = important;
419 otherPackageCount = others;
420
421 dexoptCommandCountTotal = mDexoptCommands.size();
422 dexoptCommandCountExecuted = 0;
423
424 otaDexoptTimeStart = System.nanoTime();
425 }
426
427 private static int inMegabytes(long value) {
428 long in_mega_bytes = value / (1024 * 1024);
429 if (in_mega_bytes > Integer.MAX_VALUE) {
430 Log.w(TAG, "Recording " + in_mega_bytes + "MB of free space, overflowing range");
431 return Integer.MAX_VALUE;
432 }
433 return (int)in_mega_bytes;
434 }
435
436 private void performMetricsLogging() {
437 long finalTime = System.nanoTime();
438
Andreas Gampe7bad8fd32018-09-15 11:27:58 -0700439 metricsLogger.histogram("ota_dexopt_available_space_before_mb",
Andreas Gampe77cc8172016-09-13 11:12:13 -0700440 inMegabytes(availableSpaceBefore));
Andreas Gampe7bad8fd32018-09-15 11:27:58 -0700441 metricsLogger.histogram("ota_dexopt_available_space_after_bulk_delete_mb",
Andreas Gampe77cc8172016-09-13 11:12:13 -0700442 inMegabytes(availableSpaceAfterBulkDelete));
Andreas Gampe7bad8fd32018-09-15 11:27:58 -0700443 metricsLogger.histogram("ota_dexopt_available_space_after_dexopt_mb",
Andreas Gampe77cc8172016-09-13 11:12:13 -0700444 inMegabytes(availableSpaceAfterDexopt));
445
Andreas Gampe7bad8fd32018-09-15 11:27:58 -0700446 metricsLogger.histogram("ota_dexopt_num_important_packages", importantPackageCount);
447 metricsLogger.histogram("ota_dexopt_num_other_packages", otherPackageCount);
Andreas Gampe77cc8172016-09-13 11:12:13 -0700448
Andreas Gampe7bad8fd32018-09-15 11:27:58 -0700449 metricsLogger.histogram("ota_dexopt_num_commands", dexoptCommandCountTotal);
450 metricsLogger.histogram("ota_dexopt_num_commands_executed", dexoptCommandCountExecuted);
Andreas Gampe77cc8172016-09-13 11:12:13 -0700451
452 final int elapsedTimeSeconds =
453 (int) TimeUnit.NANOSECONDS.toSeconds(finalTime - otaDexoptTimeStart);
Andreas Gampe7bad8fd32018-09-15 11:27:58 -0700454 metricsLogger.histogram("ota_dexopt_time_s", elapsedTimeSeconds);
Andreas Gampe77cc8172016-09-13 11:12:13 -0700455 }
456
Andreas Gampea8908752015-11-10 08:58:14 -0800457 private static class OTADexoptPackageDexOptimizer extends
458 PackageDexOptimizer.ForcedUpdatePackageDexOptimizer {
Andreas Gampea8908752015-11-10 08:58:14 -0800459 public OTADexoptPackageDexOptimizer(Installer installer, Object installLock,
460 Context context) {
461 super(installer, installLock, context, "*otadexopt*");
462 }
Andreas Gampea8908752015-11-10 08:58:14 -0800463 }
Andreas Gampea8908752015-11-10 08:58:14 -0800464}