yy1717
2025-12-26 3244dbd998aaed5ba13db688a5c0b85eb88e75a6
可升级200万摄像头,兼容旧摄像头,多个摄像头都可升级
2个文件已删除
6个文件已添加
10个文件已修改
1908 ■■■■ 已修改文件
UStorageTest/build.gradle 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/build.gradle 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/libs/libspca.aar 补丁 | 查看 | 原始文档 | blame | 历史
app/libs/loading.aar 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/AndroidManifest.xml 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/fwupgrade/saymanss/FwUpgradeService.java 277 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/fwupgrade/saymanss/HomePageActivity.java 288 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/fwupgrade/saymanss/deviceplug/CDeviceFilter.java 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/fwupgrade/saymanss/deviceplug/CUSBListener.java 426 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/fwupgrade/saymanss/deviceplug/CameraControlTransfer.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/fwupgrade/saymanss/deviceplug/IUsbDevicePlugDelegate.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/fwupgrade/saymanss/deviceplug/UstorageDeviceInstance.java 213 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/jni/NativeMethods.java 299 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/jniLibs/arm64-v8a/libSonixCamera.so 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/jniLibs/armeabi-v7a/libSonixCamera.so 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/activity_homepage.xml 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
build.gradle 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
gradle/wrapper/gradle-wrapper.properties 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
UStorageTest/build.gradle
@@ -2,7 +2,7 @@
android {
    compileSdkVersion 27
    namespace "com.i4season.ustoragetest"
    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 27
@@ -23,5 +23,5 @@
}
dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    api fileTree(include: ['*.jar'], dir: 'libs')
}
app/build.gradle
@@ -2,13 +2,19 @@
android {
    compileSdkVersion 27
    namespace "com.fwupgrade.saymanss"
    defaultConfig {
        applicationId "com.fwupgrade.saymanss"
        minSdkVersion 21
        targetSdkVersion 27
        versionCode 8
        versionName "1.8"
        versionCode 20
        versionName "2.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        ndk {
            // Specifies the ABI configurations of your native
            // libraries Gradle should build and package with your APK.
            abiFilters "arm64-v8a", "armeabi-v7a"
        }
    }
    buildFeatures{
        aidl true
@@ -32,12 +38,6 @@
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
@@ -69,12 +69,6 @@
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:0.5'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2'
    compile 'com.android.support:multidex:1.0.1'
    implementation 'com.android.support:multidex:1.0.1'
    implementation project(':UStorageTest')
    // loading
    compile(name: 'loading', ext: 'aar')
    // otg lic
    compile(name: 'libspca', ext: 'aar')
}
app/libs/libspca.aar
Binary files differ
app/libs/loading.aar
Binary files differ
app/src/main/AndroidManifest.xml
@@ -14,18 +14,17 @@
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
<!--        <activity android:name=".HomePageActivity"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar"
            android:configChanges="keyboard|keyboardHidden|navigation|orientation|screenSize"
            android:launchMode="singleTask"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="stateAlwaysHidden|adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>-->
<!--        <activity android:name=".HomePageActivity"-->
<!--            android:theme="@style/Theme.AppCompat.Light.NoActionBar"-->
<!--            android:configChanges="keyboard|keyboardHidden|navigation|orientation|screenSize"-->
<!--            android:launchMode="singleTask"-->
<!--            android:screenOrientation="portrait"-->
<!--            android:windowSoftInputMode="stateAlwaysHidden|adjustResize">-->
<!--            <intent-filter>-->
<!--                <action android:name="android.intent.action.MAIN" />-->
<!--                <category android:name="android.intent.category.LAUNCHER" />-->
<!--            </intent-filter>-->
<!--        </activity>-->
      <service android:name=".FwUpgradeService" android:exported="true"/>
    </application>
app/src/main/java/com/fwupgrade/saymanss/FwUpgradeService.java
@@ -16,15 +16,18 @@
import android.widget.Toast;
import com.fwupgrade.saymanss.deviceplug.CameraControlTransfer;
import com.fwupgrade.saymanss.deviceplug.IUsbDevicePlugDelegate;
import com.fwupgrade.saymanss.deviceplug.UstorageDeviceInstance;
import com.fwupgrade.saymanss.utils.AppPathInfo;
import com.fwupgrade.saymanss.utils.UtilTools;
import com.fwupgrade.saymanss.view.GeneralDialog;
import com.jni.NativeMethods;
import com.jni.UStorageTestModule;
import com.spca.usb.CUSBListener;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@@ -83,20 +86,21 @@
    public void onCreate() {
        super.onCreate();
        Log.i(TAG,"onCreate");
        initTarget();
        initData();
        acceptFwList();
        initDeviceSDK();
        UStorageTestModule.getInstance().initUStorageDeviceModuleWithVirtualDisk(AppPathInfo.getLogPath());
    }
    private File[] mFileList;
    private ArrayList<CameraControlTransfer> upgradeList = new ArrayList<>();
    private volatile boolean upgrading = false;
    private HashMap<String, Integer> tty = new HashMap<>();
    private int mUpgradeSuccessNum = 0;
    private int mUpgradeFailNum = 0;
    private int mDevicesNum = 0;
    private final Handler mHander = new Handler(Looper.getMainLooper()) {
        @Override
@@ -119,18 +123,16 @@
                case USB_DEVICE_DETACHED:
                    int count = (int) msg.obj;
                    Log.i(TAG,"count="+count);
                    if (count<2) {
                        tty.clear();
                        initTarget();
                        int ret = UstorageDeviceInstance.getInstance().tryAgain(FwUpgradeService.this);
                        if (ret==1){
                            Log.i(TAG,"发送失败结果广播给驾培");
                            sendToDriveTrainByBroadCast(0,1);
                            sendToNewDriveTrainByBroadCast(0,1);
                        }
                    }
//                    int count = (int) msg.obj;
//                    Log.i(TAG,"count="+count);
//                    if (count<2) {
//                        int ret = UstorageDeviceInstance.getInstance().tryAgain(FwUpgradeService.this);
//                        if (ret==1){
//                            Log.i(TAG,"发送失败结果广播给驾培");
//                            sendToDriveTrainByBroadCast(0,1);
//                            sendToNewDriveTrainByBroadCast(0,1);
//                        }
//                    }
                    break;
@@ -152,33 +154,13 @@
                case USB_DEVICE_UPGRADE:
                    String devName = (String) msg.obj;
                    int errCode = msg.arg1;
                    int succ_num = 0, fail_num = 0;
                    Log.d(TAG, "devicesNum:" + mDevicesNum + " mUpgradeSuccessNum:" + mUpgradeSuccessNum + " mUpgradeFailNum:" + mUpgradeFailNum);
                    Log.d("fwup","Upgrade result:" + devName + ", errCode: " + errCode+".ttySize="+tty.size());
                    if (tty.containsKey(devName)) {
                        tty.put(devName, errCode == 0? UPGRADE_SUCCESS:UPGRADE_FAIL);
                    }
                    for (Map.Entry<String, Integer> entry : tty.entrySet()) {
                        if (entry.getValue() == UPGRADE_SUCCESS) {
                            succ_num++;
                        } else if (entry.getValue() == UPGRADE_FAIL) {
                            fail_num++;
                        }
                    }
                    if (succ_num + fail_num == tty.size()) {
                    if (mUpgradeFailNum + mUpgradeSuccessNum == mDevicesNum) {
                        Log.d(TAG, "Upgrade Finish!");
                        sendToNewDriveTrainByBroadCast(succ_num,tty.size());
                        sendToDriveTrainByBroadCast(succ_num,tty.size());
                        sendToNewDriveTrainByBroadCast(mUpgradeSuccessNum,mDevicesNum);
                        sendToDriveTrainByBroadCast(mUpgradeSuccessNum,mDevicesNum);
//                        System.exit(0);
                    }
                    break;
@@ -206,19 +188,7 @@
    }
    // 每次升级路径值最小的
    private void initTarget() {
        ArrayList<UsbDevice> targets = UstorageDeviceInstance.getInstance().acceptOTGDeviceInfo((UsbManager) getSystemService(USB_SERVICE));
        String min = "Z";
        for (UsbDevice usbDevice: targets) {
            if (usbDevice.getDeviceName().compareTo(min) < 0) {
                min = usbDevice.getDeviceName();
            }
        }
        Log.i(TAG,"min="+min);
        tty.put(min, UPGRADE_PRESET);
    }
    /**
     * 获取fw列表
@@ -252,19 +222,8 @@
     * UstorageDeviceSDK初始化.
     */
    private void initDeviceSDK() {
        int count = 0 ;
        int ret = UstorageDeviceInstance.getInstance().tryAttcheDeviceHandle(FwUpgradeService.this, FwUpgradeService.this);
        Log.i(TAG,"initDeviceSDk,ret="+ret);
        if (ret==1){
            ++count;
            Log.i(TAG,"再次的初始化");
            Message message = Message.obtain();
            message.obj = count;
            message.what = USB_DEVICE_DETACHED;
            mHander.sendMessageDelayed(message,1000);
        }
        Log.i(TAG,"initDeviceSDk");
        UstorageDeviceInstance.getInstance().tryAttcheDeviceHandle(FwUpgradeService.this, FwUpgradeService.this);
    }
    @Override
@@ -272,86 +231,132 @@
        Log.d(TAG,"usbDeviceInsert");
    }
    public void onProgress(float progress) {
    }
    private void upgradeNext() {
        if (upgradeList.isEmpty()) {
            Log.d(TAG, "upgrade complete!");
            mHander.sendEmptyMessage(USB_DEVICE_UPGRADE);
        }
        if (!upgrading && upgradeList.size() > 0) {
            upgrading = true;
            CameraControlTransfer cct = upgradeList.get(0);
            new Thread(new Runnable() {
    @Override
    public void permissionFinish(boolean isSuccessful, CUSBListener.UsbControlBlock ctrlBlock) {
        synchronized (this) {
            Message msg = Message.obtain();
            msg.obj = isSuccessful;
            msg.what = USB_DEVICE_PERRMISSION;
            mHander.sendMessage(msg);
            Log.d(TAG,"permissionFinish:" + isSuccessful);
            if (isSuccessful && ctrlBlock != null) {
                initFwUpgrade(ctrlBlock);
                public void run() {
                    if (!cct.bPermission) {
                        return;
                    }
                    Log.d(TAG,"UpdateCameraInfo->dev" + cct.dev.getDeviceName());
                    boolean bClaim = cct.connection.claimInterface(cct.dev.getInterface(0), true);
                    //devInfo.connection.releaseInterface(devInfo.dev.getInterface(0));
                    Log.d(TAG,"UpdateCameraInfo->bClaim" + String.valueOf(bClaim));
                    Log.d(TAG, "Start init");
                    boolean r = NativeMethods.getInstance().Initialize(cct);
                    if (r) {
                        Log.d(TAG, "Initialise success!");
                        byte data[] = new byte[100];
                        java.util.Arrays.fill(data, (byte) 0);
                        if (NativeMethods.getInstance().GetProduct(data, 100)) {
                            if (data[0] != 0xFF) {
                                String devName = new String(data).trim();
                            }
                        }
                        java.util.Arrays.fill(data, (byte) 0);
                        if (NativeMethods.getInstance().GetFwVersion(data, 100, true)) {
                            if (data[0] != 0xFF) {
                                String fwVersion = new String(data).trim();
                            }
                        }
                        final NativeMethods.SERIAL_FLASH_TYPE sft = NativeMethods.SERIAL_FLASH_TYPE.SFT_UNKNOW;
                        if(!NativeMethods.getInstance().GetSerialFlashType(sft, true)){
                            Log.i("test", "GetSerialFlashType failed");
                        }
                        sft.setValue(NativeMethods.SERIAL_FLASH_TYPE.SFT_MXIC.ordinal());
                        Log.i("test", "sft= " + sft.getValue());
                        if(sft.getValue() == 0){
                            //return;
                            Log.i("test", "set sft= " + NativeMethods.SERIAL_FLASH_TYPE.SFT_MXIC.toString());
                            sft.setValue(NativeMethods.SERIAL_FLASH_TYPE.SFT_MXIC.ordinal());
                        }
                        if (mFileList != null && mFileList.length > 0) {
                            try {
                                String path = mFileList[0].getAbsolutePath();
                                NativeMethods.ASIC_ROM_TYPE romType = NativeMethods.ASIC_ROM_TYPE.ART_Unknow;
                                int chipID[] = new int[1];
                                if (!NativeMethods.getInstance().GetAsicRomType(romType, chipID)) {
                                    throw new Exception("get chip rom type failed!");
                                }
                                Log.d("RomType", String.valueOf(chipID[0]));
                                FileInputStream fis = new FileInputStream(path);
                                fis.available();
                                byte[] buffer = new byte[7];
                                if (fis.read(buffer, 0, 7) != -1) {
                                    if (buffer[5] < 48 || buffer[5] >= 65 || buffer[6] < 48 || buffer[6] >= 65) {
                                        throw new Exception("The selected firmware and device do not match!");
                                    }
                                    int id = (buffer[5] - 48) * 16 + (buffer[6] - 48);
                                    if (id != chipID[0]) {
                                        throw new Exception("The selected firmware and device do not match!");
                                    }
                                }
                                Log.d(TAG, "BurnFw start...");
                                if (!NativeMethods.getInstance().BurnerFW(FwUpgradeService.this, path, sft, true)) {
                                    mUpgradeFailNum++;
                                    Log.d(TAG, "BurnFw fail!!!");
            }else{
                sendToDriveTrainByBroadCast(0,1);
                sendToNewDriveTrainByBroadCast(0,1);
                                    mUpgradeSuccessNum++;
                                    Log.d(TAG, "BurnFw success!!!");
                                }
                                fis.close();
                                SystemClock.sleep(500);
                                NativeMethods.getInstance().RestartDevice();
                            } catch (Exception ex) {
                                Log.e(TAG, "upgrade fail: " + ex.getMessage());
            }
        }
                        NativeMethods.getInstance().UnInitialize();
    }
                    upgradeList.remove(cct);
                    upgrading = false;
                    SystemClock.sleep(1000);
                    upgradeNext();
                }
            }).start();
        }
    }
    @Override
    public void permissionFinish(boolean isSuccessful, com.fwupgrade.saymanss.deviceplug.CUSBListener.UsbControlBlock ctrlBlock, CameraControlTransfer cct) {
        synchronized (this) {
            mDevicesNum++;
            upgradeList.add(cct);
            upgradeNext();
        }
    }
    @Override
    public void usbDeviceDetached() {
        Log.d(TAG,"usbDeviceDetached");
    }
    /**
     * 初始化升级环境
     */
    private void initFwUpgrade(CUSBListener.UsbControlBlock ctrlBlock) {
        final int vendorId = ctrlBlock.getVenderId();
        final int productId = ctrlBlock.getProductId();
        int fileDescriptor = ctrlBlock.getFileDescriptor();
        int busNum = ctrlBlock.getBusNum();
        int devNum = ctrlBlock.getDevNum();
        boolean isTarget = false;
        String usbfsName = getUSBFSName(ctrlBlock);
        String devName = ctrlBlock.getDeviceName();
        String serial = ctrlBlock.getSerial();
        Log.d(TAG,"sonixCamInit " + String.format("vendorId:%d productId:%d fileDescriptor:%d busNum:%d devNum:%d usbfsName:%s devName:%s serial:%s,tty.size=%d", vendorId, productId, fileDescriptor, busNum, devNum, usbfsName, devName, serial,tty.size()));
        if (tty.containsKey(devName) && tty.get(devName) == 0) {
            isTarget = true;
            tty.put(devName, 1);
        }
        if (!isTarget) {
            Log.d(TAG,"Not sonixCam, close");
            ctrlBlock.close();
            return;
        }
        Log.d(TAG,"Is sonixCam, upgrade!");
        Message msg = Message.obtain();
        //msg.obj = errCode == 0;
        msg.obj = new CameraInfo(vendorId, productId, fileDescriptor, busNum, devNum, usbfsName, devName);
        msg.what = USB_DEVICE_OPEN;
        mHander.sendMessage(msg);
    }
    private final String getUSBFSName(final CUSBListener.UsbControlBlock ctrlBlock) {
        String result = null;
        final String name = ctrlBlock.getDeviceName();
        final String[] v = !TextUtils.isEmpty(name) ? name.split("/") : null;
        if ((v != null) && (v.length > 2)) {
            final StringBuilder sb = new StringBuilder(v[0]);
            for (int i = 1; i < v.length - 2; i++)
                sb.append("/").append(v[i]);
            result = sb.toString();
        }
        if (TextUtils.isEmpty(result)) {
//            Log.w(TAG, "failed to get USBFS path, try to use default path:" + name);
            result = "/dev/bus/usb";
        }
        return result;
    }
    class Update implements Runnable {
        CameraInfo cam;
app/src/main/java/com/fwupgrade/saymanss/HomePageActivity.java
@@ -26,14 +26,16 @@
import android.widget.Toast;
import com.fwupgrade.saymanss.adapter.FwFileListAdapter;
import com.fwupgrade.saymanss.deviceplug.CameraControlTransfer;
import com.fwupgrade.saymanss.deviceplug.IUsbDevicePlugDelegate;
import com.fwupgrade.saymanss.deviceplug.UstorageDeviceInstance;
import com.fwupgrade.saymanss.utils.AppPathInfo;
import com.fwupgrade.saymanss.utils.SystemUtil;
import com.fwupgrade.saymanss.utils.UtilTools;
import com.fwupgrade.saymanss.view.GeneralDialog;
import com.jni.NativeMethods;
import com.jni.UStorageTestModule;
import com.spca.usb.CUSBListener;
import java.io.BufferedReader;
import java.io.File;
@@ -43,7 +45,6 @@
import java.util.HashMap;
import java.util.Map;
import app.dinus.com.loadingdrawable.LoadingView;
public class HomePageActivity extends AppCompatActivity implements IUsbDevicePlugDelegate, AdapterView.OnItemClickListener {
    static final String TAG = "fwup";
@@ -81,8 +82,7 @@
    protected TextView mTitle;
    /** 返回 */
    protected TextView mAppVersion;
    /** LoadingView */
    private LoadingView loadingView;
    /** 升级 */
    private TextView mFwUpDataBtn;
    /** 提示 */
@@ -90,9 +90,17 @@
    /** fw list */
    protected ListView mListView;
    private TextView mDeviceFwVersion;
    private TextView mFileFwVersion;
    private File[] mFileList;
    private HashMap<String, Integer> tty = new HashMap<>();
    private ArrayList<CameraControlTransfer> upgradeList = new ArrayList<>();
    private volatile boolean upgrading = false;
    private int mUpgradeSuccessNum = 0;
    private int mUpgradeFailNum = 0;
    private int mDevicesNum = 0;
    private Handler mHander = new Handler() {
        @Override
@@ -159,35 +167,19 @@
                            mFwUpDataBtn.setText("升级失败");
                        }
                    }*/
                    String devName = (String) msg.obj;
                    int errCode = msg.arg1;
                    int succ_num = 0, fail_num = 0;
                    Log.d(TAG, "devicesNum:" + mDevicesNum + " mUpgradeSuccessNum:" + mUpgradeSuccessNum + " mUpgradeFailNum:" + mUpgradeFailNum);
                    Log.d("fwup","Upgrade result:" + devName + ", errCode: " + errCode);
                    if (tty.containsKey(devName)) {
                        tty.put(devName, errCode == 0? UPGRADE_SUCCESS:UPGRADE_FAIL);
                    }
                    for (Map.Entry<String, Integer> entry : tty.entrySet()) {
                        if (entry.getValue() == UPGRADE_SUCCESS) {
                            succ_num++;
                        } else if (entry.getValue() == UPGRADE_FAIL) {
                            fail_num++;
                        }
                    }
                    if (succ_num + fail_num == tty.size()) {
                    if (mUpgradeFailNum + mUpgradeSuccessNum == mDevicesNum) {
                        Log.d(TAG, "Upgrade Finish!");
                        Intent intent = new Intent();
                        intent.putExtra("result", succ_num == tty.size()? 0 : 1);
                        intent.putExtra("result", mUpgradeSuccessNum == mDevicesNum? 0 : 1);
                        intent.setAction("com.fwupgrade.saymanss.UPGRADE_COMPLETE");
                        intent.setPackage("safeluck.drive.training");
                        sendBroadcast(intent);
                        intent = new Intent();
                        intent.putExtra("result", succ_num == tty.size()? 0 : 1);
                        intent.putExtra("result", mUpgradeSuccessNum == mDevicesNum? 0 : 1);
                        intent.setAction("com.fwupgrade.saymanss.UPGRADE_COMPLETE");
                        intent.setPackage("demo1.tech.anyun.com.myapplication");
                        sendBroadcast(intent);
@@ -212,11 +204,10 @@
        initView();
        checkPermission();
        initTarget();
        initData();
        acceptFwList();
        initListener();
        initDeviceSDK();
        UStorageTestModule.getInstance().initUStorageDeviceModuleWithVirtualDisk(AppPathInfo.getLogPath());
    }
@@ -266,25 +257,15 @@
        //顶部条
        mTitle = (TextView) findViewById(R.id.app_topbar_center_text);
        mAppVersion = (TextView) findViewById(R.id.app_topbar_left_text);
        loadingView = (LoadingView) findViewById(R.id.progress_loading);
        loadingView.setColorFilter(getResources().getColor(R.color.apptakeaction));
        mFwUpDataBtn = (TextView) findViewById(R.id.app_fwupdata_btn);
        mFwUpNo = (TextView) findViewById(R.id.app_topbar_no);
        mListView = (ListView) findViewById(R.id.app_fw_list);
    }
    // 每次升级路径值最小的
    private void initTarget() {
        ArrayList<UsbDevice> targets = UstorageDeviceInstance.getInstance().acceptOTGDeviceInfo((UsbManager) getSystemService(USB_SERVICE));
        String min = "Z";
        for (UsbDevice usbDevice: targets) {
            if (usbDevice.getDeviceName().compareTo(min) < 0) {
                min = usbDevice.getDeviceName();
        mDeviceFwVersion = (TextView) findViewById(R.id.device_fw_version);
        mFileFwVersion = (TextView) findViewById(R.id.file_fw_version);
            }
        }
        tty.put(min, UPGRADE_PRESET);
    }
    /**
     * 初始化数据
@@ -318,13 +299,6 @@
     */
    private void initDeviceSDK() {
        UstorageDeviceInstance.getInstance().tryAttcheDeviceHandle(HomePageActivity.this, HomePageActivity.this);
//        Thread thread = new Thread() {
//            @Override
//            public void run() {
//                UstorageDeviceInstance.getInstance().tryAttcheDeviceHandle(HomePageActivity.this, HomePageActivity.this);
//            }
//        };
//        thread.start();
    }
    /**
@@ -336,14 +310,7 @@
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
        int visibility = loadingView.getVisibility();
        if (mFileList != null && visibility != View.VISIBLE) {
            File file = mFileList[position];
            String point = "确定升级此固件吗?";
            GeneralDialog generalDialog = new GeneralDialog(this, R.style.wdDialog, mHander, point, file);
            generalDialog.setCanceledOnTouchOutside(false);
            generalDialog.show();
        }
    }
@@ -352,7 +319,7 @@
     */
    private void acceptFwList() {
        Log.d("fwup","acceptFwList: ");
        loadingView.setVisibility(View.GONE);
        File file = new File(AppPathInfo.getFwSavePath());
        File[] files = file.listFiles();
        if (files != null && files.length > 0) {
@@ -375,16 +342,11 @@
    }
    @Override
    public void permissionFinish(boolean isSuccessful, CUSBListener.UsbControlBlock ctrlBlock) {
    public void permissionFinish(boolean isSuccessful, com.fwupgrade.saymanss.deviceplug.CUSBListener.UsbControlBlock ctrlBlock, CameraControlTransfer cct) {
        synchronized (this) {
            Message msg = Message.obtain();
            msg.obj = isSuccessful;
            msg.what = USB_DEVICE_PERRMISSION;
            mHander.sendMessage(msg);
            Log.d("fwup","permissionFinish:" + isSuccessful);
            if (isSuccessful && ctrlBlock != null) {
                initFwUpgrade(ctrlBlock);
            }
            mDevicesNum++;
            upgradeList.add(cct);
            upgradeNext();
        }
    }
@@ -430,78 +392,13 @@
        }
    }
    /**
     * 初始化升级环境
     */
    private void initFwUpgrade(CUSBListener.UsbControlBlock ctrlBlock) {
        final int vendorId = ctrlBlock.getVenderId();
        final int productId = ctrlBlock.getProductId();
        int fileDescriptor = ctrlBlock.getFileDescriptor();
        int busNum = ctrlBlock.getBusNum();
        int devNum = ctrlBlock.getDevNum();
        boolean isTarget = false;
        String usbfsName = getUSBFSName(ctrlBlock);
        String devName = ctrlBlock.getDeviceName();
        String serial = ctrlBlock.getSerial();
        Log.d("fwup","sonixCamInit " + String.format("vendorId:%d productId:%d fileDescriptor:%d busNum:%d devNum:%d usbfsName:%s devName:%s serial:%s", vendorId, productId, fileDescriptor, busNum, devNum, usbfsName, devName, serial));
        //final int errCode = UStorageTestModule.getInstance().sonixCamInit(vendorId, productId, fileDescriptor, busNum, devNum, usbfsName);
        //Log.d("fwup","sonixCamInit errCode:" + errCode);
        /*runOnUiThread(new Runnable() {
            @Override
            public void run() {
                UtilTools.showToast(HomePageActivity.this, "vid: " + vendorId + " pid: " + productId + " err: " + errCode);
            }
        });*/
        if (tty.containsKey(devName) && tty.get(devName) == 0) {
            isTarget = true;
            tty.put(devName, 1);
        }
        if (!isTarget) {
            Log.d("fwup","Not sonixCam, close");
            ctrlBlock.close();
            return;
        }
        Log.d("fwup","Is sonixCam, upgrade!");
        Message msg = Message.obtain();
        //msg.obj = errCode == 0;
        msg.obj = new CameraInfo(vendorId, productId, fileDescriptor, busNum, devNum, usbfsName, devName);
        msg.what = USB_DEVICE_OPEN;
        mHander.sendMessage(msg);
    }
    private final String getUSBFSName(final CUSBListener.UsbControlBlock ctrlBlock) {
        String result = null;
        final String name = ctrlBlock.getDeviceName();
        final String[] v = !TextUtils.isEmpty(name) ? name.split("/") : null;
        if ((v != null) && (v.length > 2)) {
            final StringBuilder sb = new StringBuilder(v[0]);
            for (int i = 1; i < v.length - 2; i++)
                sb.append("/").append(v[i]);
            result = sb.toString();
        }
        if (TextUtils.isEmpty(result)) {
//            Log.w(TAG, "failed to get USBFS path, try to use default path:" + name);
            result = "/dev/bus/usb";
        }
        return result;
    }
    /**
     * 升级
     * @param file
     */
    private void startFwUpdata(final File file) {
        loadingView.setVisibility(View.VISIBLE);
        mFwUpDataBtn.setText("正在升级,请勿断开连接");
        Thread thread = new Thread() {
            @Override
@@ -567,6 +464,135 @@
        return errCode;
    }
    public void onProgress(float progress) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mFwUpDataBtn.setText(String.format("Progress: %.4f%%", progress * 100));
            }
        });
    }
    private void upgradeNext() {
        if (upgradeList.isEmpty()) {
            Log.d(TAG, "upgrade complete!");
            mHander.sendEmptyMessage(USB_DEVICE_UPGRADE);
        }
        if (!upgrading && upgradeList.size() > 0) {
            upgrading = true;
            CameraControlTransfer cct = upgradeList.get(0);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    if (!cct.bPermission) {
                        return;
                    }
                    Log.d(TAG,"UpdateCameraInfo->dev" + cct.dev.getDeviceName());
                    boolean bClaim = cct.connection.claimInterface(cct.dev.getInterface(0), true);
                    //devInfo.connection.releaseInterface(devInfo.dev.getInterface(0));
                    Log.d(TAG,"UpdateCameraInfo->bClaim" + String.valueOf(bClaim));
                    Log.d(TAG, "Start init");
                    boolean r = NativeMethods.getInstance().Initialize(cct);
                    if (r) {
                        Log.d(TAG, "Initialise success!");
                        byte data[] = new byte[100];
                        java.util.Arrays.fill(data, (byte) 0);
                        if (NativeMethods.getInstance().GetProduct(data, 100)) {
                            if (data[0] != 0xFF) {
                                String devName = new String(data).trim();
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        mFileFwVersion.setText("Device Name: " + devName + ", " + cct.dev.getDeviceName());
                                    }
                                });
                            }
                        }
                        java.util.Arrays.fill(data, (byte) 0);
                        if (NativeMethods.getInstance().GetFwVersion(data, 100, true)) {
                            if (data[0] != 0xFF) {
                                String fwVersion = new String(data).trim();
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        mDeviceFwVersion.setText("Fireware Name: " + fwVersion);
                                    }
                                });
                            }
                        }
                        final NativeMethods.SERIAL_FLASH_TYPE sft = NativeMethods.SERIAL_FLASH_TYPE.SFT_UNKNOW;
                        if(!NativeMethods.getInstance().GetSerialFlashType(sft, true)){
                            Log.i("test", "GetSerialFlashType failed");
                        }
                        sft.setValue(NativeMethods.SERIAL_FLASH_TYPE.SFT_MXIC.ordinal());
                        Log.i("test", "sft= " + sft.getValue());
                        if(sft.getValue() == 0){
                            //return;
                            Log.i("test", "set sft= " + NativeMethods.SERIAL_FLASH_TYPE.SFT_MXIC.toString());
                            sft.setValue(NativeMethods.SERIAL_FLASH_TYPE.SFT_MXIC.ordinal());
                        }
                        if (mFileList != null && mFileList.length > 0) {
                            try {
                                String path = mFileList[0].getAbsolutePath();
                                NativeMethods.ASIC_ROM_TYPE romType = NativeMethods.ASIC_ROM_TYPE.ART_Unknow;
                                int chipID[] = new int[1];
                                if (!NativeMethods.getInstance().GetAsicRomType(romType, chipID)) {
                                    throw new Exception("get chip rom type failed!");
                                }
                                Log.d("RomType", String.valueOf(chipID[0]));
                                FileInputStream fis = new FileInputStream(path);
                                fis.available();
                                byte[] buffer = new byte[7];
                                if (fis.read(buffer, 0, 7) != -1) {
                                    if (buffer[5] < 48 || buffer[5] >= 65 || buffer[6] < 48 || buffer[6] >= 65) {
                                        throw new Exception("The selected firmware and device do not match!");
                                    }
                                    int id = (buffer[5] - 48) * 16 + (buffer[6] - 48);
                                    if (id != chipID[0]) {
                                        throw new Exception("The selected firmware and device do not match!");
                                    }
                                }
                                Log.d(TAG, "BurnFw start...");
                                if (!NativeMethods.getInstance().BurnerFW(HomePageActivity.this, path, sft, true)) {
                                    mUpgradeFailNum++;
                                    Log.d(TAG, "BurnFw fail!!!");
                                } else {
                                    mUpgradeSuccessNum++;
                                    Log.d(TAG, "BurnFw success!!!");
                                }
                                fis.close();
                                SystemClock.sleep(500);
                                NativeMethods.getInstance().RestartDevice();
                            } catch (Exception ex) {
                                Log.e(TAG, "upgrade fail: " + ex.getMessage());
                            }
                        } else {
                            Log.d(TAG, "upgrade file is empty!");
                        }
                        NativeMethods.getInstance().UnInitialize();
                    }
                    upgradeList.remove(cct);
                    upgrading = false;
                    SystemClock.sleep(1000);
                    upgradeNext();
                }
            }).start();
        }
    }
    // -----------------------------------------------权限申请 相关------------------------------------------
    /**
app/src/main/java/com/fwupgrade/saymanss/deviceplug/CDeviceFilter.java
New file
@@ -0,0 +1,260 @@
package com.fwupgrade.saymanss.deviceplug;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbInterface;
import android.text.TextUtils;
import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class CDeviceFilter {
    private static final String TAG = "CDeviceFilter";
    public final int mVendorId;
    public final int mProductId;
    public final int mClass;
    public final int mSubclass;
    public final int mProtocol;
    public final String mManufacturerName;
    public final String mProductName;
    public final String mSerialNumber;
    public CDeviceFilter(int vid, int pid, int clasz, int subclass, int protocol, String manufacturer, String product, String serialnum) {
        this.mVendorId = vid;
        this.mProductId = pid;
        this.mClass = clasz;
        this.mSubclass = subclass;
        this.mProtocol = protocol;
        this.mManufacturerName = manufacturer;
        this.mProductName = product;
        this.mSerialNumber = serialnum;
    }
    public CDeviceFilter(UsbDevice device) {
        this.mVendorId = device.getVendorId();
        this.mProductId = device.getProductId();
        this.mClass = device.getDeviceClass();
        this.mSubclass = device.getDeviceSubclass();
        this.mProtocol = device.getDeviceProtocol();
        this.mManufacturerName = null;
        this.mProductName = null;
        this.mSerialNumber = null;
    }
    public static List<CDeviceFilter> getDeviceFilters(Context context, int deviceFilterXmlId) {
        XmlResourceParser xmlResourceParser = context.getResources().getXml(deviceFilterXmlId);
        List<CDeviceFilter> deviceFilters = new ArrayList<>();
        try {
            int eventType = xmlResourceParser.getEventType();
            while (eventType != 1) {
                if (eventType == 2) {
                    CDeviceFilter deviceFilter = read(context, (XmlPullParser)xmlResourceParser);
                    if (deviceFilter != null)
                        deviceFilters.add(deviceFilter);
                }
                eventType = xmlResourceParser.next();
            }
        } catch (XmlPullParserException e) {
            Log.d("CDeviceFilter", "XmlPullParserException", (Throwable)e);
        } catch (IOException e) {
            Log.d("CDeviceFilter", "IOException", e);
        }
        return Collections.unmodifiableList(deviceFilters);
    }
    private static final int getAttributeInteger(Context context, XmlPullParser parser, String namespace, String name, int defaultValue) {
        int result = defaultValue;
        try {
            String v = parser.getAttributeValue(namespace, name);
            if (!TextUtils.isEmpty(v) && v.startsWith("@")) {
                String r = v.substring(1);
                int resId = context.getResources().getIdentifier(r, null, context.getPackageName());
                if (resId > 0)
                    result = context.getResources().getInteger(resId);
            } else {
                int radix = 10;
                if (v != null && v.length() > 2 && v.charAt(0) == '0' && (v
                        .charAt(1) == 'x' || v.charAt(1) == 'X')) {
                    radix = 16;
                    v = v.substring(2);
                }
                result = Integer.parseInt(v, radix);
            }
        } catch (Resources.NotFoundException e) {
            result = defaultValue;
        } catch (NumberFormatException e) {
            result = defaultValue;
        } catch (NullPointerException e) {
            result = defaultValue;
        }
        return result;
    }
    private static final String getAttributeString(Context context, XmlPullParser parser, String namespace, String name, String defaultValue) {
        String result = defaultValue;
        try {
            result = parser.getAttributeValue(namespace, name);
            if (result == null)
                result = defaultValue;
            if (!TextUtils.isEmpty(result) && result.startsWith("@")) {
                String r = result.substring(1);
                int resId = context.getResources().getIdentifier(r, null, context.getPackageName());
                if (resId > 0)
                    result = context.getResources().getString(resId);
            }
        } catch (Resources.NotFoundException e) {
            result = defaultValue;
        } catch (NumberFormatException e) {
            result = defaultValue;
        } catch (NullPointerException e) {
            result = defaultValue;
        }
        return result;
    }
    public static CDeviceFilter read(Context context, XmlPullParser parser) throws XmlPullParserException, IOException {
        int vendorId = -1;
        int productId = -1;
        int deviceClass = -1;
        int deviceSubclass = -1;
        int deviceProtocol = -1;
        String manufacturerName = null;
        String productName = null;
        String serialNumber = null;
        boolean hasValue = false;
        int eventType = parser.getEventType();
        while (eventType != 1) {
            String tag = parser.getName();
            if (!TextUtils.isEmpty(tag) && tag.equalsIgnoreCase("usb-device"))
                if (eventType == 2) {
                    hasValue = true;
                    vendorId = getAttributeInteger(context, parser, null, "vendor-id", -1);
                    if (vendorId == -1) {
                        vendorId = getAttributeInteger(context, parser, null, "vendorId", -1);
                        if (vendorId == -1)
                            vendorId = getAttributeInteger(context, parser, null, "venderId", -1);
                    }
                    productId = getAttributeInteger(context, parser, null, "product-id", -1);
                    if (productId == -1)
                        productId = getAttributeInteger(context, parser, null, "productId", -1);
                    deviceClass = getAttributeInteger(context, parser, null, "class", -1);
                    deviceSubclass = getAttributeInteger(context, parser, null, "subclass", -1);
                    deviceProtocol = getAttributeInteger(context, parser, null, "protocol", -1);
                    manufacturerName = getAttributeString(context, parser, null, "manufacturer-name", null);
                    if (TextUtils.isEmpty(manufacturerName))
                        manufacturerName = getAttributeString(context, parser, null, "manufacture", null);
                    productName = getAttributeString(context, parser, null, "product-name", null);
                    if (TextUtils.isEmpty(productName))
                        productName = getAttributeString(context, parser, null, "product", null);
                    serialNumber = getAttributeString(context, parser, null, "serial-number", null);
                    if (TextUtils.isEmpty(serialNumber))
                        serialNumber = getAttributeString(context, parser, null, "serial", null);
                } else if (eventType == 3 &&
                        hasValue) {
                    return new CDeviceFilter(vendorId, productId, deviceClass, deviceSubclass, deviceProtocol, manufacturerName, productName, serialNumber);
                }
            eventType = parser.next();
        }
        return null;
    }
    private boolean matches(int clasz, int subclass, int protocol) {
        return ((this.mClass == -1 || clasz == this.mClass) && (this.mSubclass == -1 || subclass == this.mSubclass) && (this.mProtocol == -1 || protocol == this.mProtocol));
    }
    public boolean matches(UsbDevice device) {
        if (this.mVendorId != -1 && device.getVendorId() != this.mVendorId)
            return false;
        if (this.mProductId != -1 && device.getProductId() != this.mProductId)
            return false;
        if (matches(device.getDeviceClass(), device.getDeviceSubclass(), device
                .getDeviceProtocol()))
            return true;
        int count = device.getInterfaceCount();
        for (int i = 0; i < count; i++) {
            UsbInterface intf = device.getInterface(i);
            if (matches(intf.getInterfaceClass(), intf.getInterfaceSubclass(), intf
                    .getInterfaceProtocol()))
                return true;
        }
        return false;
    }
    public boolean matches(CDeviceFilter f) {
        if (this.mVendorId != -1 && f.mVendorId != this.mVendorId)
            return false;
        if (this.mProductId != -1 && f.mProductId != this.mProductId)
            return false;
        if (f.mManufacturerName != null && this.mManufacturerName == null)
            return false;
        if (f.mProductName != null && this.mProductName == null)
            return false;
        if (f.mSerialNumber != null && this.mSerialNumber == null)
            return false;
        if (this.mManufacturerName != null && f.mManufacturerName != null &&
                !this.mManufacturerName.equals(f.mManufacturerName))
            return false;
        if (this.mProductName != null && f.mProductName != null &&
                !this.mProductName.equals(f.mProductName))
            return false;
        if (this.mSerialNumber != null && f.mSerialNumber != null &&
                !this.mSerialNumber.equals(f.mSerialNumber))
            return false;
        return matches(f.mClass, f.mSubclass, f.mProtocol);
    }
    public boolean equals(Object obj) {
        if (this.mVendorId == -1 || this.mProductId == -1 || this.mClass == -1 || this.mSubclass == -1 || this.mProtocol == -1)
            return false;
        if (obj instanceof CDeviceFilter) {
            CDeviceFilter filter = (CDeviceFilter)obj;
            if (filter.mVendorId != this.mVendorId || filter.mProductId != this.mProductId || filter.mClass != this.mClass || filter.mSubclass != this.mSubclass || filter.mProtocol != this.mProtocol)
                return false;
            if ((filter.mManufacturerName != null && this.mManufacturerName == null) || (filter.mManufacturerName == null && this.mManufacturerName != null) || (filter.mProductName != null && this.mProductName == null) || (filter.mProductName == null && this.mProductName != null) || (filter.mSerialNumber != null && this.mSerialNumber == null) || (filter.mSerialNumber == null && this.mSerialNumber != null))
                return false;
            if ((filter.mManufacturerName != null && this.mManufacturerName != null &&
                    !this.mManufacturerName.equals(filter.mManufacturerName)) || (filter.mProductName != null && this.mProductName != null &&
                    !this.mProductName.equals(filter.mProductName)) || (filter.mSerialNumber != null && this.mSerialNumber != null &&
                    !this.mSerialNumber.equals(filter.mSerialNumber)))
                return false;
            return true;
        }
        if (obj instanceof UsbDevice) {
            UsbDevice device = (UsbDevice)obj;
            if (device.getVendorId() != this.mVendorId || device
                    .getProductId() != this.mProductId || device
                    .getDeviceClass() != this.mClass || device
                    .getDeviceSubclass() != this.mSubclass || device
                    .getDeviceProtocol() != this.mProtocol)
                return false;
            return true;
        }
        return false;
    }
    public int hashCode() {
        return (this.mVendorId << 16 | this.mProductId) ^ (this.mClass << 16 | this.mSubclass << 8 | this.mProtocol);
    }
    public String toString() {
        return "DeviceFilter[mVendorId=" + this.mVendorId + ",mProductId=" + this.mProductId + ",mClass=" + this.mClass + ",mSubclass=" + this.mSubclass + ",mProtocol=" + this.mProtocol + ",mManufacturerName=" + this.mManufacturerName + ",mProductName=" + this.mProductName + ",mSerialNumber=" + this.mSerialNumber + "]";
    }
}
app/src/main/java/com/fwupgrade/saymanss/deviceplug/CUSBListener.java
New file
@@ -0,0 +1,426 @@
package com.fwupgrade.saymanss.deviceplug;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public final class CUSBListener {
    private static final boolean DEBUG = false;
    private static final String TAG = "USBListener";
    private static final String ACTION_USB_PERMISSION_BASE = "com.spca.USB_PERMISSION.";
    private final String ACTION_USB_PERMISSION = "com.spca.USB_PERMISSION." + hashCode();
    public static final String ACTION_USB_DEVICE_ATTACHED = "android.hardware.usb.action.USB_DEVICE_ATTACHED";
    private final ConcurrentHashMap<UsbDevice, UsbControlBlock> mCtrlBlocks = new ConcurrentHashMap<>();
    private final WeakReference<Context> mWeakContext;
    private final UsbManager mUsbManager;
    private final OnDeviceConnectListener mOnDeviceConnectListener;
    private PendingIntent mPermissionIntent = null;
    private List<CDeviceFilter> mDeviceFilters = new ArrayList<>();
    private final Handler mHandler = new Handler();
    private final BroadcastReceiver mUsbReceiver;
    private volatile int mDeviceCounts;
    private final Runnable mDeviceCheckRunnable;
    public void destroy() {
        unregister();
        Set<UsbDevice> keys = this.mCtrlBlocks.keySet();
        if (keys != null) {
            try {
                for (UsbDevice key : keys) {
                    UsbControlBlock ctrlBlock = this.mCtrlBlocks.remove(key);
                    ctrlBlock.close();
                }
            } catch (Exception e) {
                Log.e("USBListener", "destroy:", e);
            }
            this.mCtrlBlocks.clear();
        }
    }
    public synchronized void register() {
        if (this.mPermissionIntent == null) {
            Context context = this.mWeakContext.get();
            if (context != null) {
                this.mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(this.ACTION_USB_PERMISSION), 0);
                //this.mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent("com.android.example.USB_PERMISSION"), 0);
                IntentFilter filter = new IntentFilter(this.ACTION_USB_PERMISSION);
                //filter.addAction("android.hardware.usb.action.USB_DEVICE_ATTACHED");
                filter.addAction("android.hardware.usb.action.USB_DEVICE_DETACHED");
                context.registerReceiver(this.mUsbReceiver, filter);
            }
            this.mDeviceCounts = 0;
//            this.mHandler.postDelayed(this.mDeviceCheckRunnable, 1000L);
        }
    }
    public synchronized void unregister() {
        if (this.mPermissionIntent != null) {
            Context context = this.mWeakContext.get();
            if (context != null)
                context.unregisterReceiver(this.mUsbReceiver);
            this.mPermissionIntent = null;
        }
        this.mDeviceCounts = 0;
        this.mHandler.removeCallbacks(this.mDeviceCheckRunnable);
    }
    public synchronized boolean isRegistered() {
        return (this.mPermissionIntent != null);
    }
    public void setDeviceFilter(CDeviceFilter filter) {
        this.mDeviceFilters.clear();
        this.mDeviceFilters.add(filter);
    }
    public void setDeviceFilter(List<CDeviceFilter> filters) {
        this.mDeviceFilters.clear();
        this.mDeviceFilters.addAll(filters);
    }
    public int getDeviceCount() {
        return getDeviceList().size();
    }
    public List<UsbDevice> getDeviceList() {
        return getDeviceList(this.mDeviceFilters);
    }
    public List<UsbDevice> getDeviceList(List<CDeviceFilter> filters) {
        HashMap<String, UsbDevice> deviceList = this.mUsbManager.getDeviceList();
        List<UsbDevice> result = new ArrayList<>();
        if (deviceList != null)
            if (filters == null || filters.isEmpty()) {
                result.addAll(deviceList.values());
            } else {
                Iterator<UsbDevice> iterator = deviceList.values().iterator();
                while (iterator.hasNext()) {
                    UsbDevice device = iterator.next();
                    label19: for (CDeviceFilter filter : filters) {
                        if (filter != null) {
                            if (filter.matches(device))
                                break label19;
                            continue;
                        }
                        result.add(device);
                    }
                }
            }
        return result;
    }
    public List<UsbDevice> getDeviceList(CDeviceFilter filter) {
        HashMap<String, UsbDevice> deviceList = this.mUsbManager.getDeviceList();
        List<UsbDevice> result = new ArrayList<>();
        if (deviceList != null) {
            Iterator<UsbDevice> iterator = deviceList.values().iterator();
            while (iterator.hasNext()) {
                UsbDevice device = iterator.next();
                if (filter == null || filter.matches(device))
                    result.add(device);
            }
        }
        return result;
    }
    public Iterator<UsbDevice> getDevices() {
        Iterator<UsbDevice> iterator = null;
        HashMap<String, UsbDevice> list = this.mUsbManager.getDeviceList();
        if (list != null)
            iterator = list.values().iterator();
        return iterator;
    }
    public boolean hasPermission(UsbDevice device) {
        return (device != null && this.mUsbManager.hasPermission(device));
    }
    public synchronized void requestPermission(UsbDevice device) {
        if (this.mPermissionIntent != null) {
            if (device != null) {
                if (this.mUsbManager.hasPermission(device)) {
                    procConnect(device);
                } else {
                    this.mUsbManager.requestPermission(device, this.mPermissionIntent);
                }
            } else {
                procCancel(device);
            }
        } else {
            procCancel(device);
        }
    }
    public CUSBListener(Context context, OnDeviceConnectListener listener) {
        this.mUsbReceiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (CUSBListener.this.ACTION_USB_PERMISSION.equals(action)) {
                    Log.d(TAG, "ACTION_USB_PERMISSION");
                    synchronized (CUSBListener.this) {
                        UsbDevice device = (UsbDevice)intent.getParcelableExtra("device");
                        if (intent.getBooleanExtra("permission", false)) {
                            if (device != null)
                                CUSBListener.this.procConnect(device);
                        } else {
                            CUSBListener.this.procCancel(device);
                        }
                    }
                } else if ("android.hardware.usb.action.USB_DEVICE_ATTACHED".equals(action)) {
                    Log.d(TAG, "android.hardware.usb.action.USB_DEVICE_ATTACHED");
                    UsbDevice device = (UsbDevice)intent.getParcelableExtra("device");
                    CUSBListener.this.procAttach(device);
                } else if ("android.hardware.usb.action.USB_DEVICE_DETACHED".equals(action)) {
                    Log.d(TAG, "android.hardware.usb.action.USB_DEVICE_DETACHED");
                    UsbDevice device = (UsbDevice)intent.getParcelableExtra("device");
                    if (device != null) {
                        UsbControlBlock ctrlBlock = null;
                        ctrlBlock = (UsbControlBlock)CUSBListener.this.mCtrlBlocks.remove(device);
                        if (ctrlBlock != null)
                            ctrlBlock.close();
                        CUSBListener.this.mDeviceCounts = 0;
                        CUSBListener.this.procDettach(device);
                    }
                }
            }
        };
        this.mDeviceCounts = 0;
        this.mDeviceCheckRunnable = new Runnable() {
            public void run() {
                int n = CUSBListener.this.getDeviceCount();
                if (n != CUSBListener.this.mDeviceCounts &&
                        n > CUSBListener.this.mDeviceCounts) {
                    CUSBListener.this.mDeviceCounts = n;
                    if (CUSBListener.this.mOnDeviceConnectListener != null) {
                        Log.d(TAG, "onAttach empty");
                        CUSBListener.this.mOnDeviceConnectListener.onAttach(null);
                    }
                }
                CUSBListener.this.mHandler.postDelayed(this, 2000L);
            }
        };
        this.mWeakContext = new WeakReference<>(context);
        this.mUsbManager = (UsbManager)context.getSystemService("usb");
        this.mOnDeviceConnectListener = listener;
    }
    private final void procConnect(final UsbDevice device) {
        this.mHandler.post(new Runnable() {
            public void run() {
                boolean createNew;
                UsbControlBlock ctrlBlock = (UsbControlBlock)CUSBListener.this.mCtrlBlocks.get(device);
                if (ctrlBlock == null) {
                    ctrlBlock = new UsbControlBlock(CUSBListener.this, device);
                    CUSBListener.this.mCtrlBlocks.put(device, ctrlBlock);
                    createNew = true;
                } else {
                    createNew = false;
                }
                if (CUSBListener.this.mOnDeviceConnectListener != null) {
                    UsbControlBlock ctrlB = ctrlBlock;
                    CUSBListener.this.mOnDeviceConnectListener.onConnect(device, ctrlB, createNew);
                }
            }
        });
    }
    private final void procCancel(UsbDevice device) {
        if (this.mOnDeviceConnectListener != null)
            this.mHandler.post(new Runnable() {
                public void run() {
                    CUSBListener.this.mOnDeviceConnectListener.onCancel();
                }
            });
    }
    private final void procAttach(final UsbDevice device) {
        if (this.mOnDeviceConnectListener != null)
            this.mHandler.post(new Runnable() {
                public void run() {
                    Log.d(TAG, "procAttach");
                    CUSBListener.this.mOnDeviceConnectListener.onAttach(device);
                }
            });
    }
    private final void procDettach(final UsbDevice device) {
        if (this.mOnDeviceConnectListener != null)
            this.mHandler.post(new Runnable() {
                public void run() {
                    CUSBListener.this.mOnDeviceConnectListener.onDettach(device);
                }
            });
    }
    public static interface OnDeviceConnectListener {
        void onAttach(UsbDevice param1UsbDevice);
        void onDettach(UsbDevice param1UsbDevice);
        void onConnect(UsbDevice param1UsbDevice, UsbControlBlock param1UsbControlBlock, boolean param1Boolean);
        void onDisconnect(UsbDevice param1UsbDevice, UsbControlBlock param1UsbControlBlock);
        void onCancel();
    }
    public static final class UsbControlBlock {
        private final WeakReference<CUSBListener> mWeakMonitor;
        private final WeakReference<UsbDevice> mWeakDevice;
        protected UsbDeviceConnection mConnection;
        private final int mBusNum;
        private final int mDevNum;
        private final SparseArray<UsbInterface> mInterfaces = new SparseArray();
        public UsbControlBlock(CUSBListener listener, UsbDevice device) {
            this.mWeakMonitor = new WeakReference<>(listener);
            this.mWeakDevice = new WeakReference<>(device);
            this.mConnection = listener.mUsbManager.openDevice(device);
            String name = device.getDeviceName();
            String[] v = !TextUtils.isEmpty(name) ? name.split("/") : null;
            int busnum = 0;
            int devnum = 0;
            if (v != null) {
                busnum = Integer.parseInt(v[v.length - 2]);
                devnum = Integer.parseInt(v[v.length - 1]);
            }
            this.mBusNum = busnum;
            this.mDevNum = devnum;
            if (this.mConnection == null)
                Log.e("USBListener", "could not connect to device " + name);
        }
        public UsbDevice getDevice() {
            return this.mWeakDevice.get();
        }
        public String getDeviceName() {
            UsbDevice device = this.mWeakDevice.get();
            return (device != null) ? device.getDeviceName() : "";
        }
        public UsbDeviceConnection getUsbDeviceConnection() {
            return this.mConnection;
        }
        public synchronized int getFileDescriptor() {
            return (this.mConnection != null) ? this.mConnection.getFileDescriptor() : -1;
        }
        public byte[] getRawDescriptors() {
            return (this.mConnection != null) ? this.mConnection.getRawDescriptors() : null;
        }
        public int getVenderId() {
            UsbDevice device = this.mWeakDevice.get();
            return (device != null) ? device.getVendorId() : 0;
        }
        public int getProductId() {
            UsbDevice device = this.mWeakDevice.get();
            return (device != null) ? device.getProductId() : 0;
        }
        public int getBcdDevice() {
            byte[] descriptor = this.mConnection.getRawDescriptors();
            int bcd = descriptor[13] << 8 | descriptor[12];
            return bcd;
        }
        public synchronized String getSerial() {
            return (this.mConnection != null) ? this.mConnection.getSerial() : null;
        }
        public int getBusNum() {
            return this.mBusNum;
        }
        public int getDevNum() {
            return this.mDevNum;
        }
        public synchronized UsbInterface open(int interfaceIndex) {
            UsbDevice device = this.mWeakDevice.get();
            UsbInterface intf = null;
            intf = (UsbInterface)this.mInterfaces.get(interfaceIndex);
            if (intf == null) {
                intf = device.getInterface(interfaceIndex);
                if (intf != null)
                    synchronized (this.mInterfaces) {
                        this.mInterfaces.append(interfaceIndex, intf);
                    }
            }
            return intf;
        }
        public void close(int interfaceIndex) {
            UsbInterface intf = null;
            synchronized (this.mInterfaces) {
                intf = (UsbInterface)this.mInterfaces.get(interfaceIndex);
                if (intf != null) {
                    this.mInterfaces.delete(interfaceIndex);
                    this.mConnection.releaseInterface(intf);
                }
            }
        }
        public synchronized void close() {
            if (this.mConnection != null) {
                int n = this.mInterfaces.size();
                for (int i = 0; i < n; i++) {
                    int key = this.mInterfaces.keyAt(i);
                    UsbInterface intf = (UsbInterface)this.mInterfaces.get(key);
                    this.mConnection.releaseInterface(intf);
                }
                this.mConnection.close();
                this.mConnection = null;
                CUSBListener listener = this.mWeakMonitor.get();
                if (listener != null) {
                    if (listener.mOnDeviceConnectListener != null) {
                        UsbDevice device = this.mWeakDevice.get();
                        listener.mOnDeviceConnectListener.onDisconnect(device, this);
                    }
                    listener.mCtrlBlocks.remove(getDevice());
                }
            }
        }
    }
}
app/src/main/java/com/fwupgrade/saymanss/deviceplug/CameraControlTransfer.java
New file
@@ -0,0 +1,33 @@
package com.fwupgrade.saymanss.deviceplug;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
public class CameraControlTransfer {
    public CUSBListener usbListener;
    public UsbDevice dev;
    public boolean bPermission;
    public int vid;
    public int pid;
    public int fd;
    public int busnum;
    public int devaddr;
    public String usbFSName;
    public UsbDeviceConnection connection;
    private int controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)
    {
        try {
            if(connection != null){
                int ret = connection.controlTransfer(requestType, request, value, index, buffer, length, timeout);
                return ret;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return -1;
    }
}
app/src/main/java/com/fwupgrade/saymanss/deviceplug/IUsbDevicePlugDelegate.java
@@ -1,9 +1,5 @@
package com.fwupgrade.saymanss.deviceplug;
import android.hardware.usb.UsbDevice;
import com.spca.usb.CUSBListener;
/**
 * Created by Administrator on 2019/4/6.
 */
@@ -18,7 +14,7 @@
    /**
     * 权限申请
     */
    void permissionFinish(boolean isSuccessful, CUSBListener.UsbControlBlock ctrlBlock);
    void permissionFinish(boolean isSuccessful, CUSBListener.UsbControlBlock ctrlBlock, CameraControlTransfer cct);
    /**
     * 检测usb设备拔出
app/src/main/java/com/fwupgrade/saymanss/deviceplug/UstorageDeviceInstance.java
@@ -1,52 +1,34 @@
package com.fwupgrade.saymanss.deviceplug;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.SystemClock;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Log;
import com.spca.usb.CUSBListener;
import com.spca.usb.SpcaJNI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static android.content.Context.USB_SERVICE;
/**
 * Created by Wangj on 2016/10/25.
 */
public class UstorageDeviceInstance {
    private static String TAG = UstorageDeviceInstance.class.getSimpleName();
    private static UstorageDeviceInstance instance;
    private static Lock mLock= new ReentrantLock();
    public static final String ACTION_USB_PERMISSION = "wfd.action.USB_PERMISSION";
    private UsbManager mUsbManager;
    private PendingIntent mPermissionIntent;
    private CUSBListener mUSBListener;
    private Context g_cotext_;
    private ArrayList<CameraControlTransfer> curDevListArray;
    public ArrayList<CameraControlTransfer> devListArray;
    /** 设备发现回掉 */
    private IUsbDevicePlugDelegate iUsbDevicePlugDelegate;
    private UstorageDeviceInstance() {
    }
    public static UstorageDeviceInstance getInstance() {
        if (instance == null) {
@@ -59,87 +41,125 @@
        return instance;
    }
    UstorageDeviceInstance() {
        devListArray = new ArrayList<CameraControlTransfer>();
        curDevListArray = new ArrayList<CameraControlTransfer>();
    }
     final String getUSBFSName(final CUSBListener.UsbControlBlock ctrlBlock) {
        String result = null;
        final String name = ctrlBlock.getDeviceName();
        final String[] v = !TextUtils.isEmpty(name) ? name.split("/") : null;
        if ((v != null) && (v.length > 2)) {
            final StringBuilder sb = new StringBuilder(v[0]);
            for (int i = 1; i < v.length - 2; i++)
                sb.append("/").append(v[i]);
            result = sb.toString();
        }
        if (TextUtils.isEmpty(result)) {
            result = "/dev/bus/usb";
        }
        return result;
    }
    /**
     * 尝试是否有连接设备(OTG)
     */
    public int tryAttcheDeviceHandle(Context context, IUsbDevicePlugDelegate iUsbDevicePlugDelegate) {
        Log.d("fwup","tryAttcheDeviceHandle: ");
    public void tryAttcheDeviceHandle(Context context, IUsbDevicePlugDelegate iUsbDevicePlugDelegate) {
        this.iUsbDevicePlugDelegate = iUsbDevicePlugDelegate;
        mUsbManager = (UsbManager) context.getSystemService(USB_SERVICE);
       /* Object deviceInfo = null;
        devListArray.clear();
        curDevListArray.clear();
        if (null != (deviceInfo = acceptOTGDeviceInfo(mUsbManager))) {
            //满足 即当前存在OTG设备插入  OTG设备类型
//            initOTGDeviceModule(context, (UsbDevice) deviceInfo);
            acceptLicense(context, deviceInfo);
        }*/
        g_cotext_ = context;
//        //拿到OTG设备列表
        HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
        Log.d("deviceList", String.valueOf(deviceList.size()));
        for (UsbDevice usbDevice : deviceList.values()) {
            Log.i("Start",  String.valueOf(usbDevice.getProductName()));
            Boolean find = false;
            for (int i = 0; i < curDevListArray.size(); i++) {
                if(usbDevice.equals(curDevListArray.get(i))){
                    find= true;
                    Log.e("ERROR", "find device");
                    Log.e("ERROR",  String.valueOf(usbDevice.getDeviceClass()));
                    Log.e("ERROR",  String.valueOf(usbDevice.getDeviceName()));
                    Log.e("ERROR",  String.valueOf(usbDevice.getProductName()));
                    continue;
                }
            }
            if(usbDevice.getDeviceClass() != 0xEF) {
                Log.e("ERROR", "getDeviceClass!=0xEF");
                Log.e("ERROR",  String.valueOf(usbDevice.getDeviceClass()));
                Log.e("ERROR",  String.valueOf(usbDevice.getDeviceName()));
                Log.e("ERROR",  String.valueOf(usbDevice.getProductName()));
               continue;
            }
            if(!find){
//                if(usbDevice.getVendorId() != 0x0581 || usbDevice.getProductId() != 0x0b20){
//                    continue;
//                }
        ArrayList<UsbDevice> devices = acceptOTGDeviceInfo(mUsbManager);
        if (devices==null || devices.size()==0){
            Log.i("fwup","devices==null");
            return 1;
//                Log.d("usbDevice", String.valueOf(usbDevice.toString()));
//                Log.d("getDeviceSubclass", String.valueOf(usbDevice.getDeviceSubclass()));
                Log.d("devName", usbDevice.getDeviceName());
                Log.d("proName", usbDevice.getProductName());
                Log.d("vid", String.valueOf(usbDevice.getVendorId()));
                Log.d("pid", String.valueOf(usbDevice.getProductId()));
                CameraControlTransfer infos = new CameraControlTransfer();
                infos.dev = usbDevice;
                infos.bPermission = false;
                try {
                    infos.usbListener = mUSBListener;
                    mUSBListener = new CUSBListener(context, mOnDeviceConnectListener);
                    mUSBListener.register();
                    mUSBListener.requestPermission(usbDevice);
                }catch (Exception e) {
                    e.printStackTrace();
        }
        for (UsbDevice dev: devices) {
            acceptLicense(context, dev);
                curDevListArray.add(infos);
                Log.d(TAG, "curDevListArraySize: " + curDevListArray.size());
        }
        return 0;
        }
    }
    public int tryAgain(Context context){
        mUsbManager = (UsbManager) context.getSystemService(USB_SERVICE);
       /* Object deviceInfo = null;
        if (null != (deviceInfo = acceptOTGDeviceInfo(mUsbManager))) {
            //满足 即当前存在OTG设备插入  OTG设备类型
//            initOTGDeviceModule(context, (UsbDevice) deviceInfo);
            acceptLicense(context, deviceInfo);
        }*/
        ArrayList<UsbDevice> devices = acceptOTGDeviceInfo(mUsbManager);
        if (devices==null || devices.size()==0){
            Log.i("fwup","tryAgain devices==null");
            return 1;
    public boolean startAcceptLicense(int position, Context context, Object deviceInfo) {
        if(devListArray.get(position).usbListener.hasPermission((UsbDevice)deviceInfo)){
            return true;
        }
        for (UsbDevice dev: devices) {
            acceptLicense(context, dev);
        try {
            devListArray.get(position).usbListener.requestPermission((UsbDevice) deviceInfo);
            mUsbManager.openDevice((UsbDevice) deviceInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
        return false;
    }
    //<<<--------------------------------------- Usb 相关处理--------------------------------------------
    /**
     * 获取符合信息的OTG设备
     * @param usbManager
     */
    public ArrayList<UsbDevice> acceptOTGDeviceInfo(UsbManager usbManager) {
//        UsbDevice device = null;
        ArrayList<UsbDevice> devices = new ArrayList<>();
    private UsbDevice acceptOTGDeviceInfo(Context context, UsbManager usbManager) {
        UsbDevice device = null;
        //拿到OTG设备列表
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        if (deviceList==null || deviceList.size()==0){
            Log.d("fwup","deviceList为空 ");
        }
        for (UsbDevice usbDevice : deviceList.values()) {
            int productId = usbDevice.getProductId();
//            if (productId != 36940) {
//                device = usbDevice; // 可以增加厂商 版本等判断
//                break;
//            }
            int vendorId = usbDevice.getVendorId();
            Log.d("fwup","vendorId: " + vendorId);
            if (vendorId == 3141) {
//                device = usbDevice; // 可以增加厂商 版本等判断
                devices.add(usbDevice);
            if (vendorId == 0x0c45) {
                device = usbDevice;
                break;
            }
        }
        return devices;
        return device;
    }
    CUSBListener mUSBListener;
    private SpcaJNI mSpcaJNI;
    private void acceptLicense(Context context, Object deviceInfo) {
        try {
@@ -149,16 +169,16 @@
            UsbDevice usbDevice = (UsbDevice) deviceInfo;
            Log.d("fwup", "acceptLicense:" + usbDevice.getDeviceName());
            // request permission [frank.chang 7/25/2018]
            mUSBListener.requestPermission((UsbDevice)usbDevice);
            // open the device [frank.chang 7/25/2018]
//            mUsbManager.openDevice((UsbDevice)usbDevice);
            mUsbManager.openDevice((UsbDevice)usbDevice);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // implement OnDeviceConnectListener
    private final CUSBListener.OnDeviceConnectListener mOnDeviceConnectListener = new CUSBListener.OnDeviceConnectListener() {
@@ -169,23 +189,48 @@
        @Override
        public void onConnect(final UsbDevice device, final CUSBListener.UsbControlBlock ctrlBlock, final boolean createNew) {
            iUsbDevicePlugDelegate.permissionFinish(true, ctrlBlock);
            for (int i = 0; i < curDevListArray.size(); i++) {
                if(device.equals(curDevListArray.get(i).dev)){
                    Log.d(TAG, "Get Permission:" + device.getDeviceName());
                    CameraControlTransfer cct = curDevListArray.get(i);
                    cct.bPermission = true;
                    cct.connection = ctrlBlock.mConnection;
                    String fsName = new String();
                    fsName = ctrlBlock.getDeviceName();;
                    cct.usbFSName = fsName;
                    cct.fd = ctrlBlock.getFileDescriptor();
                    mUsbManager.openDevice(device);
                    devListArray.add(cct);
//                    int a = ctrlBlock.getBusNum();
//                    int b = ctrlBlock.getDevNum();
                    iUsbDevicePlugDelegate.permissionFinish(true, ctrlBlock, cct);
                    break;
                }
            }
//            iUsbDevicePlugDelegate.permissionFinish(true, ctrlBlock);
        }
        @Override
        public void onDisconnect(final UsbDevice device, final CUSBListener.UsbControlBlock ctrlBlock) {
            if (mSpcaJNI != null) {
                mSpcaJNI.close();
            }
        }
        @Override
        public void onDettach(final UsbDevice device) {
            for (int i = 0; i < devListArray.size(); i++) {
                if(device.equals(device)){
                    devListArray.remove(i);
                    break;
                }
            }
            iUsbDevicePlugDelegate.usbDeviceDetached();
        }
        @Override
        public void onCancel() {
        }
    };
}
app/src/main/java/com/jni/NativeMethods.java
New file
@@ -0,0 +1,299 @@
package com.jni;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class NativeMethods {
    public enum SERIAL_FLASH_TYPE {
        SFT_UNKNOW(0),
        SFT_MXIC(1),
        SFT_ST(2),
        SFT_SST(3),
        SFT_ATMEL_AT25F(4),
        SFT_ATMEL_AT25FS(5),
        SFT_ATMEL_AT45DB(6),
        SFT_WINBOND(7),
        SFT_PMC(8),
        SFT_MXIC_LIKE(9),
        SFT_AMIC(10),
        SFT_EON(11),
        SF_ESMT(12),
        SFT_GIGA(13),
        SFT_FENTECH(14),
        SFT_UC(15),             //SFT_UCUNDATA
        SFT_BY(16),
        SFT_FM(17),
        SFT_ZB(18);
        private int value;
        private String name;
        private SERIAL_FLASH_TYPE(int value) {
            this.value = value;
        }
        public int getValue() {
            return value;
        }
        public String getName() {
            return name;
        }
        public void setValue(int value){
            this.value = value;
        }
    }
    public enum ASIC_ROM_TYPE {
        ART_Unknow(-1),
        ART_32K(0),
        ART_64K(1),
        ART_128K(2),
        ART_256K(3);
        private int value;
        private ASIC_ROM_TYPE(int value) {
            this.value = value;
        }
        public int getValue() {
            return value;
        }
        private void setValue(int value){
            this.value = value;
        }
    }
    public class ChangeParamInfo
    {
        public int SerialNumberLength;      //SerialNumberLength = 6
        public int ProductLength;
        public int ManufactureLength;
        public int VidPidLength;            //VidPidLength = 8
        public int InterfaceLength;
        public int String3Length;
        public String strSerialNumber;      //Sample, strSerialNumber = "SN0001"
        public String strProduct;
        public String strManufacture;
        public String strVidPid;            //Sample, strVidPid="0c356362"
        public String strString3;
        public String strInterface;
    }
    static {
        //NativeMethods path = /com/jni/NativeMethods
        System.loadLibrary("SonixCamera");
    }
    private static NativeMethods instance;
    private static Lock mLock = new ReentrantLock();
    public static NativeMethods getInstance() {
        if (instance == null) {
            mLock.lock();
            if (instance == null) {
                instance = new NativeMethods();
            }
            mLock.unlock();
        }
        return instance;
    }
    private Object mCtrlTransferClass;
    public boolean Initialize(Object ctrlTransferClass) {
        this.mCtrlTransferClass = ctrlTransferClass;
        return Native_Initialize(ctrlTransferClass);
    }
    public native boolean Native_Initialize(Object ctrlTransferClass);
    public boolean UnInitialize() {
        return Native_UnInitialize();
    }
    public native boolean Native_UnInitialize();
    public boolean RestartDevice() {
        return Native_RestartDevice(mCtrlTransferClass);
    }
    public native boolean Native_RestartDevice(Object ctrlTransferClass);
    public boolean AsicRegisterRead(int addr, byte pData[], int length) {
        return Native_AsicRegisterRead(mCtrlTransferClass, addr, pData, length);
    }
    public native boolean Native_AsicRegisterRead(Object ctrlTransferClass, int addr, byte pData[], int length);
    public boolean AsicRegisterWrite(int addr, byte pData[], int length) {
        return Native_AsicRegisterWrite(mCtrlTransferClass, addr, pData, length);
    }
    public native boolean Native_AsicRegisterWrite(Object ctrlTransferClass, int addr, byte pData[], int length);
    public boolean SensorRegisterCustomRead(byte slaveId, int addr, byte dataByteNumber, byte pData[], byte dataByteBumber, boolean pollSCL) {
        return Native_SensorRegisterCustomRead(mCtrlTransferClass, slaveId, addr, dataByteNumber, pData, dataByteBumber, pollSCL);
    }
    public native boolean Native_SensorRegisterCustomRead(Object ctrlTransferClass, byte slaveId, int addr, byte dataByteNumber, byte pData[], byte dataByteBumber, boolean pollSCL);
    public boolean SensorRegisterCustomWrite(byte slaveId, int addr, byte dataByteNumber, byte pData[], byte dataByteBumber, boolean pollSCL) {
        return Native_SensorRegisterCustomWrite(mCtrlTransferClass, slaveId, addr, dataByteNumber, pData, dataByteBumber, pollSCL);
    }
    public native boolean Native_SensorRegisterCustomWrite(Object ctrlTransferClass, byte slaveId, int  addr, byte dataByteNumber, byte pData[], byte dataByteBumber, boolean pollSCL);
    public boolean SensorTwoRegisterCustomRead(byte slaveId, int addr, byte dataByteNumber, byte pData[], byte dataByteBumber, boolean pollSCL) {
        return Native_SensorTwoRegisterCustomRead(mCtrlTransferClass, slaveId, addr, dataByteNumber, pData, dataByteBumber, pollSCL);
    }
    public native boolean Native_SensorTwoRegisterCustomRead(Object ctrlTransferClass, byte slaveId, int addr, byte dataByteNumber, byte pData[], byte dataByteBumber, boolean pollSCL);
    public boolean SensorTwoRegisterCustomWrite(byte slaveId, int addr, byte dataByteNumber, byte pData[], byte dataByteBumber, boolean pollSCL) {
        return Native_SensorTwoRegisterCustomWrite(mCtrlTransferClass, slaveId, addr, dataByteNumber, pData, dataByteBumber, pollSCL);
    }
    public native boolean Native_SensorTwoRegisterCustomWrite(Object ctrlTransferClass, byte slaveId, int  addr, byte dataByteNumber, byte pData[], byte dataByteBumber, boolean pollSCL);
    public boolean XuRead(byte pData[], int length, byte cs, byte unitId) {
        return Native_XuRead(mCtrlTransferClass, pData, length, cs, unitId);
    }
    public native boolean Native_XuRead(Object ctrlTransferClass, byte pData[], int length, byte cs, byte unitId);
    public boolean XuWrite(byte pData[], int length, byte cs, byte unitId) {
        return Native_XuWrite(mCtrlTransferClass, pData, length, cs, unitId);
    }
    public native boolean Native_XuWrite(Object ctrlTransferClass, byte pData[], int length, byte cs, byte unitId);
    public boolean GetProduct(byte pData[], int length) {
        return Native_GetProduct(mCtrlTransferClass, pData, length);
    }
    public native boolean Native_GetProduct(Object ctrlTransferClass, byte pData[], int length);
    public boolean GetFwVersion(byte pData[], int length, boolean bNormalExport) {
        return Native_GetFwVersion(mCtrlTransferClass, pData, length, bNormalExport);
    }
    public native boolean Native_GetFwVersion(Object ctrlTransferClass, byte pData[], int length, boolean bNormalExport);
    public boolean GetFwVersionFromFile(String fw, byte pData[], int length, boolean bNormalExport) {
        return Native_GetFwVersionFromFile(mCtrlTransferClass, fw, pData, length, bNormalExport);
    }
    public native boolean Native_GetFwVersionFromFile(Object ctrlTransferClass, String fw, byte pData[], int length, boolean bNormalExport);
    public boolean SerialFlashRead(int addr, byte pData[], int length) {
        return Native_SerialFlashRead(mCtrlTransferClass, addr, pData, length);
    }
    public native boolean Native_SerialFlashRead(Object ctrlTransferClass, int addr, byte pData[], int length);
    public boolean SerialFlashSectorWrite(Object sft, int addr, byte pData[], int length) {
        return Native_SerialFlashSectorWrite(mCtrlTransferClass, sft, addr, pData, length);
    }
    public native boolean Native_SerialFlashSectorWrite(Object ctrlTransferClass, Object sft, int addr, byte pData[], int length);
    public boolean GetSerialFlashType(Object sft, boolean check) {
        return Native_GetSerialFlashType(mCtrlTransferClass, sft, check);
    }
    public native boolean Native_GetSerialFlashType(Object ctrlTransferClass, Object sft, boolean check);
    public boolean SerialFlashWrite(int addr, byte pData[], int length) {
        return Native_SerialFlashWrite(mCtrlTransferClass, addr, pData, length);
    }
    public native boolean Native_SerialFlashWrite(Object ctrlTransferClass, int addr, byte pData[], int length);
    public boolean GetVidPid(byte pData[], int length) {
        return Native_GetVidPid(mCtrlTransferClass, pData, length);
    }
    public native boolean Native_GetVidPid(Object ctrlTransferClass, byte pData[], int length);
    public boolean GetManufacturer(byte pData[], int length) {
        return Native_GetManufacturer(mCtrlTransferClass, pData, length);
    }
    public native boolean Native_GetManufacturer(Object ctrlTransferClass, byte pData[], int length);
    public boolean GetString3(byte pData[], int length) {
        return Native_GetString3(mCtrlTransferClass, pData, length);
    }
    public native boolean Native_GetString3(Object ctrlTransferClass, byte pData[], int length);
    public boolean GetInterface(byte pData[], int length) {
        return Native_GetInterface(mCtrlTransferClass, pData, length);
    }
    public native boolean Native_GetInterface(Object ctrlTransferClass, byte pData[], int length);
    public boolean GetSerialNumber(byte pData[], int length) {
        return Native_GetSerialNumber(mCtrlTransferClass, pData, length);
    }
    public native boolean Native_GetSerialNumber(Object ctrlTransferClass, byte pData[], int length);
    public boolean GetAsicRomType(Object romType, int chipID[]) {
        return Native_GetAsicRomType(mCtrlTransferClass, romType, chipID);
    }
    public native boolean Native_GetAsicRomType(Object ctrlTransferClass, Object romType, int chipID[]);
    public boolean WriteFwToFlash(Object onProgressClass, String fw, boolean bFullCheckFW) {
        return Native_WriteFwToFlash(mCtrlTransferClass, onProgressClass, fw, bFullCheckFW);
    }
    public native boolean Native_WriteFwToFlash(Object ctrlTransferClass, Object onProgressClass, String fw, boolean bFullCheckFW);
    public boolean DisableSerialFlashWriteProtect(Object sft) {
        return Native_DisableSerialFlashWriteProtect(mCtrlTransferClass, sft);
    }
    public native boolean Native_DisableSerialFlashWriteProtect(Object ctrlTransferClass, Object sft);
    public boolean EraseSerialFlash(Object sft) {
        return Native_EraseSerialFlash(mCtrlTransferClass, sft);
    }
    public native boolean Native_EraseSerialFlash(Object ctrlTransferClass, Object sft);
    public boolean EraseSectorFlash(Object sft, int addr) {
        return Native_EraseSectorFlash(mCtrlTransferClass, sft, addr);
    }
    public native boolean Native_EraseSectorFlash(Object ctrlTransferClass, Object sft, int addr);
    public boolean EraseBlockFlash(Object sft, int addr) {
        return Native_EraseBlockFlash(mCtrlTransferClass, sft, addr);
    }
    public native boolean Native_EraseBlockFlash(Object ctrlTransferClass, Object sft, int addr);
    public boolean BurnerFW(Object onProgressClass, String fw, Object sft, boolean bFullCheckFW) {
        return Native_BurnerFW(mCtrlTransferClass, onProgressClass, fw, sft, bFullCheckFW);
    }
    public native boolean Native_BurnerFW(Object ctrlTransferClass, Object onProgressClass, String fw, Object sft, boolean bFullCheckFW);
    public boolean CustomBurnerFW(Object paramInfo, Object onProgressClass, String fw, Object sft, boolean bFullCheckFW) {
        return Native_CustomBurnerFW(mCtrlTransferClass, paramInfo, onProgressClass, fw, sft, bFullCheckFW);
    }
    public native boolean Native_CustomBurnerFW(Object ctrlTransferClass, Object paramInfo, Object onProgressClass, String fw, Object sft, boolean bFullCheckFW);
    public boolean SetParamTableFromFWFile(Object paramInfo, Object onProgressClass, String fw, Object sft, boolean bFullCheckFW) {
        return Native_SetParamTableFromFWFile(mCtrlTransferClass, paramInfo, onProgressClass, fw, sft, bFullCheckFW);
    }
    public native boolean Native_SetParamTableFromFWFile(Object ctrlTransferClass, Object paramInfo, Object onProgressClass, String fw, Object sft, boolean bFullCheckFW);
}
app/src/main/jniLibs/arm64-v8a/libSonixCamera.so
Binary files differ
app/src/main/jniLibs/armeabi-v7a/libSonixCamera.so
Binary files differ
app/src/main/res/layout/activity_homepage.xml
@@ -17,33 +17,56 @@
            android:id="@+id/app_fwupdata_btn"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:gravity="center"
            android:layout_alignParentBottom="true"
            android:enabled="true"
            android:layout_marginStart="20dp"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="20dp"
            android:layout_marginEnd="20dp"
            android:layout_marginRight="20dp"
            android:layout_marginBottom="20dp"
            android:background="@drawable/bg_internetlogin_loginbtn_selector"
            android:layout_margin="20dp"
            android:textSize="16sp"
            android:enabled="true"
            android:gravity="center"
            android:text="等待设备插入"
            android:textColor="@color/appwhite"
            android:text="等待设备插入"/>
            android:textSize="16sp" />
        <ListView
            android:id="@+id/app_fw_list"
            android:layout_above="@id/app_fwupdata_btn"
            android:layout_below="@id/device_fw_version"
            android:layout_above="@+id/app_fwupdata_btn"
            android:scrollbars="none"
            android:divider="@color/appline"
            android:dividerHeight="0.5dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        </ListView>
        <app.dinus.com.loadingdrawable.LoadingView
            android:id="@+id/progress_loading"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:layout_centerInParent="true"
            android:visibility="visible"
            app:loading_renderer="DanceLoadingRenderer"/>
        <TextView
            android:id="@+id/file_fw_version"
            android:layout_alignParentTop="true"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="@drawable/bg_internetlogin_loginbtn_selector"
            android:layout_margin="20dp"
            android:enabled="true"
            android:gravity="center"
            android:textSize="16sp"
            android:textColor="@color/appwhite">
        </TextView>
        <TextView
            android:id="@+id/device_fw_version"
            android:layout_below="@id/file_fw_version"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="@drawable/bg_internetlogin_loginbtn_selector"
            android:layout_margin="20dp"
            android:enabled="true"
            android:gravity="center"
            android:textSize="16sp"
            android:textColor="@color/appwhite">
        </TextView>
        <TextView
            android:id="@+id/app_topbar_no"
build.gradle
@@ -7,7 +7,7 @@
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.2.2'
        classpath 'com.android.tools.build:gradle:8.2.2'
        
        // NOTE: Do not place your application dependencies here; they belong
gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=file:///D:/a/FwUpgrade/gradle/gradle-7.2-bin.zip
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists