Skip to content

Commit ae9d040

Browse files
krutonAndroid (Google) Code Review
authored andcommitted
Merge "Wait for ASECs to be scanned before proceeding" into jb-dev
2 parents 27cb3f8 + 51a573c commit ae9d040

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)