diff options
4 files changed, 89 insertions, 37 deletions
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index f4abda6..ab64866 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -1360,7 +1360,14 @@ public interface IMountService extends IInterface { */ public Parcelable[] getVolumeList() throws RemoteException; - public String getSecureContainerFilesystemPath(String id) throws RemoteException; + /** + * Gets the path on the filesystem for the ASEC container itself. + * + * @param cid ASEC container ID + * @return path to filesystem or {@code null} if it's not found + * @throws RemoteException + */ + public String getSecureContainerFilesystemPath(String cid) throws RemoteException; /* * Fix permissions in a container which has just been created and populated. diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index d6606f6..13ab586 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -79,6 +79,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.util.Set; import javax.crypto.SecretKey; @@ -178,7 +180,8 @@ class MountService extends IMountService.Stub final private ArrayList<MountServiceBinderListener> mListeners = new ArrayList<MountServiceBinderListener>(); private boolean mBooted = false; - private boolean mReady = false; + private CountDownLatch mConnectedSignal = new CountDownLatch(1); + private CountDownLatch mAsecsScanned = new CountDownLatch(1); private boolean mSendUmsConnectedOnBoot = false; // true if we should fake MEDIA_MOUNTED state for external storage private boolean mEmulateExternalStorage = false; @@ -446,15 +449,30 @@ class MountService extends IMountService.Stub final private HandlerThread mHandlerThread; final private Handler mHandler; + void waitForAsecScan() { + waitForLatch(mAsecsScanned); + } + private void waitForReady() { - while (mReady == false) { - for (int retries = 5; retries > 0; retries--) { - if (mReady) { + waitForLatch(mConnectedSignal); + } + + private void waitForLatch(CountDownLatch latch) { + if (latch == null) { + return; + } + + for (;;) { + try { + if (latch.await(5000, TimeUnit.MILLISECONDS)) { return; + } else { + Slog.w(TAG, "Thread " + Thread.currentThread().getName() + + " still waiting for MountService ready..."); } - SystemClock.sleep(1000); + } catch (InterruptedException e) { + Slog.w(TAG, "Interrupt while waiting for MountService to be ready."); } - Slog.w(TAG, "Waiting too long for mReady!"); } } @@ -627,7 +645,7 @@ class MountService extends IMountService.Stub * Since we'll be calling back into the NativeDaemonConnector, * we need to do our work in a new thread. */ - new Thread() { + new Thread("MountService#onDaemonConnected") { @Override public void run() { /** @@ -668,14 +686,19 @@ class MountService extends IMountService.Stub updatePublicVolumeState(mExternalStoragePath, Environment.MEDIA_REMOVED); } - // Let package manager load internal ASECs. - mPms.updateExternalMediaStatus(true, false); - /* * Now that we've done our initialization, release * the hounds! */ - mReady = true; + mConnectedSignal.countDown(); + mConnectedSignal = null; + + // Let package manager load internal ASECs. + mPms.scanAvailableAsecs(); + + // Notify people waiting for ASECs to be scanned that it's done. + mAsecsScanned.countDown(); + mAsecsScanned = null; } }.start(); } @@ -1159,22 +1182,12 @@ class MountService extends IMountService.Stub mObbActionHandler = new ObbActionHandler(mHandlerThread.getLooper()); /* - * Vold does not run in the simulator, so pretend the connector thread - * ran and did its thing. - */ - if ("simulator".equals(SystemProperties.get("ro.product.device"))) { - mReady = true; - mUmsEnabling = true; - return; - } - - /* * Create the connection to vold with a maximum queue of twice the * amount of containers we'd ever expect to have. This keeps an * "asec list" from blocking a thread repeatedly. */ mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25); - mReady = false; + Thread thread = new Thread(mConnector, VOLD_TAG); thread.start(); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index bb10358..eaecd4c 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -320,6 +320,21 @@ class ServerThread extends Thread { } if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { + MountService mountService = null; + if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) { + try { + /* + * NotificationManagerService is dependant on MountService, + * (for media / usb notifications) so we must start MountService first. + */ + Slog.i(TAG, "Mount Service"); + mountService = new MountService(context); + ServiceManager.addService("mount", mountService); + } catch (Throwable e) { + reportWtf("starting Mount Service", e); + } + } + try { Slog.i(TAG, "LockSettingsService"); lockSettings = new LockSettingsService(context); @@ -441,17 +456,13 @@ class ServerThread extends Thread { reportWtf("starting UpdateLockService", e); } - if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) { - try { - /* - * NotificationManagerService is dependant on MountService, - * (for media / usb notifications) so we must start MountService first. - */ - Slog.i(TAG, "Mount Service"); - ServiceManager.addService("mount", new MountService(context)); - } catch (Throwable e) { - reportWtf("starting Mount Service", e); - } + /* + * MountService has a few dependencies: Notification Manager and + * AppWidget Provider. Make sure MountService is completely started + * first before continuing. + */ + if (mountService != null) { + mountService.waitForAsecScan(); } try { diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 3936c18..77c3e78 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -240,6 +240,9 @@ public class PackageManagerService extends IPackageManager.Stub { // This is where all application persistent data goes for secondary users. final File mUserAppDataDir; + /** The location for ASEC container files on internal storage. */ + final String mAsecInternalPath; + // This is the object monitoring the framework dir. final FileObserver mFrameworkInstallObserver; @@ -907,6 +910,7 @@ public class PackageManagerService extends IPackageManager.Stub { File dataDir = Environment.getDataDirectory(); mAppDataDir = new File(dataDir, "data"); + mAsecInternalPath = new File(dataDir, "app-asec").getPath(); mUserAppDataDir = new File(dataDir, "user"); mDrmAppPrivateInstallDir = new File(dataDir, "app-private"); @@ -1043,7 +1047,7 @@ public class PackageManagerService extends IPackageManager.Stub { scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode | SCAN_NO_DEX, 0); - + // Collect all system packages. mSystemAppDir = new File(Environment.getRootDirectory(), "app"); mSystemInstallObserver = new AppDirObserver( @@ -6479,6 +6483,11 @@ public class PackageManagerService extends IPackageManager.Stub { } } + private boolean isAsecExternal(String cid) { + final String asecPath = PackageHelper.getSdFilesystem(cid); + return !asecPath.startsWith(mAsecInternalPath); + } + /** * Extract the MountService "container ID" from the full code path of an * .apk. @@ -6517,7 +6526,7 @@ public class PackageManagerService extends IPackageManager.Stub { } AsecInstallArgs(String cid) { - super(null, null, 0, null, null); + super(null, null, isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0, null, null); this.cid = cid; setCachePath(PackageHelper.getSdDir(cid)); } @@ -8659,6 +8668,14 @@ public class PackageManagerService extends IPackageManager.Stub { }); } + /** + * Called by MountService when the initial ASECs to scan are available. + * Should block until all the ASEC containers are finished being scanned. + */ + public void scanAvailableAsecs() { + updateExternalMediaStatusInner(true, false); + } + /* * Collect information of applications on external media, map them against * existing containers and update information based on current mount status. @@ -8793,7 +8810,11 @@ public class PackageManagerService extends IPackageManager.Stub { continue; } // Parse package - int parseFlags = PackageParser.PARSE_ON_SDCARD | mDefParseFlags; + int parseFlags = mDefParseFlags; + if (args.isExternal()) { + parseFlags |= PackageParser.PARSE_ON_SDCARD; + } + doGc = true; synchronized (mInstallLock) { final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags, |