Avoid deadlock by broadcasting outside lock.
We can end up in a rare tangled mess when sending broadcasts while
PackageManager is still trying to deal with scanAvailableAsecs().
Long-term solution is to make Environment.isExternalStorageEmulated()
more robust, but for now we just send these internal broadcasts
after we drop the MountService lock.
Bug: 22858403
Change-Id: I7b43865782f48a679882fd1675b7b961e1292df4
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 6ab2fd7..53e8d14 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -559,6 +559,7 @@
private static final int H_FSTRIM = 4;
private static final int H_VOLUME_MOUNT = 5;
private static final int H_VOLUME_BROADCAST = 6;
+ private static final int H_INTERNAL_BROADCAST = 7;
class MountServiceHandler extends Handler {
public MountServiceHandler(Looper looper) {
@@ -655,6 +656,13 @@
}
break;
}
+ case H_INTERNAL_BROADCAST: {
+ // Internal broadcasts aimed at system components, not for
+ // third-party apps.
+ final Intent intent = (Intent) msg.obj;
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+ android.Manifest.permission.WRITE_MEDIA_STORAGE);
+ }
}
}
}
@@ -1126,8 +1134,7 @@
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
intent.putExtra(DiskInfo.EXTRA_VOLUME_COUNT, volumeCount);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
- android.Manifest.permission.WRITE_MEDIA_STORAGE);
+ mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
final CountDownLatch latch = mDiskScanLatches.remove(disk.id);
if (latch != null) {
@@ -1239,8 +1246,7 @@
intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
- android.Manifest.permission.WRITE_MEDIA_STORAGE);
+ mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
}
final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);