Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 568942ef authored by Brint E. Kriebel's avatar Brint E. Kriebel
Browse files

Revert "Revert "[1/2] Speed up booting on multicore devices.""

This reverts commit 28d838f2.

Conflicts:
	services/java/com/android/server/pm/Installer.java
	services/java/com/android/server/pm/PackageManagerService.java

Change-Id: Icabf7b21cc9c1123b8c7c2f718b962f8a6d60729
parent b6bb7059
Loading
Loading
Loading
Loading
+100 −14
Original line number Diff line number Diff line
@@ -19,12 +19,16 @@ package com.android.server.pm;
import android.content.pm.PackageStats;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Slog;
import android.util.SparseArray;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;

public final class Installer {
    private static final String TAG = "Installer";
@@ -41,6 +45,16 @@ public final class Installer {

    int buflen = 0;

    final SparseArray<String> mResponses = new SparseArray<String>();
    final ArrayList<Integer> mPendingRequests = new ArrayList<Integer>();
    int mLastTransactionId = 0;
    final Object mTransactionIdLock = new Object();
    int id;

    public Installer() {
        mPollerThread.start();
    }

    private boolean connect() {
        if (mSocket != null) {
            return true;
@@ -83,12 +97,24 @@ public final class Installer {
        mSocket = null;
        mIn = null;
        mOut = null;

        synchronized (mPendingRequests) {
            mPendingRequests.clear();
            checkPoller();
        }
        synchronized (mResponses) {
            mResponses.notifyAll();
        }
    }

    private boolean readBytes(byte buffer[], int len) {
    private synchronized boolean readBytes(byte buffer[], int len) {
        int off = 0, count;
        if (len < 0)
        try {
            if (len < 0 || mIn.available() < len)
                return false;
        } catch (IOException e) {
            return false;
        }
        while (off != len) {
            try {
                count = mIn.read(buffer, off, len - off);
@@ -114,9 +140,12 @@ public final class Installer {
    private boolean readReply() {
        int len;
        buflen = 0;
        if (!readBytes(buf, 2))
        if (!readBytes(buf, 6))
            return false;
        len = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8);
        id = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8)
                | ((((int) buf[2]) & 0xff) << 16) | ((((int) buf[3]) & 0xff) << 24);

        len = (((int) buf[4]) & 0xff) | ((((int) buf[5]) & 0xff) << 8);
        if ((len < 1) || (len > 1024)) {
            Slog.e(TAG, "invalid reply length (" + len + ")");
            disconnect();
@@ -128,11 +157,24 @@ public final class Installer {
        return true;
    }

    private boolean writeCommand(String _cmd) {
    private synchronized boolean writeCommand(String _cmd, int id) {
        byte[] cmd = _cmd.getBytes();
        int len = cmd.length;
        if ((len < 1) || (len > 1024))
            return false;
        buf[0] = (byte) (id & 0xff);
        buf[1] = (byte) ((id >> 8) & 0xff);
        buf[2] = (byte) ((id >> 16) & 0xff);
        buf[3] = (byte) ((id >> 24) & 0xff);

        try {
            mOut.write(buf, 0, 4);
        } catch (IOException e) {
            Slog.e(TAG, "write error");
            disconnect();
            return false;
        }

        buf[0] = (byte) (len & 0xff);
        buf[1] = (byte) ((len >> 8) & 0xff);
        try {
@@ -209,21 +251,65 @@ public final class Installer {
            mResponses.remove(transactionId);
        }
        if (LOCAL_DEBUG) {
            Slog.i(TAG, "send: '" + cmd + "'");
            Slog.i(TAG, "recv: ["+transactionId+"]'" + s + "'");
        }
        if (readReply()) {
            String s = new String(buf, 0, buflen);
        return s == null ? "-1" : s;
    }

    private void checkPoller() {
        synchronized (mPendingRequests) {
            if (LOCAL_DEBUG) {
                Slog.i(TAG, "recv: '" + s + "'");
                Slog.v(TAG, "checkPoller handler = " + mHandler +
                        " empty=" + mPendingRequests.isEmpty());
            }
            return s;
            if (mHandler != null) {
                if (mPendingRequests.isEmpty()) {
                    needPolling = false;
                    mHandler.removeCallbacks(mPollRunnable);
                } else {
                    needPolling = true;
                    mHandler.post(mPollRunnable);
                }
            }
        }
    }

    Handler mHandler;
    Thread mPollerThread = new Thread(new Runnable() {
        @Override
        public void run() {
            Looper.prepare();
            mHandler = new Handler();
            checkPoller();
            Looper.loop();
        }
    });

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        mHandler.getLooper().quit();
    }

    boolean needPolling = false;
    Runnable mPollRunnable = new Runnable() {
        @Override
        public void run() {
            synchronized (mResponses) {
                while (readReply()) {
                    String s = new String(buf, 0, buflen);
                    if (LOCAL_DEBUG) {
                Slog.i(TAG, "fail");
                        Slog.v(TAG, "put: id = " + id + " s = " + s);
                    }
            return "-1";
                    mResponses.put(id, s);
                    mResponses.notifyAll();
                }
            }
            if (needPolling) {
                mHandler.postDelayed(this, 10);
            }
        }
    };

    private int execute(String cmd) {
        String res = transaction(cmd);
+293 −209
Original line number Diff line number Diff line
@@ -173,6 +173,12 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import libcore.io.ErrnoException;
import libcore.io.IoUtils;
@@ -477,6 +483,8 @@ public class PackageManagerService extends IPackageManager.Stub {
    /** Token for keys in mPendingVerification. */
    private int mPendingVerificationToken = 0;
    private static final int sNThreads = Runtime.getRuntime().availableProcessors() + 1;
    boolean mSystemReady;
    boolean mSafeMode;
    boolean mHasSystemUidErrors;
@@ -1198,8 +1206,11 @@ public class PackageManagerService extends IPackageManager.Stub {
        Display d = wm.getDefaultDisplay();
        d.getMetrics(mMetrics);
        synchronized (mInstallLock) {
        File frameworkDir;
        // writer
        int scanMode;
        long startTime;
        synchronized (mInstallLock) {
            synchronized (mPackages) {
                mHandlerThread.start();
                mHandler = new PackageHandler(mHandlerThread.getLooper());
@@ -1233,14 +1244,14 @@ public class PackageManagerService extends IPackageManager.Stub {
                            customResolverActivity);
                }
            long startTime = SystemClock.uptimeMillis();
                startTime = SystemClock.uptimeMillis();
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                        startTime);
                // Set flag to monitor and not change apk file paths when
                // scanning install directories.
            int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
                scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
                if (mNoDexOpt) {
                    Slog.w(TAG, "Running ENG build: no pre-dexopt!");
                    scanMode |= SCAN_NO_DEX;
@@ -1263,23 +1274,29 @@ public class PackageManagerService extends IPackageManager.Stub {
                    Slog.w(TAG, "No BOOTCLASSPATH found!");
                }
            boolean didDexOpt = false;
                final boolean[] didDexOpt = {false};
                /**
                 * Ensure all external libraries have had dexopt run on them.
                 */
                if (mSharedLibraries.size() > 0) {
                    Iterator<SharedLibraryEntry> libs = mSharedLibraries.values().iterator();
                    ExecutorService executorService = Executors.newFixedThreadPool(sNThreads);
                    while (libs.hasNext()) {
                    String lib = libs.next().path;
                        final String lib = libs.next().path;
                        if (lib == null) {
                            continue;
                        }
                        try {
                            if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
                                executorService.submit(new Runnable() {
                                    @Override
                                    public void run() {
                                        alreadyDexOpted.add(lib);
                                        mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
                            didDexOpt = true;
                                        didDexOpt[0] = true;
                                    }
                                });
                            }
                        } catch (FileNotFoundException e) {
                            Slog.w(TAG, "Library not found: " + lib);
@@ -1288,9 +1305,15 @@ public class PackageManagerService extends IPackageManager.Stub {
                                    + e.getMessage());
                        }
                    }
                    executorService.shutdown();
                    try {
                        executorService.awaitTermination(1, TimeUnit.DAYS);
                    } catch (InterruptedException e) {
                        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                    }
                }
            File frameworkDir = new File(Environment.getRootDirectory(), "framework");
                frameworkDir = new File(Environment.getRootDirectory(), "framework");
                // Gross hack for now: we know this file doesn't contain any
                // code, so don't dexopt it to avoid the resulting log spew.
@@ -1308,9 +1331,10 @@ public class PackageManagerService extends IPackageManager.Stub {
                 */
                String[] frameworkFiles = frameworkDir.list();
                if (frameworkFiles != null) {
                    ExecutorService executorService = Executors.newFixedThreadPool(sNThreads);
                    for (int i = 0; i < frameworkFiles.length; i++) {
                        File libPath = new File(frameworkDir, frameworkFiles[i]);
                    String path = libPath.getPath();
                        final String path = libPath.getPath();
                        // Skip the file if we alrady did it.
                        if (alreadyDexOpted.contains(path)) {
                            continue;
@@ -1321,8 +1345,13 @@ public class PackageManagerService extends IPackageManager.Stub {
                        }
                        try {
                            if (dalvik.system.DexFile.isDexOptNeeded(path)) {
                                executorService.submit(new Runnable() {
                                    @Override
                                    public void run() {
                                        mInstaller.dexopt(path, Process.SYSTEM_UID, true);
                            didDexOpt = true;
                                        didDexOpt[0] = true;
                                    }
                                });
                            }
                        } catch (FileNotFoundException e) {
                            Slog.w(TAG, "Jar not found: " + path);
@@ -1330,9 +1359,15 @@ public class PackageManagerService extends IPackageManager.Stub {
                            Slog.w(TAG, "Exception reading jar: " + path, e);
                        }
                    }
                    executorService.shutdown();
                    try {
                        executorService.awaitTermination(1, TimeUnit.DAYS);
                    } catch (InterruptedException e) {
                        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                    }
                }
            if (didDexOpt) {
                if (didDexOpt[0]) {
                    File dalvikCacheDir = new File(dataDir, "dalvik-cache");
                    // If we had to do a dexopt of one of the previous
@@ -1352,6 +1387,8 @@ public class PackageManagerService extends IPackageManager.Stub {
                        }
                    }
                }
            }
        }
        // Collect vendor overlay packages.
        // (Do this before scanning any apps.)
@@ -1361,14 +1398,14 @@ public class PackageManagerService extends IPackageManager.Stub {
        mVendorOverlayInstallObserver = new AppDirObserver(
            vendorOverlayDir.getPath(), OBSERVER_EVENTS, true, false);
        mVendorOverlayInstallObserver.startWatching();
            scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
        scanDir(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
                | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode | SCAN_TRUSTED_OVERLAY, 0);
        // Find base frameworks (resource packages without code).
        mFrameworkInstallObserver = new AppDirObserver(
                frameworkDir.getPath(), OBSERVER_EVENTS, true, false);
        mFrameworkInstallObserver.startWatching();
            scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
        scanDir(frameworkDir, PackageParser.PARSE_IS_SYSTEM
                | PackageParser.PARSE_IS_SYSTEM_DIR
                | PackageParser.PARSE_IS_PRIVILEGED,
                scanMode | SCAN_NO_DEX, 0);
@@ -1378,7 +1415,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        mPrivilegedInstallObserver = new AppDirObserver(
                privilegedAppDir.getPath(), OBSERVER_EVENTS, true, true);
        mPrivilegedInstallObserver.startWatching();
                scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
        scanDir(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
                | PackageParser.PARSE_IS_SYSTEM_DIR
                | PackageParser.PARSE_IS_PRIVILEGED, scanMode, 0);
@@ -1387,7 +1424,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        mSystemInstallObserver = new AppDirObserver(
                systemAppDir.getPath(), OBSERVER_EVENTS, true, false);
        mSystemInstallObserver.startWatching();
            scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
        scanDir(systemAppDir, PackageParser.PARSE_IS_SYSTEM
                | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
        // Collect all vendor packages.
@@ -1395,14 +1432,16 @@ public class PackageManagerService extends IPackageManager.Stub {
        mVendorInstallObserver = new AppDirObserver(
                vendorAppDir.getPath(), OBSERVER_EVENTS, true, false);
        mVendorInstallObserver.startWatching();
            scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
        scanDir(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
                | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
        final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
        synchronized (mInstallLock) {
        synchronized (mPackages) {
            if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
            mInstaller.moveFiles();
            // Prune any system packages that no longer exist.
            final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
            if (!mOnlyCore) {
                Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
                while (psit.hasNext()) {
@@ -1464,6 +1503,8 @@ public class PackageManagerService extends IPackageManager.Stub {
            // Remove any shared userIDs that have no associated packages
            mSettings.pruneSharedUsersLPw();
        }
        }
        if (!mOnlyCore) {
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
@@ -1471,14 +1512,15 @@ public class PackageManagerService extends IPackageManager.Stub {
            mAppInstallObserver = new AppDirObserver(
                    mAppInstallDir.getPath(), OBSERVER_EVENTS, false, false);
            mAppInstallObserver.startWatching();
                scanDirLI(mAppInstallDir, 0, scanMode | SCAN_TRUSTED_OVERLAY, 0);
            scanDir(mAppInstallDir, 0, scanMode | SCAN_TRUSTED_OVERLAY, 0);
            mDrmAppInstallObserver = new AppDirObserver(
                    mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false, false);
            mDrmAppInstallObserver.startWatching();
                scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
            scanDir(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
                    scanMode | SCAN_TRUSTED_OVERLAY, 0);
            synchronized (mPackages) {
                /**
                 * Remove disable package settings for any updated system
                 * apps that were removed via an OTA. If they're not a
@@ -1506,11 +1548,15 @@ public class PackageManagerService extends IPackageManager.Stub {
                    }
                    reportSettingsProblem(Log.WARN, msg);
                }
            }
        } else {
            mAppInstallObserver = null;
            mDrmAppInstallObserver = null;
        }
        synchronized (mInstallLock) {
        synchronized (mPackages) {
            // Now that we know all of the shared libraries, update all clients to have
            // the correct library paths.
            updateAllSharedLibrariesLPw();
@@ -3653,13 +3699,15 @@ public class PackageManagerService extends IPackageManager.Stub {
        return true;
    }
    private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
    private void scanDir(File dir, final int flags, final int scanMode, final long currentTime) {
        String[] files = dir.list();
        if (files == null) {
            Log.d(TAG, "No files in app dir " + dir);
            return;
        }
        ExecutorService executorService = Executors.newFixedThreadPool(sNThreads);
        if (DEBUG_PACKAGE_SCANNING) {
            Log.d(TAG, "Scanning app dir " + dir + " scanMode=" + scanMode
                    + " flags=0x" + Integer.toHexString(flags));
@@ -3667,11 +3715,14 @@ public class PackageManagerService extends IPackageManager.Stub {
        int i;
        for (i=0; i<files.length; i++) {
            File file = new File(dir, files[i]);
            final File file = new File(dir, files[i]);
            if (!isPackageFilename(files[i])) {
                // Ignore entries which are not apk's
                continue;
            }
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    PackageParser.Package pkg = scanPackageLI(file,
                            flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
                    // Don't mess around with apps in system partition.
@@ -3682,6 +3733,14 @@ public class PackageManagerService extends IPackageManager.Stub {
                        file.delete();
                    }
                }
            });
        }
        executorService.shutdown();
        try {
            executorService.awaitTermination(1, TimeUnit.DAYS);
        } catch (InterruptedException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }
    private static File getSettingsProblemFile() {
@@ -4010,26 +4069,51 @@ public class PackageManagerService extends IPackageManager.Stub {
            mDeferredDexOpt = null;
        }
        if (pkgs != null) {
            int i = 0;
            final int[] i = {0};
            final int pkgsSize = pkgs.size();
            ExecutorService executorService = Executors.newFixedThreadPool(sNThreads);
            final long start = System.currentTimeMillis();
            for (PackageParser.Package pkg : pkgs) {
                if (!isFirstBoot()) {
                    i++;
                    try {
                        ActivityManagerNative.getDefault().showBootMessage(
                                mContext.getResources().getString(
                                        com.android.internal.R.string.android_upgrading_apk,
                                        i, pkgs.size()), true);
                    } catch (RemoteException e) {
                    }
                }
                PackageParser.Package p = pkg;
                final PackageParser.Package p = pkg;
                synchronized (mInstallLock) {
                    if (!p.mDidDexOpt) {
                        executorService.submit(new Runnable() {
                            @Override
                            public void run() {
                                if (!isFirstBoot()) {
                                    i[0]++;
                                    postBootMessageUpdate(i[0], pkgsSize);
                                }
                                performDexOptLI(p, false, false, true);
                            }
                        });
                    } else {
                        if (!isFirstBoot()) {
                            i[0]++;
                            postBootMessageUpdate(i[0], pkgsSize);
                        }
                    }
                }
            }
            executorService.shutdown();
            try {
                executorService.awaitTermination(1, TimeUnit.DAYS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            final long time = System.currentTimeMillis() - start;
            Slog.v("MIK", "Finished in "+time+" ms");
        }
    }
    private void postBootMessageUpdate(int n, int total) {
        try {
            ActivityManagerNative.getDefault().showBootMessage(
                    mContext.getResources().getString(
                            com.android.internal.R.string.android_upgrading_apk,
                            n, total), true);
        } catch (RemoteException e) {
        }
    }
    public boolean performDexOpt(String packageName) {