状态栏不弹出“已连接USB”的解决办法

我们将Android5.1设备与PC(计算机/电脑)连接时,USB计算机连接方式有:USB 存储设备、媒体设备(MTP)、相机(PTP)、只充电。比如,我要使用 “USB存储设备” 这个USB连接方式:
状态栏不弹出“已连接USB”的解决办法 
那么,状态栏会弹出,“已连接USB” 的通知,并且你可以点击进去,打开USB存储设备:

状态栏不弹出“已连接USB”的解决办法 
状态栏不弹出“已连接USB”的解决办法 
将Android设备与PC连接设置为 “USB存储设备” 模式,就是将Android设备的内部存储器挂载到PC,当做U盘使用。


---------------------------------------------分割线--------------------------------------------

现在在我们的工业平板上遇到状态栏不弹出“已连接USB”,那么就不能打开USB存储设备:

状态栏不弹出“已连接USB”的解决办法 
虽然,不使用“USB存储设备” 模式作为Android设备与PC连接方式,“媒体设备(MTP)”模式也可以在Android与PC之间进行数据传输;但是,有时候应用程序需要使用“USB存储设备”这个模式,APP新建的文件/文件夹可以实时更新到PC,其他模式却不行。因此,需要“USB存储设备” 模式能够正常使用!

排查问题过程:
1. 查找关键字
通过查找关键字“已连接USB”,追踪到frameworks/base/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java文件。在updateUsbMassStorageNotification方法中,通过打印日志发现 available 和 isStorageCanShared 值为false,导致“已连接USB”通知弹不出来!
2. 文件对比
available 和 isStorageCanShared 值 与 volumes.getPath() 和 mStorageManager.getVolumeState(path); 相关,通过对比能够正常使用“USB存储设备”的StorageNotification.java文件,StorageNotification.java没有异常。

  1. /**
  2.      * Update the state of the USB mass storage notification
  3.      */
  4.     void updateUsbMassStorageNotification(boolean available) {

  5.         boolean isStorageCanShared = isAbleToShare();
  6.         Slog.d(TAG, "updateUsbMassStorageNotification - isStorageCanShared=" + isStorageCanShared + ",available=" + available);
  7.         if( !mStorageManager.isUsbMassStorageEnabled() || mLastState.equals(Environment.MEDIA_BAD_REMOVAL) ) {
  8.             /* Show "USB Connected" notification, if the system want it and there is more than one storage can be shared. */
  9.             /* Like SHARED SD, there is an internal storage, but that can not be shared. So don't show notification. */
  10.             if (available && isStorageCanShared) {   // available 与 isStorageCanShared 的值都为false
  11.                 Slog.d(TAG, "updateUsbMassStorageNotification - [true]");
  12.             Intent intent = new Intent();
  13.             intent.setClass(mContext, com.android.systemui.usb.UsbStorageActivity.class);
  14.             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

  15.             PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
  16.             setUsbStorageNotification(
  17.                     com.android.internal.R.string.usb_storage_notification_title,
  18.                     com.android.internal.R.string.usb_storage_notification_message,
  19.                     com.android.internal.R.drawable.stat_sys_data_usb,
  20.                     false, true, pi);
  21.             } else if(!available && !isStorageCanShared || !mUmsAvailable) {
  22.                 /* Cancel "USB Connected" notification, if the system want to cancel it and there is no storage can be shared. */
  23.                 /* Like SD hot-plug, remove the external SD card, but still one storage can be shared. So don't cancel the notification. */
  24.                 Slog.d(TAG, "updateUsbMassStorageNotification - [false]");
  25.                 setUsbStorageNotification(0, 0, 0, false, false, null);
  26.             } else {
  27.                 Slog.d(TAG, "updateUsbMassStorageNotification - Cannot as your wish!");
  28.                 /* When there is no partition to share (NOFS/BAD/...), invisible this notification */
  29.             Intent intent = new Intent();
  30.             intent.setClass(mContext, com.android.systemui.usb.UsbStorageActivity.class);

  31.             PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
  32.             setUsbStorageNotification(
  33.                     com.android.internal.R.string.usb_storage_stop_notification_title,
  34.                     com.android.internal.R.string.usb_storage_stop_notification_message,
  35.                     com.android.internal.R.drawable.stat_sys_warning, false, false, pi);
  36.             }
  37.             mLastConnected = available;
  38.         } else {
  39.             Slog.d(TAG, "updateUsbMassStorageNotification - UMS Enabled");
  40.         }
  41.     }
  1.     private void onUsbMassStorageConnectionChangedAsync(boolean connected) {
  2.         mUmsAvailable = connected;
  3.         /*
  4.          * Even though we may have a UMS host connected, we the SD card
  5.          * may not be in a state for export.
  6.          */
  7.         int allowedShareNum = 0;
  8.         String st = "";
  9.         String path = "";
  10.         StorageVolume[] volumes = mStorageManager.getVolumeList();

  11.         if (volumes != null) {
  12.             for (int i = 0; i < volumes.length; i++) {
  13.                 if (volumes[i].allowMassStorage() && !volumes[i].isEmulated()) {
  14.                     path = volumes[i].getPath();
  15.                     st = mStorageManager.getVolumeState(path);
  16.                     if (!(st.equals(Environment.MEDIA_REMOVED) || st.equals(Environment.MEDIA_CHECKING)|| st.equals(Environment.MEDIA_BAD_REMOVAL))) {
  17.                         /* got a truly sharable volume */
  18.                         allowedShareNum++;
  19.                     }
  20.                 }
  21.             }
  22.         }

  23.         if(connected && allowedShareNum == 0){
  24.             /* only changed connceted here */
  25.             Slog.d(TAG, "change connected from true -> false");
  26.             connected = false;
  27.         }

  28.         if (st != null) {
  29.             if (DEBUG) Log.i(TAG, String.format("UMS connection changed to %s (media state %s), (path %s)",
  30.                     connected, st, path));

  31.             Slog.d(TAG, "onUsbMassStorageConnectionChangedAsync - mLastState: " + mLastState + ", st: " + st + ", mLastConnected: " + mLastConnected+ ", connected: " + connected + ", path: " + path);
  32.             if (!connected) {
  33.                 mUsbNotifications.clear();
  34.                 updateUsbMassStorageNotification(connected);
  35.                 Slog.d(TAG, "onUsbMassStorageConnectionChangedAsync - Disconnect");
  36.             } else {
  37.                 String mCurrentFunctions = SystemProperties.get("sys.usb.config", "none");
  38.                 if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MASS_STORAGE)) {
  39.                     Slog.d(TAG, "onUsbMassStorageConnectionChangedAsync - Connect - UMS");
  40.                     if (mLastState.equals(st) && mLastConnected == connected && !mAlarmBootOff) {
  41.                         Slog.d(TAG, "onUsbMassStorageConnectionChangedAsync - Connect - UMS - Ignore");
  42.                         return;
  43.                     }
  44.                     updateUsbMassStorageNotification(connected);
  45.                 } else {
  46.                     Slog.d(TAG, "onUsbMassStorageConnectionChangedAsync - Connect - MTP");
  47.                     setUsbStorageNotification(0, 0, 0, false, false, null);
  48.                     mLastConnected = connected;
  49.                 }
  50.             }
  51.         }
  52.         mLastConnected = connected;
  53.         Slog.d(TAG, "onUsbMassStorageConnectionChangedAsync - mLastConnected: " + mLastConnected);
  54.     }

3. 检查配置文件
需要检查配置文件是ProjectConfig.mk、<project>_defconfig,通过与正常的配置文件进行对比检查,发现如下异常:
在ProjectConfig.mk文件中:
异常:MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT = yes
          MTK_OWNER_SDCARD_ONLY_SUPPORT = yes
          MTK_SHARED_SDCARD = yes
正常:MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT = no
          MTK_OWNER_SDCARD_ONLY_SUPPORT = no
          MTK_SHARED_SDCARD = no
在<project>_defconfig文件中:
异常:CONFIG_MTK_SHARED_SDCARD=y
          CONFIG_MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT=y
正常:# CONFIG_MTK_SHARED_SDCARD is not set 
          # CONFIG_MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT is not set

4. 问题处理
将上述ProjectConfig.mk、<project>_defconfig文件中出现的问题进行修改:在ProjectConfig.mk文件中:
          MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT = yes  --> MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT = no
          MTK_OWNER_SDCARD_ONLY_SUPPORT = yes                   --> MTK_OWNER_SDCARD_ONLY_SUPPORT = no
          MTK_SHARED_SDCARD = yes                                              --> MTK_SHARED_SDCARD = no
在<project>_defconfig文件中:
          CONFIG_MTK_SHARED_SDCARD=y                                            -->  # CONFIG_MTK_SHARED_SDCARD is not se
          CONFIG_MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT=y --> # CONFIG_MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT is not set

修改完成之后make clean,并且全部重新编译Android5.1源码,将编译好的源码,更新到我们的工业平板上,即可解决“USB存储设备” 模式不可用的问题。