Tuesday, March 12, 2019

Android开发笔记-ch3.4.19 USB and Storage Access


3.4.19 USB and Storage Access

Refer to USB host, there are two way to deal with USB device: To have your application discover a particular USB device, you can specify an intent filter to filter for the android.hardware.usb.action.USB_DEVICE_ATTACHED intent. Along with this intent filter, you need to specify a resource file that specifies properties of the USB device, such as product and vendor ID. When users connect a device that matches your device filter, the system presents them with a dialog that asks if they want to start your application. If your application is interested in inspecting all of the USB devices currently connected while your application is running, it can enumerate devices on the bus. Use the getDeviceList() method to get a hash map of all the USB devices that are connected. The hash map is keyed by the USB device's name if you want to obtain a device from the map. Note, for the BroadcastReceiver registered for the intent, it would still get invoked even the permission was granted already (therefore no pop up dialog for requesting user permission).
For some device like which even coming with KK 4.4, attached USB key won't be mounted automatically, i.e. no node under /Storage as mentioned in this SO. And no mount option under setting/storage. So I guess have to use Android USB manager/host API to access the massive storage, and may use Storage Access Framework(SAF, avaialbe since KK 4.4/API19). magnusja/libaums is an open source project for USB mass storage access. It can work with NanoHTTPD and AsyncHttpServer(no recent update) together for SAF support, but is not robust enough when used for mediaplaying: wit NanoHttpd, seeing lots of java.net.SocketException, slow response; with AsyncHttpServer, there is also exception, though less than NanoHttpd, also slow. For both of them, have to restart the file server for playing a new media file while doing contineously multiple video playback, otherwsie may get MEDIA_ERROR_SERVER_DIED, may due to fail to cancel async http access, which stop the server from responding to new request. Refer to this. So for now, before switch mediaplayer, has to do pause, stop the http server, and restart the http server for loading new media.
According to wikipedia, bInterfaceClass=8 is Mass Storage. For my CF card reader: lsusb -d 058f:6369 -v shows:
...
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x058f Alcor Micro Corp.
idProduct 0x6369
bcdDevice 1.00
iManufacturer 1 Generic
iProduct 2 Mass Storage Device
...
bInterfaceClass 8 Mass Storage
For using intent filter, I update AndroidManifest.xml as below(note meta-data is a must):
<intent-filter>
    <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
    <action android:name="android.intent.action.MAIN"/>
    <action android:name="org.mousedog.eodbusmedia.SplashActivity"/>
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" />
And created xml/device_filter.xml as below(note attribute of usb-device is optional, all USB device will fit if no id spedified):
<?xml version=”1.0” encoding=”utf-8”?>
<resources>
    <usb-device vendor-id="1423" product-id="25449" class="0" subclass="0" protocol="0" />
</resources>
The two ids, 0x58f=1423, 0x6369=25449, cannot use the hex value, even with 0x prefix will lead to Java INT parsing exception.

Either libaums or the two Http server is not stable enough, so better to mount the massive storage. Here is dmesg output for liquid8064:
<6>[ 873.581481] msm_ehci_host msm_ehci_host.0: EHCI USB exited from low power mode
<6>[ 873.854522] usb 1-1: new high-speed USB device number 3 using msm_ehci_host
<6>[ 874.008300] usb 1-1: New USB device found, idVendor=058f, idProduct=6369
<6>[ 874.014007] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
<6>[ 874.021270] usb 1-1: Product: Mass Storage Device
<6>[ 874.026519] usb 1-1: Manufacturer: Generic
<6>[ 874.029907] usb 1-1: SerialNumber: 920321111113
<6>[ 874.056884] scsi1 : usb-storage 1-1:1.0
<5>[ 875.056793] scsi 1:0:0:0: Direct-Access Multiple Flash Reader 1.05 PQ: 0 ANSI: 0
<5>[ 875.078857] sd 1:0:0:0: Attached scsi generic sg0 type 0
<5>[ 876.188659] sd 1:0:0:0: [sda] 2001888 512-byte logical blocks: (1.02 GB/977 MiB)
<5>[ 876.197113] sd 1:0:0:0: [sda] Write Protect is off
<7>[ 876.200897] sd 1:0:0:0: [sda] Mode Sense: 03 00 00 00
<3>[ 876.202239] sd 1:0:0:0: [sda] No Caching mode page present
<3>[ 876.206787] sd 1:0:0:0: [sda] Assuming drive cache: write through
<3>[ 876.221252] sd 1:0:0:0: [sda] No Caching mode page present
<3>[ 876.225799] sd 1:0:0:0: [sda] Assuming drive cache: write through
<6>[ 876.235839] sda: sda1
<3>[ 876.251342] sd 1:0:0:0: [sda] No Caching mode page present
<3>[ 876.255828] sd 1:0:0:0: [sda] Assuming drive cache: write through
<5>[ 876.261840] sd 1:0:0:0: [sda] Attached SCSI removable disk
On Rockchip, init.usbstorage.rc contains:
on init
# Directory for multi usb storage
mkdir /mnt/usb_storage 0700 root system
mount tmpfs tmpfs /mnt/usb_storage mode=0555,uid=1013,gid=1023
Where AID_MEDIA 1013 /* mediaserver process */
There is an app UMS enable, github src, maybe just for enable Usb Mass Storge for accessed by PC host.
StickMount can be used to mount USB Mass Storage. According to this the mount point would be /mnt/media_rw/random-hex-id
However, this folder is not accessible from normal app. Refer to this xda post. I decoded Stickmount apk, and found this may work: 1) adb root 2) adb shell 3) mount -o rw,remount / / => remount / with rw option 4) mkdir -p /mnt/usb_storage/ 5)
mount -t vfat -o rw,nosuid,nodev,umask=0,dmask=0,fmask=0%s /dev/block/%s '%s/usbStorage/%s'
mount -t ext4 -o rw,nosuid,nodev,umask=0,dmask=0,fmask=0%s /dev/block/%s '%s/usbStorage/%s'
mount -t ext3 -o rw,nosuid,nodev,umask=0,dmask=0,fmask=0%s /dev/block/%s '%s/usbStorage/%s'
mount -t ext2 -o rw,nosuid,nodev,umask=0,dmask=0,fmask=0%s /dev/block/%s '%s/usbStorage/%s'
ntfs-3g -o umask=0%s /dev/block/%s '%s/usbStorage/%s'
mount -t ntfs -o rw,nosuid,nodev,umask=0,dmask=0,fmask=0%s /dev/block/%s '%s/usbStorage/%s'
mount -t exfat -o rw,nosuid,nodev,umask=0,dmask=0,fmask=0%s /dev/block/%s '%s/usbStorage/%s'
mount.exfat-fuse -o rw,nosuid,nodev,umask=0,dmask=0,fmask=0%s /dev/block/%s '%s/usbStorage/%s'
For a FAT32 USB drive, with command like: # mount -o rw,umask=000 -t $type /dev/block/sda1 /mnt/usb_storage , if $type is cifs , will get mount: Invalid argument; if $type is exfat or exfat-fuse, will get: mount: No such device; if $type is vfat, it works. Set umask=000 to give access to all user.
Refer this and this. For device has udev, so add rules to /etc/udev/rules.d/customer.rule with SUBSYSTEM=="scsi", ATTRS{model}=="Ext HDD 1021 ", SYMLINK+="MyUMS%n" may work. But the Rockchip box doesn't have udev. As mentioned here, some Android uses vold (volume daemon) instead of udevd. Rockchip has busybox installed. On Rockchip box: ls -ls /dev/socket => srw-rw---- root mount 1969-12-31 19:00 vold, as mentioned here, cat /init.rc will see:
service vold /system/bin/vold
class core
socket vold stream 0660 root mount
ioprio be 2
Some device does have vold, and has same above vold service code in /init.rc. However, it won't auto mount. As mentioned here, since Android 4.3 vold.fstab is changed to /fstab.<device> and this file needs root access. Refer to https://source.android.com/devices/storage/config for more official info. The same USB key will show up as 3 nodes:
 # ls -l /dev/sg0
crw------- root root 21, 0 2018-03-18 19:50 sg0
 # ls -l /sys/block/sda
lrwxrwxrwx root root 2018-03-18 19:50 sda -> ../devices/platform/msm_ehci_host.0/usb1/1-1/1-1:1.0/host1/target1:0:0/1:0:0:0/block/sda
 # ls -l /dev/block/sda
brw------- root root 8, 0 1970-03-20 13:05 sda
The code I added in /etc/init.post_boot.sh as below:
mount -o rw,remount / /
mkdir -p /mnt/usb_storage/DISK1/udisk0
#chmod -R 777 /mnt/usb_storage
#chmod -R option doesn't work as expected, put -R at the end works, but will change mode of all files on the USB storage
chmod 777 /mnt/usb_storage /mnt/usb_storage/DISK1 /mnt/usb_storage/DISK1/udisk0
mount -o ro,remount / /
mount -o rw,umask=000 -t vfat /dev/block/sda1 /mnt/usb_storage/DISK1/udisk0

0 Comments:

Post a Comment