blob: 03950119ea13143ab186a8ddde0942aed1a70af4 [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 Gampea8908752015-11-10 08:58:14 -080043import java.util.List;
Andreas Gampe77cc8172016-09-13 11:12:13 -070044import java.util.concurrent.TimeUnit;
Andreas Gampea8908752015-11-10 08:58:14 -080045
46/**
47 * A service for A/B OTA dexopting.
48 *
49 * {@hide}
50 */
51public class OtaDexoptService extends IOtaDexopt.Stub {
52 private final static String TAG = "OTADexopt";
53 private final static boolean DEBUG_DEXOPT = true;
Andreas Gampea8908752015-11-10 08:58:14 -080054
Andreas Gampec7e02c12016-08-01 22:08:26 -070055 // The synthetic library dependencies denoting "no checks."
Shubham Ajmera557c0542017-09-05 10:20:41 -070056 private final static String[] NO_LIBRARIES =
57 new String[] { PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK };
Andreas Gampec7e02c12016-08-01 22:08:26 -070058
Andreas Gampedab38e02016-09-09 17:50:20 -070059 // The amount of "available" (free - low threshold) space necessary at the start of an OTA to
60 // not bulk-delete unused apps' odex files.
61 private final static long BULK_DELETE_THRESHOLD = 1024 * 1024 * 1024; // 1GB.
62
Andreas Gampea8908752015-11-10 08:58:14 -080063 private final Context mContext;
Andreas Gampea8908752015-11-10 08:58:14 -080064 private final PackageManagerService mPackageManagerService;
65
66 // TODO: Evaluate the need for WeakReferences here.
Andreas Gampecc241a52016-06-23 20:27:12 -070067
68 /**
Andreas Gampe115514b2016-07-28 16:54:41 -070069 * The list of dexopt invocations for all work.
Andreas Gampecc241a52016-06-23 20:27:12 -070070 */
Andreas Gampe115514b2016-07-28 16:54:41 -070071 private List<String> mDexoptCommands;
Andreas Gampecc241a52016-06-23 20:27:12 -070072
Andreas Gampebf062322016-06-10 15:21:39 -070073 private int completeSize;
Andreas Gampea8908752015-11-10 08:58:14 -080074
Andreas Gampe77cc8172016-09-13 11:12:13 -070075 // MetricsLogger properties.
76
77 // Space before and after.
78 private long availableSpaceBefore;
79 private long availableSpaceAfterBulkDelete;
80 private long availableSpaceAfterDexopt;
81
82 // Packages.
83 private int importantPackageCount;
84 private int otherPackageCount;
85
86 // Number of dexopt commands. This may be different from the count of packages.
87 private int dexoptCommandCountTotal;
88 private int dexoptCommandCountExecuted;
89
90 // For spent time.
91 private long otaDexoptTimeStart;
92
93
Andreas Gampea8908752015-11-10 08:58:14 -080094 public OtaDexoptService(Context context, PackageManagerService packageManagerService) {
95 this.mContext = context;
96 this.mPackageManagerService = packageManagerService;
Andreas Gampea8908752015-11-10 08:58:14 -080097 }
98
99 public static OtaDexoptService main(Context context,
100 PackageManagerService packageManagerService) {
101 OtaDexoptService ota = new OtaDexoptService(context, packageManagerService);
102 ServiceManager.addService("otadexopt", ota);
103
Andreas Gampe3e1b6ad2017-04-10 15:48:50 -0700104 // Now it's time to check whether we need to move any A/B artifacts.
105 ota.moveAbArtifacts(packageManagerService.mInstaller);
106
Andreas Gampea8908752015-11-10 08:58:14 -0800107 return ota;
108 }
109
110 @Override
111 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
Dianne Hackborn354736e2016-08-22 17:00:05 -0700112 String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
Andreas Gampea8908752015-11-10 08:58:14 -0800113 (new OtaDexoptShellCommand(this)).exec(
Dianne Hackborn354736e2016-08-22 17:00:05 -0700114 this, in, out, err, args, callback, resultReceiver);
Andreas Gampea8908752015-11-10 08:58:14 -0800115 }
116
117 @Override
118 public synchronized void prepare() throws RemoteException {
Andreas Gampe115514b2016-07-28 16:54:41 -0700119 if (mDexoptCommands != null) {
Andreas Gampea8908752015-11-10 08:58:14 -0800120 throw new IllegalStateException("already called prepare()");
121 }
Todd Kennedya8d4f482016-08-18 11:22:52 -0700122 final List<PackageParser.Package> important;
123 final List<PackageParser.Package> others;
Andreas Gampea8908752015-11-10 08:58:14 -0800124 synchronized (mPackageManagerService.mPackages) {
Andreas Gampe115514b2016-07-28 16:54:41 -0700125 // Important: the packages we need to run with ab-ota compiler-reason.
Todd Kennedya8d4f482016-08-18 11:22:52 -0700126 important = PackageManagerServiceUtils.getPackagesForDexopt(
David Brazdil6b4736d2016-02-04 11:54:17 +0000127 mPackageManagerService.mPackages.values(), mPackageManagerService);
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 Gampea8908752015-11-10 08:58:14 -0800160 }
161
162 @Override
163 public synchronized void cleanup() throws RemoteException {
164 if (DEBUG_DEXOPT) {
165 Log.i(TAG, "Cleaning up OTA Dexopt state.");
166 }
Andreas Gampe115514b2016-07-28 16:54:41 -0700167 mDexoptCommands = null;
Andreas Gampe8d1d2ab2016-09-19 15:18:46 -0700168 availableSpaceAfterDexopt = getAvailableSpace();
Andreas Gampe77cc8172016-09-13 11:12:13 -0700169
170 performMetricsLogging();
Andreas Gampea8908752015-11-10 08:58:14 -0800171 }
172
173 @Override
174 public synchronized boolean isDone() throws RemoteException {
Andreas Gampe115514b2016-07-28 16:54:41 -0700175 if (mDexoptCommands == null) {
Andreas Gampea8908752015-11-10 08:58:14 -0800176 throw new IllegalStateException("done() called before prepare()");
177 }
178
Andreas Gampe115514b2016-07-28 16:54:41 -0700179 return mDexoptCommands.isEmpty();
Andreas Gampea8908752015-11-10 08:58:14 -0800180 }
181
182 @Override
Andreas Gampebf062322016-06-10 15:21:39 -0700183 public synchronized float getProgress() throws RemoteException {
Andreas Gampe115514b2016-07-28 16:54:41 -0700184 // Approximate the progress by the amount of already completed commands.
Andreas Gampebf062322016-06-10 15:21:39 -0700185 if (completeSize == 0) {
186 return 1f;
187 }
Andreas Gampe115514b2016-07-28 16:54:41 -0700188 int commandsLeft = mDexoptCommands.size();
189 return (completeSize - commandsLeft) / ((float)completeSize);
Andreas Gampecc241a52016-06-23 20:27:12 -0700190 }
191
192 @Override
193 public synchronized String nextDexoptCommand() throws RemoteException {
Andreas Gampe115514b2016-07-28 16:54:41 -0700194 if (mDexoptCommands == null) {
Andreas Gampecc241a52016-06-23 20:27:12 -0700195 throw new IllegalStateException("dexoptNextPackage() called before prepare()");
196 }
197
Andreas Gampe115514b2016-07-28 16:54:41 -0700198 if (mDexoptCommands.isEmpty()) {
199 return "(all done)";
200 }
Andreas Gampecc241a52016-06-23 20:27:12 -0700201
Andreas Gampe115514b2016-07-28 16:54:41 -0700202 String next = mDexoptCommands.remove(0);
Andreas Gampecc241a52016-06-23 20:27:12 -0700203
Andreas Gampedab38e02016-09-09 17:50:20 -0700204 if (getAvailableSpace() > 0) {
Andreas Gampe77cc8172016-09-13 11:12:13 -0700205 dexoptCommandCountExecuted++;
206
Andreas Gampe332dd122017-03-17 13:59:08 -0700207 Log.d(TAG, "Next command: " + next);
Andreas Gampe115514b2016-07-28 16:54:41 -0700208 return next;
209 } else {
Andreas Gampedab38e02016-09-09 17:50:20 -0700210 if (DEBUG_DEXOPT) {
211 Log.w(TAG, "Not enough space for OTA dexopt, stopping with "
212 + (mDexoptCommands.size() + 1) + " commands left.");
213 }
Andreas Gampe115514b2016-07-28 16:54:41 -0700214 mDexoptCommands.clear();
215 return "(no free space)";
Andreas Gampecc241a52016-06-23 20:27:12 -0700216 }
217 }
218
Andreas Gampedab38e02016-09-09 17:50:20 -0700219 private long getMainLowSpaceThreshold() {
Andreas Gampecc241a52016-06-23 20:27:12 -0700220 File dataDir = Environment.getDataDirectory();
221 @SuppressWarnings("deprecation")
222 long lowThreshold = StorageManager.from(mContext).getStorageLowBytes(dataDir);
223 if (lowThreshold == 0) {
224 throw new IllegalStateException("Invalid low memory threshold");
225 }
Andreas Gampedab38e02016-09-09 17:50:20 -0700226 return lowThreshold;
227 }
228
229 /**
230 * Returns the difference of free space to the low-storage-space threshold. Positive values
231 * indicate free bytes.
232 */
233 private long getAvailableSpace() {
234 // TODO: If apps are not installed in the internal /data partition, we should compare
235 // against that storage's free capacity.
236 long lowThreshold = getMainLowSpaceThreshold();
237
238 File dataDir = Environment.getDataDirectory();
Andreas Gampecc241a52016-06-23 20:27:12 -0700239 long usableSpace = dataDir.getUsableSpace();
Andreas Gampedab38e02016-09-09 17:50:20 -0700240
241 return usableSpace - lowThreshold;
242 }
243
Andreas Gampe115514b2016-07-28 16:54:41 -0700244 /**
245 * Generate all dexopt commands for the given package.
246 */
247 private synchronized List<String> generatePackageDexopts(PackageParser.Package pkg,
248 int compilationReason) {
Jeff Sharkeyc98c7bc2016-12-07 14:57:34 -0700249 // Intercept and collect dexopt requests
250 final List<String> commands = new ArrayList<String>();
251 final Installer collectingInstaller = new Installer(mContext, true) {
Andreas Gampe37f190b2017-04-17 11:27:58 -0700252 /**
253 * Encode the dexopt command into a string.
254 *
255 * Note: If you have to change the signature of this function, increase the version
256 * number, and update the counterpart in
257 * frameworks/native/cmds/installd/otapreopt.cpp.
258 */
Jeff Sharkeyc98c7bc2016-12-07 14:57:34 -0700259 @Override
260 public void dexopt(String apkPath, int uid, @Nullable String pkgName,
261 String instructionSet, int dexoptNeeded, @Nullable String outputPath,
262 int dexFlags, String compilerFilter, @Nullable String volumeUuid,
David Brazdil3d44ed02018-01-16 20:01:47 +0000263 @Nullable String sharedLibraries, @Nullable String seInfo, boolean downgrade,
264 int targetSdkVersion)
Shubham Ajmera246dccf2017-05-24 17:46:36 -0700265 throws InstallerException {
Andreas Gampe37f190b2017-04-17 11:27:58 -0700266 final StringBuilder builder = new StringBuilder();
267
David Brazdil3d44ed02018-01-16 20:01:47 +0000268 // The version. Right now it's 4.
269 builder.append("4 ");
Andreas Gampe37f190b2017-04-17 11:27:58 -0700270
271 builder.append("dexopt");
272
273 encodeParameter(builder, apkPath);
274 encodeParameter(builder, uid);
275 encodeParameter(builder, pkgName);
276 encodeParameter(builder, instructionSet);
277 encodeParameter(builder, dexoptNeeded);
278 encodeParameter(builder, outputPath);
279 encodeParameter(builder, dexFlags);
280 encodeParameter(builder, compilerFilter);
281 encodeParameter(builder, volumeUuid);
282 encodeParameter(builder, sharedLibraries);
283 encodeParameter(builder, seInfo);
Shubham Ajmera246dccf2017-05-24 17:46:36 -0700284 encodeParameter(builder, downgrade);
David Brazdil3d44ed02018-01-16 20:01:47 +0000285 encodeParameter(builder, targetSdkVersion);
Andreas Gampe37f190b2017-04-17 11:27:58 -0700286
287 commands.add(builder.toString());
288 }
289
290 /**
291 * Encode a parameter as necessary for the commands string.
292 */
293 private void encodeParameter(StringBuilder builder, Object arg) {
294 builder.append(' ');
295
296 if (arg == null) {
297 builder.append('!');
Andreas Gampef4eb8eb2017-05-09 23:03:19 -0700298 return;
Andreas Gampe37f190b2017-04-17 11:27:58 -0700299 }
300
301 String txt = String.valueOf(arg);
302 if (txt.indexOf('\0') != -1 || txt.indexOf(' ') != -1 || "!".equals(txt)) {
303 throw new IllegalArgumentException(
304 "Invalid argument while executing " + arg);
305 }
306 builder.append(txt);
Jeff Sharkeyc98c7bc2016-12-07 14:57:34 -0700307 }
308 };
Andreas Gampecc241a52016-06-23 20:27:12 -0700309
310 // Use the package manager install and install lock here for the OTA dex optimizer.
311 PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
312 collectingInstaller, mPackageManagerService.mInstallLock, mContext);
Calin Juravle56562132016-07-12 13:56:34 +0100313
Andreas Gampec7e02c12016-08-01 22:08:26 -0700314 String[] libraryDependencies = pkg.usesLibraryFiles;
Todd Kennedyc29b11a2017-10-23 15:55:59 -0700315 if (pkg.isSystem()) {
Andreas Gampec7e02c12016-08-01 22:08:26 -0700316 // For system apps, we want to avoid classpaths checks.
317 libraryDependencies = NO_LIBRARIES;
318 }
319
Calin Juravle1d0e83d2017-07-17 15:12:01 -0700320
Andreas Gampec7e02c12016-08-01 22:08:26 -0700321 optimizer.performDexOpt(pkg, libraryDependencies,
Calin Juravle1d0e83d2017-07-17 15:12:01 -0700322 null /* ISAs */,
Calin Juravle07b6eab2017-03-01 19:55:35 -0800323 null /* CompilerStats.PackageStats */,
Calin Juravle3b74c412017-08-03 19:48:37 -0700324 mPackageManagerService.getDexManager().getPackageUseInfoOrDefault(pkg.packageName),
Calin Juravle1d0e83d2017-07-17 15:12:01 -0700325 new DexoptOptions(pkg.packageName, compilationReason,
326 DexoptOptions.DEXOPT_BOOT_COMPLETE));
Andreas Gampecc241a52016-06-23 20:27:12 -0700327
Jeff Sharkeyc98c7bc2016-12-07 14:57:34 -0700328 return commands;
Andreas Gampebf062322016-06-10 15:21:39 -0700329 }
330
331 @Override
Andreas Gampea8908752015-11-10 08:58:14 -0800332 public synchronized void dexoptNextPackage() throws RemoteException {
Andreas Gampe115514b2016-07-28 16:54:41 -0700333 throw new UnsupportedOperationException();
Andreas Gampea8908752015-11-10 08:58:14 -0800334 }
335
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800336 private void moveAbArtifacts(Installer installer) {
Andreas Gampe115514b2016-07-28 16:54:41 -0700337 if (mDexoptCommands != null) {
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800338 throw new IllegalStateException("Should not be ota-dexopting when trying to move.");
Andreas Gampea8908752015-11-10 08:58:14 -0800339 }
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800340
Andreas Gampe3e1b6ad2017-04-10 15:48:50 -0700341 if (!mPackageManagerService.isUpgrade()) {
342 Slog.d(TAG, "No upgrade, skipping A/B artifacts check.");
343 return;
344 }
345
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800346 // Look into all packages.
347 Collection<PackageParser.Package> pkgs = mPackageManagerService.getPackages();
Andreas Gampe3e1b6ad2017-04-10 15:48:50 -0700348 int packagePaths = 0;
349 int pathsSuccessful = 0;
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800350 for (PackageParser.Package pkg : pkgs) {
351 if (pkg == null) {
352 continue;
353 }
354
355 // Does the package have code? If not, there won't be any artifacts.
356 if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
357 continue;
358 }
359 if (pkg.codePath == null) {
360 Slog.w(TAG, "Package " + pkg + " can be optimized but has null codePath");
361 continue;
362 }
363
364 // If the path is in /system or /vendor, ignore. It will have been ota-dexopted into
365 // /data/ota and moved into the dalvik-cache already.
366 if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")) {
367 continue;
368 }
369
370 final String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo);
371 final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
372 final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
373 for (String dexCodeInstructionSet : dexCodeInstructionSets) {
374 for (String path : paths) {
375 String oatDir = PackageDexOptimizer.getOatDir(new File(pkg.codePath)).
376 getAbsolutePath();
377
378 // TODO: Check first whether there is an artifact, to save the roundtrip time.
379
Andreas Gampe3e1b6ad2017-04-10 15:48:50 -0700380 packagePaths++;
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800381 try {
382 installer.moveAb(path, dexCodeInstructionSet, oatDir);
Andreas Gampe3e1b6ad2017-04-10 15:48:50 -0700383 pathsSuccessful++;
Andreas Gampeabcbe2f2016-02-26 11:25:36 -0800384 } catch (InstallerException e) {
385 }
386 }
Andreas Gampea8908752015-11-10 08:58:14 -0800387 }
388 }
Andreas Gampe3e1b6ad2017-04-10 15:48:50 -0700389 Slog.i(TAG, "Moved " + pathsSuccessful + "/" + packagePaths);
Andreas Gampea8908752015-11-10 08:58:14 -0800390 }
391
Andreas Gampe77cc8172016-09-13 11:12:13 -0700392 /**
393 * Initialize logging fields.
394 */
395 private void prepareMetricsLogging(int important, int others, long spaceBegin, long spaceBulk) {
396 availableSpaceBefore = spaceBegin;
397 availableSpaceAfterBulkDelete = spaceBulk;
398 availableSpaceAfterDexopt = 0;
399
400 importantPackageCount = important;
401 otherPackageCount = others;
402
403 dexoptCommandCountTotal = mDexoptCommands.size();
404 dexoptCommandCountExecuted = 0;
405
406 otaDexoptTimeStart = System.nanoTime();
407 }
408
409 private static int inMegabytes(long value) {
410 long in_mega_bytes = value / (1024 * 1024);
411 if (in_mega_bytes > Integer.MAX_VALUE) {
412 Log.w(TAG, "Recording " + in_mega_bytes + "MB of free space, overflowing range");
413 return Integer.MAX_VALUE;
414 }
415 return (int)in_mega_bytes;
416 }
417
418 private void performMetricsLogging() {
419 long finalTime = System.nanoTime();
420
421 MetricsLogger.histogram(mContext, "ota_dexopt_available_space_before_mb",
422 inMegabytes(availableSpaceBefore));
423 MetricsLogger.histogram(mContext, "ota_dexopt_available_space_after_bulk_delete_mb",
424 inMegabytes(availableSpaceAfterBulkDelete));
425 MetricsLogger.histogram(mContext, "ota_dexopt_available_space_after_dexopt_mb",
426 inMegabytes(availableSpaceAfterDexopt));
427
428 MetricsLogger.histogram(mContext, "ota_dexopt_num_important_packages",
429 importantPackageCount);
430 MetricsLogger.histogram(mContext, "ota_dexopt_num_other_packages", otherPackageCount);
431
432 MetricsLogger.histogram(mContext, "ota_dexopt_num_commands", dexoptCommandCountTotal);
433 MetricsLogger.histogram(mContext, "ota_dexopt_num_commands_executed",
434 dexoptCommandCountExecuted);
435
436 final int elapsedTimeSeconds =
437 (int) TimeUnit.NANOSECONDS.toSeconds(finalTime - otaDexoptTimeStart);
438 MetricsLogger.histogram(mContext, "ota_dexopt_time_s", elapsedTimeSeconds);
439 }
440
Andreas Gampea8908752015-11-10 08:58:14 -0800441 private static class OTADexoptPackageDexOptimizer extends
442 PackageDexOptimizer.ForcedUpdatePackageDexOptimizer {
Andreas Gampea8908752015-11-10 08:58:14 -0800443 public OTADexoptPackageDexOptimizer(Installer installer, Object installLock,
444 Context context) {
445 super(installer, installLock, context, "*otadexopt*");
446 }
Andreas Gampea8908752015-11-10 08:58:14 -0800447 }
Andreas Gampea8908752015-11-10 08:58:14 -0800448}