Framework USB How-to

来源:互联网 发布:化妆水 知乎 编辑:程序博客网 时间:2024/04/28 20:18

1 监控特定的文件创建和删除

1.1 Java

1.1.1 InotifyMonService.java

package com.george.inotifymon;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbManager;
import android.os.FileObserver;
import android.os.IBinder;
import android.util.Log;

public class InotifyMonService extends Service {
    private final static String TAG = "InotifyMonService";
    private final static String MON_DIR = "/sdcard/DCIM";
    private final static String PID9091 = "diag,serial_smd,rmnet_qti_bam,adb";

    private FileObserver mFileOb;
    private UsbManager mUsbManager;
    
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");
        mUsbManager = (UsbManager)this.getSystemService(Context.USB_SERVICE);
        mFileOb = new SdCardListener(MON_DIR);
        new myThread().start();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    @Deprecated
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
    }
    
    private class myThread extends Thread {
        @Override
        public void run() {
            super.run();
            mFileOb.startWatching();
        }
    }

    private class SdCardListener extends FileObserver {
        public SdCardListener(String path) {
            //super(path, FileObserver.ALL_EVENTS);
            super(path, FileObserver.CREATE | FileObserver.MOVED_TO |
                    FileObserver.DELETE | FileObserver.MOVED_FROM);
        }

        @Override
        public void onEvent(int event, String path) {
            Log.d(TAG, "event: 0x"+ Integer.toHexString(event));
            event = event & FileObserver.ALL_EVENTS;
            switch(event) {
                case FileObserver.CREATE:
                    Log.d(TAG, "create path: " + path);
                    if ((path != null) && path.equals("pid9091.txt")) {
                        mUsbManager.setCurrentFunction(PID9091, true);
                        Log.d(TAG, "switch USB cfg to (" + PID9091 + ")");
                    }
                    break;
                case FileObserver.DELETE:
                    Log.d(TAG, "delete path: " + path);
                    if ((path != null) && path.equals("pid9091.txt")) {
                        mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP, true);
                        Log.d(TAG, "switch USB cfg to (" + UsbManager.USB_FUNCTION_MTP + ")");
                    }
                    break;
                case FileObserver.MOVED_FROM:
                    Log.d(TAG, "moved_from path: " + path);
                    if (path != null) {
                        // TODO
                    }
                    break;
                case FileObserver.MOVED_TO:
                    Log.d(TAG, "moved_to path: " + path);
                    if (path != null) {
                        // TODO
                    }
                    break;
            }
        }
    }
}


1.1.2 AndroidManifest.xml

    USES: android:sharedUserId="android.uid.system"

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MANAGE_USB" />

1.1.3 Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_JAVA_LIBRARIES := bouncycastle conscrypt telephony-common ims-common
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 android-support-v13 jsr305

LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES := \
        $(call all-java-files-under, src)

LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res

LOCAL_PACKAGE_NAME := InotifyMon
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true

include $(BUILD_PACKAGE)


1.2 C

1.2.1 inotify_mon.c

/*
 * inotify_mon.c
 *
 * Copyright (C) 2017
 *
 * George Tso <zoosenpin@163.com>
 */

#include <cutils/properties.h>
#include <pthread.h>
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/inotify.h>  
#include <unistd.h>  

#define BUF_SZ 64
#define MSG_SZ 256
#define MON_DIR "/sdcard/DCIM"
#define NR_EVENT 12
#define PID9091 "diag,serial_smd,rmnet_qti_bam,adb"

static char *event_str[NR_EVENT] =   
{  
    "IN_ACCESS",  
    "IN_MODIFY",  
    "IN_ATTRIB",  
    "IN_CLOSE_WRITE",  
    "IN_CLOSE_NOWRITE",  
    "IN_OPEN",  
    "IN_MOVED_FROM",  
    "IN_MOVED_TO",  
    "IN_CREATE",  
    "IN_DELETE",  
    "IN_DELETE_SELF",  
    "IN_MOVE_SELF"  
};

static int dbg_msg(const char *fmt, ...)
{
    char buf[MSG_SZ];
    va_list arg;
    int ret = 0;
    int fd = 0;

    va_start(arg, fmt);
    ret = vsnprintf(buf, MSG_SZ, fmt, arg);
    va_end(arg);

    fd = open("/dev/kmsg", O_WRONLY);
    if (fd > 0) {
        ret = write(fd, buf, ret);
        close(fd);
    }

    return ret;
}

static void set_usb_cfg(const char *cfg)
{
    char cmd[BUF_SZ] = {'\0'};

    if (0) {
        // Legacy style
        property_set("persist.sys.usb.config", cfg);
    } else {
        snprintf(cmd, BUF_SZ,
                "service call usb 15 s16 %s i32 1", cfg);
        system(cmd);
    }
}
 
static void* inotify_mon_thread(void* arg)
{
    char buf[BUFSIZ];  
    int fd;  
    int wd;  
    int i;  
    int len;  
    int nread;  
    struct inotify_event *event;  
    int cnt = 25;

    do {
        if (!access(MON_DIR, F_OK)) {
            break;
        }
        dbg_msg("wait framework mounts /sdcard/\n");
        sleep(1);
    } while (cnt-- > 0);

    sleep(1);

    fd = inotify_init();  
    if (fd < 0) {  
        dbg_msg("inotify_init failed\n");  
        goto err;  
    }  

    cnt = 25;
    do {
        wd = inotify_add_watch(fd, MON_DIR, IN_CREATE | IN_DELETE |
                IN_MOVED_FROM | IN_MOVED_TO);  
        if (wd < 0) {  
            dbg_msg("inotify_add_watch %s failed\n", MON_DIR);
            sleep(1);
            continue;
        }
        break;
    } while (cnt-- > 0);

    buf[sizeof(buf) - 1] = 0;  
    while ((len = read(fd, buf, sizeof(buf) - 1)) > 0) {
        nread = 0;
        while (len > 0) {
            event = (struct inotify_event *)&buf[nread];
            for (i = 0; i < NR_EVENT; i++) {
                if ((event->mask >> i) & 1) {
                    if (event->len > 0) {
                        dbg_msg("file: %s, event_str: %s\n", event->name, event_str[i]);
                        // IN_CREATE
                        if (i == 8 && !strncmp(event->name, "pid9091", 7)) {
                            set_usb_cfg(PID9091);
                        } else if (i == 9 && !strncmp(event->name, "pid9091", 7)) { // IN_DELETE
                            set_usb_cfg("mtp,adb");
                        }
                    }
                }
            }
            nread = nread + sizeof(struct inotify_event) + event->len;
            len = len - sizeof(struct inotify_event) - event->len;
        }
    }
    return 0;
err:
    return "err";
}

int main(int argc, char *argv[])  
{
    pthread_t id;

    pthread_create(&id, NULL, inotify_mon_thread, NULL);
    while (1) {
        sleep(1);
    }

    return 0;
}


1.2.2 sepolicy

binder_use(inotify_mon)
binder_call(inotify_mon, servicemanager);
binder_call(inotify_mon, system_server)
allow inotify_mon kmsg_device:chr_file w_file_perms;
allow inotify_mon sdcard_type:dir { getattr r_dir_perms };
allow inotify_mon sdcard_type:file { getattr r_file_perms };
allow inotify_mon system_prop:property_service set;

2 文件管理器中删除文件,USB MTP/PTP不刷新问题

// such as storage = "/sdcard"
private void oemForceScanStorage(String storage) {
    File file = new File(storage);

    if (file.exists()) {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_MEDIA_MOUNTED);
        intent.setData(Uri.fromFile(file));
        sendBroadcast(intent);
    }
}

// such as f = "/sdcard/df.mp4"
private void oemForceScanFile(String f) {
    File file = new File(f);

    if (file.exists()) {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        intent.setData(Uri.fromFile(file));
        sendBroadcast(intent);
    }

}

原创粉丝点击