android第三方app怎样调用NVRAM

要操作NVRAM,必须具有系统app的权限。我在系统的里面找到读写MAC地址相关的实现,首先是读的方法

private String getMacAddrFromNvram() {
    StringBuffer nvramBuf = new StringBuffer();
    try {
        int i = 0;
        String buff = null;
        INvram agent = INvram.getService();
        if (agent == null) {
            mToast.setText("No support MAC address writing due to NVRAM");
            mToast.show();
            Log.e(TAG, "NvRAMAgent is null");
            return "";
        }
        try {
            buff = agent.readFileByName(
                    MAC_ADDRESS_FILENAME, MAC_ADDRESS_OFFSET + MAC_ADDRESS_DIGITS);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        Log.i(TAG, "Raw data:" + buff);
        if (buff.length() < 2 * (MAC_ADDRESS_OFFSET + MAC_ADDRESS_DIGITS)) {
            mToast.setText("The foramt of NVRAM is not correct");
            mToast.show();
            return "";
        }
        // Remove the \0 special character.
        int macLen = buff.length() - 1;
        for (i = MAC_ADDRESS_OFFSET * 2; i < macLen; i += 2) {
            if ((i + 2) < macLen) {
                nvramBuf.append(buff.substring(i, i + 2));
                nvramBuf.append(":");
            } else {
                nvramBuf.append(buff.substring(i));
            }
        }
        Log.d(TAG, "buff:" + nvramBuf.toString());
    } catch (Exception e) {
        e.printStackTrace();
        return "";
    }
    return nvramBuf.toString();
}

核心就是这个INvram,看一下相关的实现。

public interface INvram extends IBase {
	...
	static INvram asInterface(IHwBinder binder) {
    if (binder == null) {
        return null;
    } else {
        IHwInterface iface = binder.queryLocalInterface("[email protected]::INvram");
        if (iface != null && iface instanceof INvram) {
            return (INvram)iface;
        } else {
                INvram.Proxy proxy = new INvram.Proxy(binder);

                try {
                    Iterator var3 = proxy.interfaceChain().iterator();

                    while(var3.hasNext()) {
                        String descriptor = (String)var3.next();
                        if (descriptor.equals("[email protected]::INvram")) {
                            return proxy;
                        }
                    }
                } catch (RemoteException var5) {
                }

                return null;
       		}
    	}
	}

    static INvram castFrom(IHwInterface iface) {
        return iface == null ? null : asInterface(iface.asBinder());
    }

    IHwBinder asBinder();

    static INvram getService(String serviceName, boolean retry) throws RemoteException {
        return asInterface(HwBinder.getService("[email protected]::INvram", serviceName, retry));
    }

    static INvram getService(boolean retry) throws RemoteException {
        return getService("default", retry);
    }

    static INvram getService(String serviceName) throws RemoteException {
        return asInterface(HwBinder.getService("[email protected]::INvram", serviceName));
    }

    static INvram getService() throws RemoteException {
        return getService("default");
    }

    String readFileByName(String var1, int var2) throws RemoteException;

    byte writeFileByNamevec(String var1, int var2, ArrayList var3) throws RemoteException;
	...
}

一开始想通过反射来调用,非SDK接口,根本找不到这个类,

private String readFileByName(String name,int offSet){
    try {
        Class INvram = Class.forName("vendor.mediatek.hardware.nvram.V1_0.INvram");
        Method getService = INvram.getDeclaredMethod("getService");
        Object object = getService.invoke(INvram);//通过getinstance方法实例化对象
        Method getAuthor = INvram.getDeclaredMethod("readFileByName", String.class,int.class);//参数类型的class
        getAuthor.setAccessible(true);
        String mac =(String)getAuthor.invoke(object, name,offSet);
        return mac;
    }catch (Exception e){
        Log.d(TAG, "readFileByName: Exception "+e.toString());
        return "";
    }
}

于是去out目录找到相应的jar包,把jar导进去就可以调用了。路径为out\soong.intermediates\vendor\mediatek\proprietary\hardware\interfaces\nvram\1.0\vendor.mediatek.hardware.nvram-V1.0-java\android_common\combined\vendor.mediatek.hardware.nvram-V1.0-java.jar。再去看一下写MAC的方法

private void updateMacAddr() {

    try {
        int i = 0;
        INvram agent = INvram.getService();
        byte[] macAddr = new byte[MAC_ADDRESS_DIGITS];
        if (agent == null) {
            mToast.setText("No support MAC address writing due to NVRAM");
            mToast.show();
            Log.e(TAG, "NvRAMAgent is null");
            return;
        }

        //parse mac address firstly 例如输入的为00:08:22:E8:48:96
        StringTokenizer txtBuffer = new StringTokenizer(
                                mMacAddrEdit.getText().toString(), ":");
		//将byte型转化为16进制的int
        while (txtBuffer.hasMoreTokens()) {
            macAddr[i] = (byte) Integer.parseInt(txtBuffer.nextToken(), 16);
            i++;
        }
        if (i != MAC_ADDRESS_DIGITS) {
            Log.e(TAG, "Wrong length of macAddr:" + i);
            mToast.setText("The format of mac address is not correct");
            mToast.show();
            return;
        }
		
		//这里是为了读取前面4个byte
        String buff = null;
        try {
            buff = agent.readFileByName(
                    MAC_ADDRESS_FILENAME, MAC_ADDRESS_OFFSET + MAC_ADDRESS_DIGITS);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        // 将16进制字符转化为byte数组
        byte[] buffArr = HexDump.hexStringToByteArray(
                            buff.substring(0, buff.length() - 1));
		
		//从第4个开始赋值
        for (i = 0; i < MAC_ADDRESS_DIGITS; i ++) {
            buffArr[i + 4] = macAddr[i];
        }

        ArrayList dataArray = new ArrayList(
                            MAC_ADDRESS_OFFSET + MAC_ADDRESS_DIGITS);

        for (i = 0; i < MAC_ADDRESS_OFFSET + MAC_ADDRESS_DIGITS; i++) {
            dataArray.add(i, new Byte(buffArr[i]));
        }

        int flag = 0;
        try {
            flag = agent.writeFileByNamevec(MAC_ADDRESS_FILENAME,
                    MAC_ADDRESS_OFFSET + MAC_ADDRESS_DIGITS, dataArray);
        } catch (Exception e) {
            e.printStackTrace();
            mToast.setText(e.getMessage() + ":" + e.getCause());
            mToast.show();
            return;
        }
        mToast.setText("Update successfully.\r\nPlease reboot this device");
        mToast.show();
    } catch (Exception e) {
        mToast.setText(e.getMessage() + ":" + e.getCause());
        mToast.show();
        e.printStackTrace();
    }
}

来看一下hexStringToByteArray的实现

public static byte[] hexStringToByteArray(String hexString){
	int length = hexString.length();
	byte[] buffer = new byte[length / 2];
	
	for (int i = 0 ; i < length ; i += 2)
	{
	    buffer[i / 2] = (byte)((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i+1)));
	}
	
	return buffer;
}

private static int toByte(char c){
    if (c >= '0' && c <= '9') return (c - '0');
    if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
    if (c >= 'a' && c <= 'f') return (c - 'a' + 10);

    throw new RuntimeException ("Invalid hex char '" + c + "'");
}

你可能感兴趣的:(android第三方app怎样调用NVRAM)