Loading services/core/java/com/android/server/pm/AbstractStatsBase.java 0 → 100644 +126 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm; import android.os.Environment; import android.os.SystemClock; import android.util.AtomicFile; import java.io.File; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; /** * A simple base class for statistics that need to be saved/restored from a dedicated file. This * class provides a base implementation that: * <ul> * <li>Provide an AtomicFile to the actual read/write code * <li>A background-thread write and a synchronous write * <li>Write-limiting for the background-thread (by default writes are at least 30 minutes apart) * <li>Can lock on the provided data object before writing * </ul> * For completion, a subclass needs to implement actual {@link #writeInternal(Object) writing} and * {@link #readInternal(Object) reading}. */ public abstract class AbstractStatsBase<T> { private static final int WRITE_INTERVAL_MS = (PackageManagerService.DEBUG_DEXOPT) ? 0 : 30*60*1000; private final Object mFileLock = new Object(); private final AtomicLong mLastTimeWritten = new AtomicLong(0); private final AtomicBoolean mBackgroundWriteRunning = new AtomicBoolean(false); private final String mFileName; private final String mBackgroundThreadName; private final boolean mLock; protected AbstractStatsBase(String fileName, String threadName, boolean lock) { mFileName = fileName; mBackgroundThreadName = threadName; mLock = lock; } protected AtomicFile getFile() { File dataDir = Environment.getDataDirectory(); File systemDir = new File(dataDir, "system"); File fname = new File(systemDir, mFileName); return new AtomicFile(fname); } void writeNow(final T data) { writeImpl(data); mLastTimeWritten.set(SystemClock.elapsedRealtime()); } boolean maybeWriteAsync(final T data) { if (SystemClock.elapsedRealtime() - mLastTimeWritten.get() < WRITE_INTERVAL_MS && !PackageManagerService.DEBUG_DEXOPT) { return false; } if (mBackgroundWriteRunning.compareAndSet(false, true)) { new Thread(mBackgroundThreadName) { @Override public void run() { try { writeImpl(data); mLastTimeWritten.set(SystemClock.elapsedRealtime()); } finally { mBackgroundWriteRunning.set(false); } } }.start(); return true; } return false; } private void writeImpl(T data) { if (mLock) { synchronized (data) { synchronized (mFileLock) { writeInternal(data); } } } else { synchronized (mFileLock) { writeInternal(data); } } } protected abstract void writeInternal(T data); void read(T data) { if (mLock) { synchronized (data) { synchronized (mFileLock) { readInternal(data); } } } else { synchronized (mFileLock) { readInternal(data); } } // We use the current time as last-written. read() is called on system server startup // (current situation), and we want to postpone I/O at boot. mLastTimeWritten.set(SystemClock.elapsedRealtime()); } protected abstract void readInternal(T data); } services/core/java/com/android/server/pm/CompilerStats.java 0 → 100644 +294 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm; import android.util.ArrayMap; import android.util.AtomicFile; import android.util.Log; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.IndentingPrintWriter; import libcore.io.IoUtils; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.util.HashMap; import java.util.Map; /** * A class that collects, serializes and deserializes compiler-related statistics on a * per-package per-code-path basis. * * Currently used to track compile times. */ class CompilerStats extends AbstractStatsBase<Void> { private final static String COMPILER_STATS_VERSION_HEADER = "PACKAGE_MANAGER__COMPILER_STATS__"; private final static int COMPILER_STATS_VERSION = 1; /** * Class to collect all stats pertaining to one package. */ static class PackageStats { private final String packageName; /** * This map stores compile-times for all code paths in the package. The value * is in milliseconds. */ private final Map<String, Long> compileTimePerCodePath; /** * @param packageName */ public PackageStats(String packageName) { this.packageName = packageName; // We expect at least one element in here, but let's make it minimal. compileTimePerCodePath = new ArrayMap<>(2); } public String getPackageName() { return packageName; } /** * Return the recorded compile time for a given code path. Returns * 0 if there is no recorded time. */ public long getCompileTime(String codePath) { String storagePath = getStoredPathFromCodePath(codePath); synchronized (compileTimePerCodePath) { Long l = compileTimePerCodePath.get(storagePath); if (l == null) { return 0; } return l; } } public void setCompileTime(String codePath, long compileTimeInMs) { String storagePath = getStoredPathFromCodePath(codePath); synchronized (compileTimePerCodePath) { if (compileTimeInMs <= 0) { compileTimePerCodePath.remove(storagePath); } else { compileTimePerCodePath.put(storagePath, compileTimeInMs); } } } private static String getStoredPathFromCodePath(String codePath) { int lastSlash = codePath.lastIndexOf(File.separatorChar); return codePath.substring(lastSlash + 1); } public void dump(IndentingPrintWriter ipw) { synchronized (compileTimePerCodePath) { if (compileTimePerCodePath.size() == 0) { ipw.println("(No recorded stats)"); } else { for (Map.Entry<String, Long> e : compileTimePerCodePath.entrySet()) { ipw.println(" " + e.getKey() + " - " + e.getValue()); } } } } } private final Map<String, PackageStats> packageStats; public CompilerStats() { super("package-cstats.list", "CompilerStats_DiskWriter", /* lock */ false); packageStats = new HashMap<>(); } public PackageStats getPackageStats(String packageName) { synchronized (packageStats) { return packageStats.get(packageName); } } public void setPackageStats(String packageName, PackageStats stats) { synchronized (packageStats) { packageStats.put(packageName, stats); } } public PackageStats createPackageStats(String packageName) { synchronized (packageStats) { PackageStats newStats = new PackageStats(packageName); packageStats.put(packageName, newStats); return newStats; } } public PackageStats getOrCreatePackageStats(String packageName) { synchronized (packageStats) { PackageStats existingStats = packageStats.get(packageName); if (existingStats != null) { return existingStats; } return createPackageStats(packageName); } } public void deletePackageStats(String packageName) { synchronized (packageStats) { packageStats.remove(packageName); } } // I/O // The encoding is simple: // // 1) The first line is a line consisting of the version header and the version number. // // 2) The rest of the file is package data. // 2.1) A package is started by any line not starting with "-"; // 2.2) Any line starting with "-" is code path data. The format is: // '-'{code-path}':'{compile-time} public void write(Writer out) { @SuppressWarnings("resource") FastPrintWriter fpw = new FastPrintWriter(out); fpw.print(COMPILER_STATS_VERSION_HEADER); fpw.println(COMPILER_STATS_VERSION); synchronized (packageStats) { for (PackageStats pkg : packageStats.values()) { synchronized (pkg.compileTimePerCodePath) { if (!pkg.compileTimePerCodePath.isEmpty()) { fpw.println(pkg.getPackageName()); for (Map.Entry<String, Long> e : pkg.compileTimePerCodePath.entrySet()) { fpw.println("-" + e.getKey() + ":" + e.getValue()); } } } } } fpw.flush(); } public boolean read(Reader r) { synchronized (packageStats) { // TODO: Could make this a final switch, then we wouldn't have to synchronize over // the whole reading. packageStats.clear(); try { BufferedReader in = new BufferedReader(r); // Read header, do version check. String versionLine = in.readLine(); if (versionLine == null) { throw new IllegalArgumentException("No version line found."); } else { if (!versionLine.startsWith(COMPILER_STATS_VERSION_HEADER)) { throw new IllegalArgumentException("Invalid version line: " + versionLine); } int version = Integer.parseInt( versionLine.substring(COMPILER_STATS_VERSION_HEADER.length())); if (version != COMPILER_STATS_VERSION) { // TODO: Upgrade older formats? For now, just reject and regenerate. throw new IllegalArgumentException("Unexpected version: " + version); } } // For simpler code, we ignore any data lines before the first package. We // collect it in a fake package. PackageStats currentPackage = new PackageStats("fake package"); String s = null; while ((s = in.readLine()) != null) { if (s.startsWith("-")) { int colonIndex = s.indexOf(':'); if (colonIndex == -1 || colonIndex == 1) { throw new IllegalArgumentException("Could not parse data " + s); } String codePath = s.substring(1, colonIndex); long time = Long.parseLong(s.substring(colonIndex + 1)); currentPackage.setCompileTime(codePath, time); } else { currentPackage = getOrCreatePackageStats(s); } } } catch (Exception e) { Log.e(PackageManagerService.TAG, "Error parsing compiler stats", e); return false; } return true; } } void writeNow() { writeNow(null); } boolean maybeWriteAsync() { return maybeWriteAsync(null); } @Override protected void writeInternal(Void data) { AtomicFile file = getFile(); FileOutputStream f = null; try { f = file.startWrite(); OutputStreamWriter osw = new OutputStreamWriter(f); osw.flush(); file.finishWrite(f); } catch (IOException e) { if (f != null) { file.failWrite(f); } Log.e(PackageManagerService.TAG, "Failed to write compiler stats", e); } } void read() { read((Void)null); } @Override protected void readInternal(Void data) { AtomicFile file = getFile(); BufferedReader in = null; try { in = new BufferedReader(new InputStreamReader(file.openRead())); read(in); } catch (FileNotFoundException expected) { } finally { IoUtils.closeQuietly(in); } } } services/core/java/com/android/server/pm/OtaDexoptService.java +4 −2 Original line number Original line Diff line number Diff line Loading @@ -225,7 +225,8 @@ public class OtaDexoptService extends IOtaDexopt.Stub { optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles, optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles, null /* ISAs */, false /* checkProfiles */, null /* ISAs */, false /* checkProfiles */, getCompilerFilterForReason(compilationReason)); getCompilerFilterForReason(compilationReason), null /* CompilerStats.PackageStats */); mCommandsForCurrentPackage = collectingConnection.commands; mCommandsForCurrentPackage = collectingConnection.commands; if (mCommandsForCurrentPackage.isEmpty()) { if (mCommandsForCurrentPackage.isEmpty()) { Loading Loading @@ -271,7 +272,8 @@ public class OtaDexoptService extends IOtaDexopt.Stub { mPackageManagerService.mInstaller, mPackageManagerService.mInstallLock, mContext); mPackageManagerService.mInstaller, mPackageManagerService.mInstallLock, mContext); optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles, null /* ISAs */, optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles, null /* ISAs */, false /* checkProfiles */, false /* checkProfiles */, getCompilerFilterForReason(PackageManagerService.REASON_AB_OTA)); getCompilerFilterForReason(PackageManagerService.REASON_AB_OTA), mPackageManagerService.getOrCreateCompilerPackageStats(nextPackage)); } } private void moveAbArtifacts(Installer installer) { private void moveAbArtifacts(Installer installer) { Loading services/core/java/com/android/server/pm/PackageDexOptimizer.java +12 −3 Original line number Original line Diff line number Diff line Loading @@ -90,7 +90,8 @@ class PackageDexOptimizer { * synchronized on {@link #mInstallLock}. * synchronized on {@link #mInstallLock}. */ */ int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries, int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries, String[] instructionSets, boolean checkProfiles, String targetCompilationFilter) { String[] instructionSets, boolean checkProfiles, String targetCompilationFilter, CompilerStats.PackageStats packageStats) { synchronized (mInstallLock) { synchronized (mInstallLock) { final boolean useLock = mSystemReady; final boolean useLock = mSystemReady; if (useLock) { if (useLock) { Loading @@ -99,7 +100,7 @@ class PackageDexOptimizer { } } try { try { return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles, return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles, targetCompilationFilter); targetCompilationFilter, packageStats); } finally { } finally { if (useLock) { if (useLock) { mDexoptWakeLock.release(); mDexoptWakeLock.release(); Loading Loading @@ -150,7 +151,8 @@ class PackageDexOptimizer { } } private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries, private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries, String[] targetInstructionSets, boolean checkProfiles, String targetCompilerFilter) { String[] targetInstructionSets, boolean checkProfiles, String targetCompilerFilter, CompilerStats.PackageStats packageStats) { final String[] instructionSets = targetInstructionSets != null ? final String[] instructionSets = targetInstructionSets != null ? targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); Loading Loading @@ -254,10 +256,17 @@ class PackageDexOptimizer { | DEXOPT_BOOTCOMPLETE); | DEXOPT_BOOTCOMPLETE); try { try { long startTime = System.currentTimeMillis(); mInstaller.dexopt(path, sharedGid, pkg.packageName, dexCodeInstructionSet, mInstaller.dexopt(path, sharedGid, pkg.packageName, dexCodeInstructionSet, dexoptNeeded, oatDir, dexFlags, targetCompilerFilter, pkg.volumeUuid, dexoptNeeded, oatDir, dexFlags, targetCompilerFilter, pkg.volumeUuid, sharedLibrariesPath); sharedLibrariesPath); performedDexOpt = true; performedDexOpt = true; if (packageStats != null) { long endTime = System.currentTimeMillis(); packageStats.setCompileTime(path, (int)(endTime - startTime)); } } catch (InstallerException e) { } catch (InstallerException e) { Slog.w(TAG, "Failed to dexopt", e); Slog.w(TAG, "Failed to dexopt", e); successfulDexOpt = false; successfulDexOpt = false; Loading services/core/java/com/android/server/pm/PackageManagerService.java +69 −210 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/core/java/com/android/server/pm/AbstractStatsBase.java 0 → 100644 +126 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm; import android.os.Environment; import android.os.SystemClock; import android.util.AtomicFile; import java.io.File; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; /** * A simple base class for statistics that need to be saved/restored from a dedicated file. This * class provides a base implementation that: * <ul> * <li>Provide an AtomicFile to the actual read/write code * <li>A background-thread write and a synchronous write * <li>Write-limiting for the background-thread (by default writes are at least 30 minutes apart) * <li>Can lock on the provided data object before writing * </ul> * For completion, a subclass needs to implement actual {@link #writeInternal(Object) writing} and * {@link #readInternal(Object) reading}. */ public abstract class AbstractStatsBase<T> { private static final int WRITE_INTERVAL_MS = (PackageManagerService.DEBUG_DEXOPT) ? 0 : 30*60*1000; private final Object mFileLock = new Object(); private final AtomicLong mLastTimeWritten = new AtomicLong(0); private final AtomicBoolean mBackgroundWriteRunning = new AtomicBoolean(false); private final String mFileName; private final String mBackgroundThreadName; private final boolean mLock; protected AbstractStatsBase(String fileName, String threadName, boolean lock) { mFileName = fileName; mBackgroundThreadName = threadName; mLock = lock; } protected AtomicFile getFile() { File dataDir = Environment.getDataDirectory(); File systemDir = new File(dataDir, "system"); File fname = new File(systemDir, mFileName); return new AtomicFile(fname); } void writeNow(final T data) { writeImpl(data); mLastTimeWritten.set(SystemClock.elapsedRealtime()); } boolean maybeWriteAsync(final T data) { if (SystemClock.elapsedRealtime() - mLastTimeWritten.get() < WRITE_INTERVAL_MS && !PackageManagerService.DEBUG_DEXOPT) { return false; } if (mBackgroundWriteRunning.compareAndSet(false, true)) { new Thread(mBackgroundThreadName) { @Override public void run() { try { writeImpl(data); mLastTimeWritten.set(SystemClock.elapsedRealtime()); } finally { mBackgroundWriteRunning.set(false); } } }.start(); return true; } return false; } private void writeImpl(T data) { if (mLock) { synchronized (data) { synchronized (mFileLock) { writeInternal(data); } } } else { synchronized (mFileLock) { writeInternal(data); } } } protected abstract void writeInternal(T data); void read(T data) { if (mLock) { synchronized (data) { synchronized (mFileLock) { readInternal(data); } } } else { synchronized (mFileLock) { readInternal(data); } } // We use the current time as last-written. read() is called on system server startup // (current situation), and we want to postpone I/O at boot. mLastTimeWritten.set(SystemClock.elapsedRealtime()); } protected abstract void readInternal(T data); }
services/core/java/com/android/server/pm/CompilerStats.java 0 → 100644 +294 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm; import android.util.ArrayMap; import android.util.AtomicFile; import android.util.Log; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.IndentingPrintWriter; import libcore.io.IoUtils; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.util.HashMap; import java.util.Map; /** * A class that collects, serializes and deserializes compiler-related statistics on a * per-package per-code-path basis. * * Currently used to track compile times. */ class CompilerStats extends AbstractStatsBase<Void> { private final static String COMPILER_STATS_VERSION_HEADER = "PACKAGE_MANAGER__COMPILER_STATS__"; private final static int COMPILER_STATS_VERSION = 1; /** * Class to collect all stats pertaining to one package. */ static class PackageStats { private final String packageName; /** * This map stores compile-times for all code paths in the package. The value * is in milliseconds. */ private final Map<String, Long> compileTimePerCodePath; /** * @param packageName */ public PackageStats(String packageName) { this.packageName = packageName; // We expect at least one element in here, but let's make it minimal. compileTimePerCodePath = new ArrayMap<>(2); } public String getPackageName() { return packageName; } /** * Return the recorded compile time for a given code path. Returns * 0 if there is no recorded time. */ public long getCompileTime(String codePath) { String storagePath = getStoredPathFromCodePath(codePath); synchronized (compileTimePerCodePath) { Long l = compileTimePerCodePath.get(storagePath); if (l == null) { return 0; } return l; } } public void setCompileTime(String codePath, long compileTimeInMs) { String storagePath = getStoredPathFromCodePath(codePath); synchronized (compileTimePerCodePath) { if (compileTimeInMs <= 0) { compileTimePerCodePath.remove(storagePath); } else { compileTimePerCodePath.put(storagePath, compileTimeInMs); } } } private static String getStoredPathFromCodePath(String codePath) { int lastSlash = codePath.lastIndexOf(File.separatorChar); return codePath.substring(lastSlash + 1); } public void dump(IndentingPrintWriter ipw) { synchronized (compileTimePerCodePath) { if (compileTimePerCodePath.size() == 0) { ipw.println("(No recorded stats)"); } else { for (Map.Entry<String, Long> e : compileTimePerCodePath.entrySet()) { ipw.println(" " + e.getKey() + " - " + e.getValue()); } } } } } private final Map<String, PackageStats> packageStats; public CompilerStats() { super("package-cstats.list", "CompilerStats_DiskWriter", /* lock */ false); packageStats = new HashMap<>(); } public PackageStats getPackageStats(String packageName) { synchronized (packageStats) { return packageStats.get(packageName); } } public void setPackageStats(String packageName, PackageStats stats) { synchronized (packageStats) { packageStats.put(packageName, stats); } } public PackageStats createPackageStats(String packageName) { synchronized (packageStats) { PackageStats newStats = new PackageStats(packageName); packageStats.put(packageName, newStats); return newStats; } } public PackageStats getOrCreatePackageStats(String packageName) { synchronized (packageStats) { PackageStats existingStats = packageStats.get(packageName); if (existingStats != null) { return existingStats; } return createPackageStats(packageName); } } public void deletePackageStats(String packageName) { synchronized (packageStats) { packageStats.remove(packageName); } } // I/O // The encoding is simple: // // 1) The first line is a line consisting of the version header and the version number. // // 2) The rest of the file is package data. // 2.1) A package is started by any line not starting with "-"; // 2.2) Any line starting with "-" is code path data. The format is: // '-'{code-path}':'{compile-time} public void write(Writer out) { @SuppressWarnings("resource") FastPrintWriter fpw = new FastPrintWriter(out); fpw.print(COMPILER_STATS_VERSION_HEADER); fpw.println(COMPILER_STATS_VERSION); synchronized (packageStats) { for (PackageStats pkg : packageStats.values()) { synchronized (pkg.compileTimePerCodePath) { if (!pkg.compileTimePerCodePath.isEmpty()) { fpw.println(pkg.getPackageName()); for (Map.Entry<String, Long> e : pkg.compileTimePerCodePath.entrySet()) { fpw.println("-" + e.getKey() + ":" + e.getValue()); } } } } } fpw.flush(); } public boolean read(Reader r) { synchronized (packageStats) { // TODO: Could make this a final switch, then we wouldn't have to synchronize over // the whole reading. packageStats.clear(); try { BufferedReader in = new BufferedReader(r); // Read header, do version check. String versionLine = in.readLine(); if (versionLine == null) { throw new IllegalArgumentException("No version line found."); } else { if (!versionLine.startsWith(COMPILER_STATS_VERSION_HEADER)) { throw new IllegalArgumentException("Invalid version line: " + versionLine); } int version = Integer.parseInt( versionLine.substring(COMPILER_STATS_VERSION_HEADER.length())); if (version != COMPILER_STATS_VERSION) { // TODO: Upgrade older formats? For now, just reject and regenerate. throw new IllegalArgumentException("Unexpected version: " + version); } } // For simpler code, we ignore any data lines before the first package. We // collect it in a fake package. PackageStats currentPackage = new PackageStats("fake package"); String s = null; while ((s = in.readLine()) != null) { if (s.startsWith("-")) { int colonIndex = s.indexOf(':'); if (colonIndex == -1 || colonIndex == 1) { throw new IllegalArgumentException("Could not parse data " + s); } String codePath = s.substring(1, colonIndex); long time = Long.parseLong(s.substring(colonIndex + 1)); currentPackage.setCompileTime(codePath, time); } else { currentPackage = getOrCreatePackageStats(s); } } } catch (Exception e) { Log.e(PackageManagerService.TAG, "Error parsing compiler stats", e); return false; } return true; } } void writeNow() { writeNow(null); } boolean maybeWriteAsync() { return maybeWriteAsync(null); } @Override protected void writeInternal(Void data) { AtomicFile file = getFile(); FileOutputStream f = null; try { f = file.startWrite(); OutputStreamWriter osw = new OutputStreamWriter(f); osw.flush(); file.finishWrite(f); } catch (IOException e) { if (f != null) { file.failWrite(f); } Log.e(PackageManagerService.TAG, "Failed to write compiler stats", e); } } void read() { read((Void)null); } @Override protected void readInternal(Void data) { AtomicFile file = getFile(); BufferedReader in = null; try { in = new BufferedReader(new InputStreamReader(file.openRead())); read(in); } catch (FileNotFoundException expected) { } finally { IoUtils.closeQuietly(in); } } }
services/core/java/com/android/server/pm/OtaDexoptService.java +4 −2 Original line number Original line Diff line number Diff line Loading @@ -225,7 +225,8 @@ public class OtaDexoptService extends IOtaDexopt.Stub { optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles, optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles, null /* ISAs */, false /* checkProfiles */, null /* ISAs */, false /* checkProfiles */, getCompilerFilterForReason(compilationReason)); getCompilerFilterForReason(compilationReason), null /* CompilerStats.PackageStats */); mCommandsForCurrentPackage = collectingConnection.commands; mCommandsForCurrentPackage = collectingConnection.commands; if (mCommandsForCurrentPackage.isEmpty()) { if (mCommandsForCurrentPackage.isEmpty()) { Loading Loading @@ -271,7 +272,8 @@ public class OtaDexoptService extends IOtaDexopt.Stub { mPackageManagerService.mInstaller, mPackageManagerService.mInstallLock, mContext); mPackageManagerService.mInstaller, mPackageManagerService.mInstallLock, mContext); optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles, null /* ISAs */, optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles, null /* ISAs */, false /* checkProfiles */, false /* checkProfiles */, getCompilerFilterForReason(PackageManagerService.REASON_AB_OTA)); getCompilerFilterForReason(PackageManagerService.REASON_AB_OTA), mPackageManagerService.getOrCreateCompilerPackageStats(nextPackage)); } } private void moveAbArtifacts(Installer installer) { private void moveAbArtifacts(Installer installer) { Loading
services/core/java/com/android/server/pm/PackageDexOptimizer.java +12 −3 Original line number Original line Diff line number Diff line Loading @@ -90,7 +90,8 @@ class PackageDexOptimizer { * synchronized on {@link #mInstallLock}. * synchronized on {@link #mInstallLock}. */ */ int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries, int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries, String[] instructionSets, boolean checkProfiles, String targetCompilationFilter) { String[] instructionSets, boolean checkProfiles, String targetCompilationFilter, CompilerStats.PackageStats packageStats) { synchronized (mInstallLock) { synchronized (mInstallLock) { final boolean useLock = mSystemReady; final boolean useLock = mSystemReady; if (useLock) { if (useLock) { Loading @@ -99,7 +100,7 @@ class PackageDexOptimizer { } } try { try { return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles, return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles, targetCompilationFilter); targetCompilationFilter, packageStats); } finally { } finally { if (useLock) { if (useLock) { mDexoptWakeLock.release(); mDexoptWakeLock.release(); Loading Loading @@ -150,7 +151,8 @@ class PackageDexOptimizer { } } private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries, private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries, String[] targetInstructionSets, boolean checkProfiles, String targetCompilerFilter) { String[] targetInstructionSets, boolean checkProfiles, String targetCompilerFilter, CompilerStats.PackageStats packageStats) { final String[] instructionSets = targetInstructionSets != null ? final String[] instructionSets = targetInstructionSets != null ? targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); Loading Loading @@ -254,10 +256,17 @@ class PackageDexOptimizer { | DEXOPT_BOOTCOMPLETE); | DEXOPT_BOOTCOMPLETE); try { try { long startTime = System.currentTimeMillis(); mInstaller.dexopt(path, sharedGid, pkg.packageName, dexCodeInstructionSet, mInstaller.dexopt(path, sharedGid, pkg.packageName, dexCodeInstructionSet, dexoptNeeded, oatDir, dexFlags, targetCompilerFilter, pkg.volumeUuid, dexoptNeeded, oatDir, dexFlags, targetCompilerFilter, pkg.volumeUuid, sharedLibrariesPath); sharedLibrariesPath); performedDexOpt = true; performedDexOpt = true; if (packageStats != null) { long endTime = System.currentTimeMillis(); packageStats.setCompileTime(path, (int)(endTime - startTime)); } } catch (InstallerException e) { } catch (InstallerException e) { Slog.w(TAG, "Failed to dexopt", e); Slog.w(TAG, "Failed to dexopt", e); successfulDexOpt = false; successfulDexOpt = false; Loading
services/core/java/com/android/server/pm/PackageManagerService.java +69 −210 File changed.Preview size limit exceeded, changes collapsed. Show changes