Android 8.1 源碼_細節篇 -- 訪客模式 PC 端不顯示盤符的原因及解決方案

【現象】

這個問題主要是針對 MTK 平臺,整理信息的來源是自己在項目過程中遇到的一個 Bug ,Device 切換到訪客模式下,連接電腦 USB ,打開傳輸模式,卻發現在 PC 端無法顯示內部存儲的盤符,這是不合理的。

但其實原生代碼是不存在這個問題的,MTK 合入了一個 patch 導致出現這樣的問題。

MTK 導致問題的修改如下:MtpService.java

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        UserHandle user = new UserHandle(ActivityManager.getCurrentUser());
        synchronized (this) {
            if (sServerHolder != null) {
                Log.d(TAG, "MTP server is still running.");
            } else {
                mVolumeMap = new HashMap<>();
                mStorageMap = new HashMap<>();
                mStorageManager.registerListener(mStorageEventListener);
                mVolumes = StorageManager.getVolumeList(user.getIdentifier(), 0);
                for (StorageVolume volume : mVolumes) {
                    if (Environment.MEDIA_MOUNTED.equals(volume.getState())) {
                        volumeMountedLocked(volume.getPath());                 // 跟蹤 volumeMountedLocked() 函數
                    } else {
                        Log.e(TAG, "StorageVolume not mounted " + volume.getPath());
                    }
                }
            }
        }
    private void volumeMountedLocked(String path) {
        // For update storage
        /*
         * 問題就在這裏!
         * MTK 爲了修改一個 Bug:偶現顯示兩個內部存儲盤符,所以在這邊重新獲取一遍 StroageVolume ,但是沒有考慮多用戶模式
         *
         */
        StorageVolume[] volumes = mStorageManager.getVolumeList(new UserHandle();
        mVolumes = volumes;
        for (int i = 0; i < mVolumes.length; i++) {
            StorageVolume volume = mVolumes[i];
            if (volume.getPath().equals(path)) {
                mVolumeMap.put(path, volume);
                if (!mMtpDisabled) {
                    // In PTP mode we support only primary storage
                    if (volume.isPrimary() || !mPtpMode) {
                        addStorageLocked(volume);
                    }
                }
                break;
            }
        }
    }

【解決方案】

    private void volumeMountedLocked(String path) {
        // For update storage, support multi-user mode
        /*
         * 我們發現原生設計對多用戶讀取盤符是這麼操作的:mVolumes = StorageManager.getVolumeList(user.getIdentifier(), 0);
         * 我們直接進行如下修改:添加多用戶模式判斷邏輯
         *
         */
         
        StorageVolume[] volumes = mStorageManager.getVolumeList(
                                  new UserHandle(ActivityManager.getCurrentUser()).getIdentifier(), 0);    // 正解!
                                  
        mVolumes = volumes;
        for (int i = 0; i < mVolumes.length; i++) {
            StorageVolume volume = mVolumes[i];
            if (volume.getPath().equals(path)) {
                mVolumeMap.put(path, volume);
                if (!mMtpDisabled) {
                    // In PTP mode we support only primary storage
                    if (volume.isPrimary() || !mPtpMode) {
                        addStorageLocked(volume);
                    }
                }
                break;
            }
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章