Loading services/core/java/com/android/server/pm/MultiTaskDealer.java 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.android.server.pm; import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; import android.util.Log; public class MultiTaskDealer { public static final String TAG = "MultiTaskDealer"; public static final String PACKAGEMANAGER_SCANER = "packagescan"; private static final boolean DEBUG_TASK = false; private static HashMap<String, WeakReference<MultiTaskDealer>> map = new HashMap<String, WeakReference<MultiTaskDealer>>(); public static MultiTaskDealer getDealer(String name) { WeakReference<MultiTaskDealer> ref = map.get(name); MultiTaskDealer dealer = ref!=null?ref.get():null; return dealer; } public static MultiTaskDealer startDealer(String name,int taskCount) { MultiTaskDealer dealer = getDealer(name); if(dealer==null) { dealer = new MultiTaskDealer(name,taskCount); WeakReference<MultiTaskDealer> ref = new WeakReference<MultiTaskDealer>(dealer); map.put(name,ref); } return dealer; } public void startLock() { mLock.lock(); } public void endLock() { mLock.unlock(); } private ThreadPoolExecutor mExecutor; private int mTaskCount = 0; private boolean mNeedNotifyEnd = false; private Object mObjWaitAll = new Object(); private ReentrantLock mLock = new ReentrantLock(); public MultiTaskDealer(String name,int taskCount) { final String taskName = name; ThreadFactory factory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); public Thread newThread(final Runnable r) { if (DEBUG_TASK) Log.d(TAG, "create a new thread:" + taskName); return new Thread(r, taskName + "-" + mCount.getAndIncrement()); } }; mExecutor = new ThreadPoolExecutor(taskCount, taskCount, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), factory){ protected void afterExecute(Runnable r, Throwable t) { if(t!=null) { t.printStackTrace(); } MultiTaskDealer.this.TaskCompleteNotify(r); if (DEBUG_TASK) Log.d(TAG, "end task"); super.afterExecute(r,t); } protected void beforeExecute(Thread t, Runnable r) { if (DEBUG_TASK) Log.d(TAG, "start task"); super.beforeExecute(t,r); } }; } public void addTask(Runnable task) { synchronized (mObjWaitAll) { mTaskCount+=1; } mExecutor.execute(task); if (DEBUG_TASK) Log.d(TAG, "addTask"); } private void TaskCompleteNotify(Runnable task) { synchronized (mObjWaitAll) { mTaskCount-=1; if(mTaskCount<=0 && mNeedNotifyEnd) { if (DEBUG_TASK) Log.d(TAG, "complete notify"); mObjWaitAll.notify(); } } } public void waitAll() { if (DEBUG_TASK) Log.d(TAG, "start wait all"); synchronized (mObjWaitAll) { if(mTaskCount>0) { mNeedNotifyEnd = true; try { mObjWaitAll.wait(); } catch (Exception e) { } mNeedNotifyEnd = false; } if (DEBUG_TASK) Log.d(TAG, "wait finish"); return; } } } services/core/java/com/android/server/pm/PackageManagerService.java +43 −16 Original line number Diff line number Diff line /* * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); Loading Loading @@ -2276,9 +2279,9 @@ public class PackageManagerService extends IPackageManager.Stub { mSystemPermissions = systemConfig.getSystemPermissions(); mAvailableFeatures = systemConfig.getAvailableFeatures(); synchronized (mInstallLock) { // synchronized (mInstallLock) { // writer synchronized (mPackages) { // synchronized (mPackages) { mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/); mHandlerThread.start(); Loading Loading @@ -2834,8 +2837,8 @@ public class PackageManagerService extends IPackageManager.Stub { } mEphemeralApplicationRegistry = new EphemeralApplicationRegistry(this); } // synchronized (mPackages) } // synchronized (mInstallLock) //} // synchronized (mPackages) //} // synchronized (mInstallLock) // Now after opening every single application zip, make sure they // are all flushed. Not really needed, but keeps things nice and Loading Loading @@ -6702,6 +6705,13 @@ public class PackageManagerService extends IPackageManager.Stub { + " flags=0x" + Integer.toHexString(parseFlags)); } Log.d(TAG, "start scanDirLI:"+dir); // use multi thread to speed up scanning int iMultitaskNum = SystemProperties.getInt("persist.pm.multitask", 6); Log.d(TAG, "max thread:" + iMultitaskNum); final MultiTaskDealer dealer = (iMultitaskNum > 1) ? MultiTaskDealer.startDealer( MultiTaskDealer.PACKAGEMANAGER_SCANER, iMultitaskNum) : null; for (File file : files) { final boolean isPackage = (isApkFile(file) || file.isDirectory()) && !PackageInstallerService.isStageName(file.getName()); Loading @@ -6709,20 +6719,37 @@ public class PackageManagerService extends IPackageManager.Stub { // Ignore entries which are not packages continue; } final File ref_file = file; final int ref_parseFlags = parseFlags; final int ref_scanFlags = scanFlags; final long ref_currentTime = currentTime; Runnable scanTask = new Runnable() { public void run() { try { scanPackageTracedLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK, scanFlags, currentTime, null); scanPackageTracedLI(ref_file, ref_parseFlags | PackageParser.PARSE_MUST_BE_APK, ref_scanFlags, ref_currentTime, null); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage()); Slog.w(TAG, "Failed to parse " + ref_file + ": " + e.getMessage()); // Delete invalid userdata apps if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 && if ((ref_parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 && e.error == PackageManager.INSTALL_FAILED_INVALID_APK) { logCriticalInfo(Log.WARN, "Deleting invalid package at " + file); removeCodePathLI(file); logCriticalInfo(Log.WARN, "Deleting invalid package at " + ref_file); removeCodePathLI(ref_file); } } } }; if (dealer != null) dealer.addTask(scanTask); else scanTask.run(); } if (dealer != null) dealer.waitAll(); Log.d(TAG, "end scanDirLI:"+dir); } private static File getSettingsProblemFile() { Loading @@ -6736,7 +6763,7 @@ public class PackageManagerService extends IPackageManager.Stub { logCriticalInfo(priority, msg); } static void logCriticalInfo(int priority, String msg) { static synchronized void logCriticalInfo(int priority, String msg) { Slog.println(priority, TAG, msg); EventLogTags.writePmCriticalInfo(msg); try { Loading Loading
services/core/java/com/android/server/pm/MultiTaskDealer.java 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.android.server.pm; import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; import android.util.Log; public class MultiTaskDealer { public static final String TAG = "MultiTaskDealer"; public static final String PACKAGEMANAGER_SCANER = "packagescan"; private static final boolean DEBUG_TASK = false; private static HashMap<String, WeakReference<MultiTaskDealer>> map = new HashMap<String, WeakReference<MultiTaskDealer>>(); public static MultiTaskDealer getDealer(String name) { WeakReference<MultiTaskDealer> ref = map.get(name); MultiTaskDealer dealer = ref!=null?ref.get():null; return dealer; } public static MultiTaskDealer startDealer(String name,int taskCount) { MultiTaskDealer dealer = getDealer(name); if(dealer==null) { dealer = new MultiTaskDealer(name,taskCount); WeakReference<MultiTaskDealer> ref = new WeakReference<MultiTaskDealer>(dealer); map.put(name,ref); } return dealer; } public void startLock() { mLock.lock(); } public void endLock() { mLock.unlock(); } private ThreadPoolExecutor mExecutor; private int mTaskCount = 0; private boolean mNeedNotifyEnd = false; private Object mObjWaitAll = new Object(); private ReentrantLock mLock = new ReentrantLock(); public MultiTaskDealer(String name,int taskCount) { final String taskName = name; ThreadFactory factory = new ThreadFactory() { private final AtomicInteger mCount = new AtomicInteger(1); public Thread newThread(final Runnable r) { if (DEBUG_TASK) Log.d(TAG, "create a new thread:" + taskName); return new Thread(r, taskName + "-" + mCount.getAndIncrement()); } }; mExecutor = new ThreadPoolExecutor(taskCount, taskCount, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), factory){ protected void afterExecute(Runnable r, Throwable t) { if(t!=null) { t.printStackTrace(); } MultiTaskDealer.this.TaskCompleteNotify(r); if (DEBUG_TASK) Log.d(TAG, "end task"); super.afterExecute(r,t); } protected void beforeExecute(Thread t, Runnable r) { if (DEBUG_TASK) Log.d(TAG, "start task"); super.beforeExecute(t,r); } }; } public void addTask(Runnable task) { synchronized (mObjWaitAll) { mTaskCount+=1; } mExecutor.execute(task); if (DEBUG_TASK) Log.d(TAG, "addTask"); } private void TaskCompleteNotify(Runnable task) { synchronized (mObjWaitAll) { mTaskCount-=1; if(mTaskCount<=0 && mNeedNotifyEnd) { if (DEBUG_TASK) Log.d(TAG, "complete notify"); mObjWaitAll.notify(); } } } public void waitAll() { if (DEBUG_TASK) Log.d(TAG, "start wait all"); synchronized (mObjWaitAll) { if(mTaskCount>0) { mNeedNotifyEnd = true; try { mObjWaitAll.wait(); } catch (Exception e) { } mNeedNotifyEnd = false; } if (DEBUG_TASK) Log.d(TAG, "wait finish"); return; } } }
services/core/java/com/android/server/pm/PackageManagerService.java +43 −16 Original line number Diff line number Diff line /* * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); Loading Loading @@ -2276,9 +2279,9 @@ public class PackageManagerService extends IPackageManager.Stub { mSystemPermissions = systemConfig.getSystemPermissions(); mAvailableFeatures = systemConfig.getAvailableFeatures(); synchronized (mInstallLock) { // synchronized (mInstallLock) { // writer synchronized (mPackages) { // synchronized (mPackages) { mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/); mHandlerThread.start(); Loading Loading @@ -2834,8 +2837,8 @@ public class PackageManagerService extends IPackageManager.Stub { } mEphemeralApplicationRegistry = new EphemeralApplicationRegistry(this); } // synchronized (mPackages) } // synchronized (mInstallLock) //} // synchronized (mPackages) //} // synchronized (mInstallLock) // Now after opening every single application zip, make sure they // are all flushed. Not really needed, but keeps things nice and Loading Loading @@ -6702,6 +6705,13 @@ public class PackageManagerService extends IPackageManager.Stub { + " flags=0x" + Integer.toHexString(parseFlags)); } Log.d(TAG, "start scanDirLI:"+dir); // use multi thread to speed up scanning int iMultitaskNum = SystemProperties.getInt("persist.pm.multitask", 6); Log.d(TAG, "max thread:" + iMultitaskNum); final MultiTaskDealer dealer = (iMultitaskNum > 1) ? MultiTaskDealer.startDealer( MultiTaskDealer.PACKAGEMANAGER_SCANER, iMultitaskNum) : null; for (File file : files) { final boolean isPackage = (isApkFile(file) || file.isDirectory()) && !PackageInstallerService.isStageName(file.getName()); Loading @@ -6709,20 +6719,37 @@ public class PackageManagerService extends IPackageManager.Stub { // Ignore entries which are not packages continue; } final File ref_file = file; final int ref_parseFlags = parseFlags; final int ref_scanFlags = scanFlags; final long ref_currentTime = currentTime; Runnable scanTask = new Runnable() { public void run() { try { scanPackageTracedLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK, scanFlags, currentTime, null); scanPackageTracedLI(ref_file, ref_parseFlags | PackageParser.PARSE_MUST_BE_APK, ref_scanFlags, ref_currentTime, null); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage()); Slog.w(TAG, "Failed to parse " + ref_file + ": " + e.getMessage()); // Delete invalid userdata apps if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 && if ((ref_parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 && e.error == PackageManager.INSTALL_FAILED_INVALID_APK) { logCriticalInfo(Log.WARN, "Deleting invalid package at " + file); removeCodePathLI(file); logCriticalInfo(Log.WARN, "Deleting invalid package at " + ref_file); removeCodePathLI(ref_file); } } } }; if (dealer != null) dealer.addTask(scanTask); else scanTask.run(); } if (dealer != null) dealer.waitAll(); Log.d(TAG, "end scanDirLI:"+dir); } private static File getSettingsProblemFile() { Loading @@ -6736,7 +6763,7 @@ public class PackageManagerService extends IPackageManager.Stub { logCriticalInfo(priority, msg); } static void logCriticalInfo(int priority, String msg) { static synchronized void logCriticalInfo(int priority, String msg) { Slog.println(priority, TAG, msg); EventLogTags.writePmCriticalInfo(msg); try { Loading