首页 > 代码库 > Android sdcard分区加载过程

Android sdcard分区加载过程

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)) {

 

 

 

 

Android sdcard分区加载过程