Android sdcard分区加载过程
加载分区
MountService()
挂载服务
MountService启动
frameworks/base/services/java/com/android/server/MountService.java
1338 public MountService(Context context) {
1339 mContext = context;
1340
1341 synchronized (mVolumesLock) {
1342 readStorageListLocked();
1343 }
1344
1345 // XXX: This will go away soon infavor of IMountServiceObserver
1346 mPms = (PackageManagerService)ServiceManager.getService("package");
1347
1348 HandlerThread hthread = newHandlerThread(TAG);
1349 hthread.start();
1350 mHandler = newMountServiceHandler(hthread.getLooper());
1351
1352 // Watch for user changes
1353 final IntentFilter userFilter = new IntentFilter();
1354 userFilter.addAction(Intent.ACTION_USER_ADDED);
1355 userFilter.addAction(Intent.ACTION_USER_REMOVED);
1356 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
1357
1358 // Watch for USB changes on primaryvolume
1359 final StorageVolume primary =getPrimaryPhysicalVolume();
1360 if (primary != null &&primary.allowMassStorage()) {
1361 mContext.registerReceiver(
1362 mUsbReceiver, new IntentFilter(UsbManager.ACTION_USB_STATE),null, mHandler);
1363 }
1364
读取需要加载的分区
1187 private void readStorageListLocked() {
1188 mVolumes.clear();
1189 mVolumeStates.clear();
1190
1191 Resources resources = mContext.getResources();
1192
1193 int id = com.android.internal.R.xml.storage_list;
1194 XmlResourceParser parser =resources.getXml(id);
1195 AttributeSet attrs =Xml.asAttributeSet(parser);
1196
1197 try {
1198 XmlUtils.beginDocument(parser,TAG_STORAGE_LIST);
1199 while (true) {
1200 XmlUtils.nextElement(parser);
1201
1202 String element =parser.getName();
1203 if (element == null) break;
1204
1205 if(TAG_STORAGE.equals(element)) {
1206 TypedArray a =resources.obtainAttributes(attrs,
1207 com.android.internal.R.styleable.Storage);
1208
1209 String path = a.getString(
1210 com.android.internal.R.styleable.Storage_mountPoint);
1211 int descriptionId =a.getResourceId(
1212 com.android.internal.R.styleable.Storage_storageDescription, -1);
1213 CharSequence description =a.getText(
1214 com.android.internal.R.styleable.Storage_storageDescription);
1215 boolean primary =a.getBoolean(
1216 com.android.internal.R.styleable.Storage_primary,false);
1217 boolean removable =a.getBoolean(
1218 com.android.internal.R.styleable.Storage_removable, false);
1219 boolean emulated =a.getBoolean(
1220 com.android.internal.R.styleable.Storage_emulated, false);
1221 int mtpReserve = a.getInt(
1222 com.android.internal.R.styleable.Storage_mtpReserve, 0);
1223 boolean allowMassStorage = a.getBoolean(
1224 com.android.internal.R.styleable.Storage_allowMassStorage, false);
1225 // resource parser doesnot support longs, so XML value is in megabytes
1226 long maxFileSize = a.getInt(
1227 com.android.internal.R.styleable.Storage_maxFileSize, 0) * 1024L *1024L;
1228
1229 Slog.d(TAG, "gotstorage path: " + path + " description: " + description +
1230 " primary:" + primary + " removable: " + removable +
1231 " emulated:" + emulated + " mtpReserve:" + mtpReserve +
1232 "allowMassStorage: " + allowMassStorage +
1233 "maxFileSize: " + maxFileSize);
frameworks/base/core/res/res/xml/storage_list.xml
<StorageListxmlns:android="http://schemas.android.com/apk/res/android">
<storage android:mountPoint="/storage/sdcard0"
android:storageDescription="@string/storage_internal"
android:primary="true"
android:emulated="false"
android:removable="true"
android:allowMassStorage="true" />
<storage android:mountPoint="/storage/usbotg"
android:storageDescription="@string/storage_usb"
android:removable="true"
android:primary="false"/>
</StorageList>
处理系统消息,进行分区加载
406 class MountServiceHandlerextends Handler {
407 ArrayList<UnmountCallBack> mForceUnmounts = newArrayList<UnmountCallBack>();
408 boolean mUpdatingStatus = false;
409
410 MountServiceHandler(Looper l) {
411 super(l);
412 }
413
414 @Override
415 public void handleMessage(Message msg) {
416 switch (msg.what) {
417 case H_UNMOUNT_PM_UPDATE: {
418 if (DEBUG_UNMOUNT)Slog.i(TAG, "H_UNMOUNT_PM_UPDATE");
419 UnmountCallBack ucb =(UnmountCallBack) msg.obj;
420 mForceUnmounts.add(ucb);
421 if (DEBUG_UNMOUNT)Slog.i(TAG, " registered = " + mUpdatingStatus);
422 // Register only ifneeded.
423 if (!mUpdatingStatus) {
424 if (DEBUG_UNMOUNT)Slog.i(TAG, "Updating external media status on PackageManager");
425 mUpdatingStatus =true;
426 mPms.updateExternalMediaStatus(false, true);
427 }
428 break;
429 }
响应系统ready消息,进行分区挂载
489 case H_SYSTEM_READY: {
490 try {
491 handleSystemReady();
492 } catch (Exception ex) {
493 Slog.e(TAG,"Boot-time mount exception", ex);
494 }
495 break;
496 }
497 }
498 }
499 };
526 private void handleSystemReady() {
527 // Snapshot current volume states sinceit‘s not safe to call into vold
528 // while holding locks.
529 final HashMap<String, String> snapshot;
530 synchronized (mVolumesLock) {
531 snapshot = new HashMap<String, String>(mVolumeStates);
532 }
533
534 for (Map.Entry<String, String> entry : snapshot.entrySet()) {
535 final String path = entry.getKey();
536 final String state = entry.getValue();
537
538 if (state.equals(Environment.MEDIA_UNMOUNTED)) {
539 int rc = doMountVolume(path);
540 if (rc !=StorageResultCode.OperationSucceeded) {
541 Slog.e(TAG,String.format("Boot-time mount failed (%d)",
542 rc));
543 }
544 } else if (state.equals(Environment.MEDIA_SHARED)) {
545 /*
546 * Bootstrap UMS enabled statesince vold indicates
547 * the volume is shared(runtime restart while ums enabled)
548 */
549 notifyVolumeStateChange(null,path, VolumeState.NoMedia,
550 VolumeState.Shared);
551 }
552 }
553
554 // Push mounted state for all emulatedstorage
555 synchronized (mVolumesLock) {
556 for (StorageVolume volume : mVolumes) {
557 if (volume.isEmulated()) {
558 updatePublicVolumeState(volume, Environment.MEDIA_MOUNTED);
559 }
560 }
561 }
562
563 /*
564 * If UMS was connected on boot, send the connected event
565 * now that we‘re up.
566 */
567 if (mSendUmsConnectedOnBoot) {
568 sendUmsIntent(true);
569 mSendUmsConnectedOnBoot = false;
570 }
571 }
挂载分区
977 private int doMountVolume(String path) {
978 int rc = StorageResultCode.OperationSucceeded;
979
980 final StorageVolume volume;
981 synchronized (mVolumesLock) {
982 volume = mVolumesByPath.get(path);
983 }
984
985 if (DEBUG_EVENTS) Slog.i(TAG, "doMountVolume: Mouting " +path);
986 try {
987 mConnector.execute("volume", "mount", path);
988 } catch (NativeDaemonConnectorException e) {
989 /*
990 * Mount failed for some reason
991 */
992 String action = null;
993 int code = e.getCode();
994 if (code == VoldResponseCode.OpFailedNoMedia) {
995 /*
996 * Attempt to mount but nomedia inserted
997 */
998 rc = StorageResultCode.OperationFailedNoMedia;
999 } else if (code == VoldResponseCode.OpFailedMediaBlank) {
1000 if (DEBUG_EVENTS) Slog.i(TAG," updating volume state :: media nofs");
1379 mConnector= new
NativeDaemonConnector(this,"vold",MAX_CONTAINERS * 2, VOLD_TAG, 25);
frameworks/base/services/java/com/android/server/NativeDaemonConnector.java
通过socket向vold发送命令
Vold模块
/system/vold/main.cpp
46 int main() {
47
48 VolumeManager *vm;
49 CommandListener *cl;
50 NetlinkManager *nm;
51
52 SLOGI("Vold 2.1 (the revenge) firing up");
53
54 mkdir("/dev/block/vold", 0755);
55
56 /* For when cryptfs checks and mounts an encrypted filesystem */
57 klog_set_level(6);
58
59 /* Create our singleton managers */
60 if (!(vm = VolumeManager::Instance())) {
61 SLOGE("Unable to create VolumeManager");
62 exit(1);
63 };
64
65 if (!(nm = NetlinkManager::Instance())) {
66 SLOGE("Unable to create NetlinkManager");
67 exit(1);
68 };
69
70
71 cl = new CommandListener();
设置命令响应
72 vm->setBroadcaster((SocketListener *) cl);
73 nm->setBroadcaster((SocketListener *) cl);
/system/vold/CommandListener.cpp
121 intCommandListener::VolumeCmd::runCommand(SocketClient*cli,
122 int argc, char **argv) {
123 dumpArgs(argc, argv, -1);
124
125 if (argc < 2) {
126 cli->sendMsg(ResponseCode::CommandSyntaxError, "MissingArgument", false);
127 return 0;
128 }
129
130 VolumeManager *vm =VolumeManager::Instance();
131 int rc = 0;
132
133 if (!strcmp(argv[1], "list")) {
134 return vm->listVolumes(cli);
135 } else if (!strcmp(argv[1],"debug")) {
136 if (argc != 3 || (argc == 3 &&(strcmp(argv[2], "off") && strcmp(argv[2], "on")))){
137 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volumedebug <off/on>", false);
138 return 0;
139 }
140 vm->setDebug(!strcmp(argv[2],"on") ? true : false);
响应mount命令
141 } else if (!strcmp(argv[1], "mount")) {
142 if (argc != 3) {
143 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volumemount <path>", false);
144 return 0;
145 }
146 rc = vm->mountVolume(argv[2]);
147 } else if (!strcmp(argv[1],"unmount")) {
148 if (argc < 3 || argc > 4 ||
149 ((argc == 4 &&strcmp(argv[3], "force")) &&
150 (argc == 4 &&strcmp(argv[3], "force_and_revert")))) {
151 cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volumeunmount <path> [force|force_and_revert]", false);
152 return 0;
153 }
154
155 bool force = false;
156 bool revert = false;
157 if (argc >= 4 &&!strcmp(argv[3], "force")) {
158 force = true;
/system/vold/VolumeManager.cpp
1272 intVolumeManager::mountVolume(const char *label) {
1273 Volume *v = lookupVolume(label);
1274
1275 if (!v) {
1276 errno = ENOENT;
1277 return -1;
1278 }
1279
1280 return v->mountVol();
1281 }
/system/vold/Volume.cpp
315 intVolume::mountVol() {
442 if (!strcmp(getMountpoint(),"/storage/usbotg")){
443 if (Fat::doMount(devicePath,getMountpoint(), false, false, false,
444 AID_SYSTEM, AID_MEDIA_RW,0000, true)) {
445 SLOGE("%s failed to mountvia VFAT (%s)\n", devicePath, strerror(errno));
446 continue;
447 }
448 }else{
449 if (Fat::doMount(devicePath,getMountpoint(), false, false, false,
450 AID_MEDIA_RW,AID_MEDIA_RW, 0007, true)) {
451 SLOGE("%s failed to mountvia VFAT (%s)\n", devicePath, strerror(errno));
452 continue;
453 }
454 }
115 int Fat::doMount(const char *fsPath, const char*mountPoint,
116 bool ro, bool remount, boolexecutable,
117 int ownerUid, int ownerGid,int permMask, bool createLost) {
118 int rc;
119 unsigned long flags;
120 char mountData[255];
121
122 flags = MS_NODEV | MS_NOSUID | MS_DIRSYNC;
123
124 flags |= (executable ? 0 : MS_NOEXEC);
125 flags |= (ro ? MS_RDONLY : 0);
126 flags |= (remount ? MS_REMOUNT : 0);
127
128 /*
129 * Note: This is a temporary hack. If thesampling profiler is enabled,
130 * we make the SD card world-writable soany process can write snapshots.
131 *
132 * TODO: Remove this code once we have adrop box in system_server.
133 */
134 char value[PROPERTY_VALUE_MAX];
135 property_get("persist.sampling_profiler", value,"");
136 if (value[0] == ‘1‘) {
137 SLOGW("The SD card isworld-writable because the"
138 " ‘persist.sampling_profiler‘ systemproperty is set to ‘1‘.");
139 permMask = 0;
140 }
141
142 sprintf(mountData,
143 "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed",
144 ownerUid, ownerGid, permMask, permMask);
145
146 rc = mount(fsPath, mountPoint,"vfat", flags, mountData);
147
148 if (rc && errno == EROFS) {
149 SLOGE("%s appears to be a readonly filesystem - retrying mount RO", fsPath);
150 flags |= MS_RDONLY;
Linux api挂载分区
151 rc = mount(fsPath, mountPoint,"vfat", flags, mountData);
152 }
153
154 if (rc == 0 && createLost) {
155 char *lost_path;
156 asprintf(&lost_path,"%s/LOST.DIR", mountPoint);
157 if (access(lost_path, F_OK)) {
158 /*
159 * Create a LOST.DIR in the rootso we have somewhere to put
160 * lost cluster chains (fsck_msdosdoesn‘t currently do this)
161 */
162 if (mkdir(lost_path, 0755)) {