Skip to content

Commit 51a573c

Browse files
committed
Wait for ASECs to be scanned before proceeding
Move MountService up the list, then pause waiting for MountService to finish scanning ASECs before the services that require those packages to be ready. Additionally, don't automatically mark all ASEC apps as FLAG_EXTERNAL on reboot. This prevents AppWidgets and other things from being used with ASECs which are on internal storage. Bug: 6445613 Change-Id: I3e0b3e244fec966814d7a5ea93de5d337aea79bd
1 parent 468a2ac commit 51a573c

File tree

4 files changed

+89
-37
lines changed

4 files changed

+89
-37
lines changed

core/java/android/os/storage/IMountService.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1360,7 +1360,14 @@ public void unmountVolume(String mountPoint, boolean force, boolean removeEncryp
13601360
*/
13611361
public Parcelable[] getVolumeList() throws RemoteException;
13621362

1363-
public String getSecureContainerFilesystemPath(String id) throws RemoteException;
1363+
/**
1364+
* Gets the path on the filesystem for the ASEC container itself.
1365+
*
1366+
* @param cid ASEC container ID
1367+
* @return path to filesystem or {@code null} if it's not found
1368+
* @throws RemoteException
1369+
*/
1370+
public String getSecureContainerFilesystemPath(String cid) throws RemoteException;
13641371

13651372
/*
13661373
* Fix permissions in a container which has just been created and populated.

services/java/com/android/server/MountService.java

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@
7979
import java.util.List;
8080
import java.util.Map;
8181
import java.util.Map.Entry;
82+
import java.util.concurrent.CountDownLatch;
83+
import java.util.concurrent.TimeUnit;
8284
import java.util.Set;
8385

8486
import javax.crypto.SecretKey;
@@ -178,7 +180,8 @@ class VoldResponseCode {
178180
final private ArrayList<MountServiceBinderListener> mListeners =
179181
new ArrayList<MountServiceBinderListener>();
180182
private boolean mBooted = false;
181-
private boolean mReady = false;
183+
private CountDownLatch mConnectedSignal = new CountDownLatch(1);
184+
private CountDownLatch mAsecsScanned = new CountDownLatch(1);
182185
private boolean mSendUmsConnectedOnBoot = false;
183186
// true if we should fake MEDIA_MOUNTED state for external storage
184187
private boolean mEmulateExternalStorage = false;
@@ -446,15 +449,30 @@ public void handleMessage(Message msg) {
446449
final private HandlerThread mHandlerThread;
447450
final private Handler mHandler;
448451

452+
void waitForAsecScan() {
453+
waitForLatch(mAsecsScanned);
454+
}
455+
449456
private void waitForReady() {
450-
while (mReady == false) {
451-
for (int retries = 5; retries > 0; retries--) {
452-
if (mReady) {
457+
waitForLatch(mConnectedSignal);
458+
}
459+
460+
private void waitForLatch(CountDownLatch latch) {
461+
if (latch == null) {
462+
return;
463+
}
464+
465+
for (;;) {
466+
try {
467+
if (latch.await(5000, TimeUnit.MILLISECONDS)) {
453468
return;
469+
} else {
470+
Slog.w(TAG, "Thread " + Thread.currentThread().getName()
471+
+ " still waiting for MountService ready...");
454472
}
455-
SystemClock.sleep(1000);
473+
} catch (InterruptedException e) {
474+
Slog.w(TAG, "Interrupt while waiting for MountService to be ready.");
456475
}
457-
Slog.w(TAG, "Waiting too long for mReady!");
458476
}
459477
}
460478

@@ -627,7 +645,7 @@ public void onDaemonConnected() {
627645
* Since we'll be calling back into the NativeDaemonConnector,
628646
* we need to do our work in a new thread.
629647
*/
630-
new Thread() {
648+
new Thread("MountService#onDaemonConnected") {
631649
@Override
632650
public void run() {
633651
/**
@@ -668,14 +686,19 @@ public void run() {
668686
updatePublicVolumeState(mExternalStoragePath, Environment.MEDIA_REMOVED);
669687
}
670688

671-
// Let package manager load internal ASECs.
672-
mPms.updateExternalMediaStatus(true, false);
673-
674689
/*
675690
* Now that we've done our initialization, release
676691
* the hounds!
677692
*/
678-
mReady = true;
693+
mConnectedSignal.countDown();
694+
mConnectedSignal = null;
695+
696+
// Let package manager load internal ASECs.
697+
mPms.scanAvailableAsecs();
698+
699+
// Notify people waiting for ASECs to be scanned that it's done.
700+
mAsecsScanned.countDown();
701+
mAsecsScanned = null;
679702
}
680703
}.start();
681704
}
@@ -1158,23 +1181,13 @@ public MountService(Context context) {
11581181
// Add OBB Action Handler to MountService thread.
11591182
mObbActionHandler = new ObbActionHandler(mHandlerThread.getLooper());
11601183

1161-
/*
1162-
* Vold does not run in the simulator, so pretend the connector thread
1163-
* ran and did its thing.
1164-
*/
1165-
if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
1166-
mReady = true;
1167-
mUmsEnabling = true;
1168-
return;
1169-
}
1170-
11711184
/*
11721185
* Create the connection to vold with a maximum queue of twice the
11731186
* amount of containers we'd ever expect to have. This keeps an
11741187
* "asec list" from blocking a thread repeatedly.
11751188
*/
11761189
mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25);
1177-
mReady = false;
1190+
11781191
Thread thread = new Thread(mConnector, VOLD_TAG);
11791192
thread.start();
11801193

services/java/com/android/server/SystemServer.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,21 @@ public void run() {
320320
}
321321

322322
if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
323+
MountService mountService = null;
324+
if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) {
325+
try {
326+
/*
327+
* NotificationManagerService is dependant on MountService,
328+
* (for media / usb notifications) so we must start MountService first.
329+
*/
330+
Slog.i(TAG, "Mount Service");
331+
mountService = new MountService(context);
332+
ServiceManager.addService("mount", mountService);
333+
} catch (Throwable e) {
334+
reportWtf("starting Mount Service", e);
335+
}
336+
}
337+
323338
try {
324339
Slog.i(TAG, "LockSettingsService");
325340
lockSettings = new LockSettingsService(context);
@@ -441,17 +456,13 @@ public void run() {
441456
reportWtf("starting UpdateLockService", e);
442457
}
443458

444-
if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) {
445-
try {
446-
/*
447-
* NotificationManagerService is dependant on MountService,
448-
* (for media / usb notifications) so we must start MountService first.
449-
*/
450-
Slog.i(TAG, "Mount Service");
451-
ServiceManager.addService("mount", new MountService(context));
452-
} catch (Throwable e) {
453-
reportWtf("starting Mount Service", e);
454-
}
459+
/*
460+
* MountService has a few dependencies: Notification Manager and
461+
* AppWidget Provider. Make sure MountService is completely started
462+
* first before continuing.
463+
*/
464+
if (mountService != null) {
465+
mountService.waitForAsecScan();
455466
}
456467

457468
try {

services/java/com/android/server/pm/PackageManagerService.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,9 @@ public class PackageManagerService extends IPackageManager.Stub {
240240
// This is where all application persistent data goes for secondary users.
241241
final File mUserAppDataDir;
242242

243+
/** The location for ASEC container files on internal storage. */
244+
final String mAsecInternalPath;
245+
243246
// This is the object monitoring the framework dir.
244247
final FileObserver mFrameworkInstallObserver;
245248

@@ -907,6 +910,7 @@ public PackageManagerService(Context context, boolean factoryTest, boolean onlyC
907910

908911
File dataDir = Environment.getDataDirectory();
909912
mAppDataDir = new File(dataDir, "data");
913+
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
910914
mUserAppDataDir = new File(dataDir, "user");
911915
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
912916

@@ -1043,7 +1047,7 @@ public PackageManagerService(Context context, boolean factoryTest, boolean onlyC
10431047
scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
10441048
| PackageParser.PARSE_IS_SYSTEM_DIR,
10451049
scanMode | SCAN_NO_DEX, 0);
1046-
1050+
10471051
// Collect all system packages.
10481052
mSystemAppDir = new File(Environment.getRootDirectory(), "app");
10491053
mSystemInstallObserver = new AppDirObserver(
@@ -6479,6 +6483,11 @@ boolean doPostDeleteLI(boolean delete) {
64796483
}
64806484
}
64816485

6486+
private boolean isAsecExternal(String cid) {
6487+
final String asecPath = PackageHelper.getSdFilesystem(cid);
6488+
return !asecPath.startsWith(mAsecInternalPath);
6489+
}
6490+
64826491
/**
64836492
* Extract the MountService "container ID" from the full code path of an
64846493
* .apk.
@@ -6517,7 +6526,7 @@ class AsecInstallArgs extends InstallArgs {
65176526
}
65186527

65196528
AsecInstallArgs(String cid) {
6520-
super(null, null, 0, null, null);
6529+
super(null, null, isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0, null, null);
65216530
this.cid = cid;
65226531
setCachePath(PackageHelper.getSdDir(cid));
65236532
}
@@ -8659,6 +8668,14 @@ public void run() {
86598668
});
86608669
}
86618670

8671+
/**
8672+
* Called by MountService when the initial ASECs to scan are available.
8673+
* Should block until all the ASEC containers are finished being scanned.
8674+
*/
8675+
public void scanAvailableAsecs() {
8676+
updateExternalMediaStatusInner(true, false);
8677+
}
8678+
86628679
/*
86638680
* Collect information of applications on external media, map them against
86648681
* existing containers and update information based on current mount status.
@@ -8793,7 +8810,11 @@ private void loadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int
87938810
continue;
87948811
}
87958812
// Parse package
8796-
int parseFlags = PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
8813+
int parseFlags = mDefParseFlags;
8814+
if (args.isExternal()) {
8815+
parseFlags |= PackageParser.PARSE_ON_SDCARD;
8816+
}
8817+
87978818
doGc = true;
87988819
synchronized (mInstallLock) {
87998820
final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags,

0 commit comments

Comments
 (0)