对Android系统的NV区写入配置信息实现手机恢复出厂设置后原有信息不丢失

一、NVRAM基本概念 

NV就是Non Volatile缩写,就是非易失性存储性,通俗来说,就是即使系统掉电后,存储在该存储器的数据也不会丢失。 
为什么要备份恢复,NV值是需要通过校准和终测才能使手机硬件达到最佳工作状态,特别是其中的RF相关的NV项,经过校准及终测后,每台手机的这些NV值基本上都不一样,又加上NV数据是是存储在镜像文件,而镜像文件数据很可能遭到破坏(如:重新烧写版本),这时的NV数据也将被破坏,之前校准和终测后的NV数据也将无法恢复,使得手机将面临重新走校准、终测的生产流程。 

对Android系统的NV区写入配置信息实现手机恢复出厂设置后原有信息不丢失_第1张图片

                                                                                             图1-NVRAM框架图 

二、如何实现对NV区的读写操作

1、frameworks/base/core/java/android/os/NvRAMAgent.java

package android.os;

public interface NvRAMAgent extends IInterface
{
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends Binder implements NvRAMAgent
    {
        private static final String DESCRIPTOR = "NvRAMAgent";
        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
            this.attachInterface(this, DESCRIPTOR);
        }
        /**
         * Cast an IBinder object into an NvRAMAgent interface,
         * generating a proxy if needed.
         */
        public static NvRAMAgent asInterface(IBinder obj)
        {
            if ((obj==null)) {
                return null;
            }
            IInterface iin = (IInterface)obj.queryLocalInterface(DESCRIPTOR);
            if (((iin!=null)&&(iin instanceof NvRAMAgent))) {
                return ((NvRAMAgent)iin);
            }
            return new Stub.Proxy(obj);
        }
        public IBinder asBinder()
        {
            return this;
        }
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException
        {
            switch (code)
            {
                case INTERFACE_TRANSACTION:
                {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_READFILE:
                {
                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    byte[] _result = this.readFile(_arg0);
                    reply.writeNoException();
                    reply.writeByteArray(_result);
                    return true;
                }
                case TRANSACTION_WRITEFILE:
                {
                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    byte[] _arg1;
                    _arg1 = data.createByteArray();
                    int _result = this.writeFile(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
                default:
                {
                    break;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }
        private static class Proxy implements NvRAMAgent
        {
            private IBinder mRemote;
            Proxy(IBinder remote)
            {
                mRemote = remote;
            }
            public IBinder asBinder()
            {
                return mRemote;
            }
            public String getInterfaceDescriptor()
            {
                return DESCRIPTOR;
            }
            public byte[] readFile(int file_lid) throws RemoteException
            {
                Parcel _data = Parcel.obtain();
                Parcel _reply = Parcel.obtain();
                byte[] _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(file_lid);
                    mRemote.transact(Stub.TRANSACTION_READFILE, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createByteArray();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
            public int writeFile(int file_lid, byte[] buff) throws RemoteException
            {
                Parcel _data = Parcel.obtain();
                Parcel _reply = Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(file_lid);
                    _data.writeByteArray(buff);
                    mRemote.transact(Stub.TRANSACTION_WRITEFILE, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            public byte[] readFileByName(String filename) throws RemoteException
            {
                Parcel _data = Parcel.obtain();
                Parcel _reply = Parcel.obtain();
                byte[] _result;

                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(filename);
                    mRemote.transact(Stub.TRANSACTION_READFILEBYNAME, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createByteArray();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }

                return _result;
            }

            public int writeFileByName(String filename, byte[] buff)
                throws RemoteException {
                Parcel _data = Parcel.obtain();
                Parcel _reply = Parcel.obtain();
                int _result;

                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(filename);
                    _data.writeByteArray(buff);
                    mRemote.transact(Stub.TRANSACTION_WRITEFILEBYNAME, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }

                return _result;
            }
        }
        static final int TRANSACTION_READFILE = (IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_WRITEFILE = (IBinder.FIRST_CALL_TRANSACTION + 1);
        static final int TRANSACTION_READFILEBYNAME = (IBinder.FIRST_CALL_TRANSACTION + 2);
        static final int TRANSACTION_WRITEFILEBYNAME = (IBinder.FIRST_CALL_TRANSACTION + 3);
    }
    public byte[] readFile(int file_lid) throws RemoteException;
    public int writeFile(int file_lid, byte[] buff) throws RemoteException;
    public byte[] readFileByName(String filepath) throws RemoteException;
    public int writeFileByName(String filepath, byte[] buff) throws RemoteException;
}

这个文件是Android上层对nv区的接口文件,里面是都是定义了对nv区的读写函数:readFile(),writeFile(),readFileByName(),writeFileByName()。我们通过调用改接口中的写入函数将我们要写入的数据写入到nv区;调用读取函数读取nv区中的值;nv区的值都是通过类似键值的方式进行存储读写!

2、frameworks/base/core/java/android/os/NvRAMPROINFOUtils.java

 package android.os;

/** pro_info cyrus start */
public final class NvRAMPROINFOUtils {
	
	public static final String TAG = "NvRAMPROINFOUtils";
	
	/**
	 * key: 104-->1024 
	 */
	//add  by wst start	
	public static final int key_fontcamera_value = 668;
	public static final int key_backcamera_value = 669;


	public static final int read(int key){
		int result = 0;
		try{
			android.os.NvRAMAgent agent = android.os.NvRAMAgent.Stub.asInterface (android.os.ServiceManager.getService("NvRAMAgent"));
            result = agent.readFileByName("/data/nvram/APCFG/APRDEB/PRODUCT_INFO")[key];
        }catch(Exception e){
        }
		return result;
	}
	
	public static final int read(int key,int signal){
		int init_flag = android.os.NvRAMPROINFOUtils.read(key_singal_init);
		if(init_flag != 1&&android.os.NvRAMPROINFOUtils.read(key) == 0){
				android.os.NvRAMPROINFOUtils.write(key,signal);
				android.os.NvRAMPROINFOUtils.write(key_singal_init,1);
				return signal;
		}else{
			return read(key);
			}	
	}


	public static final boolean write(int key, int value){
		int result = 0;
		try{
			android.os.NvRAMAgent agent = android.os.NvRAMAgent.Stub.asInterface (android.os.ServiceManager.getService("NvRAMAgent"));
    		byte[] buff = agent.readFileByName("/data/nvram/APCFG/APRDEB/PRODUCT_INFO");
    		buff[key] = (byte) value;
    		result = agent.writeFileByName("/data/nvram/APCFG/APRDEB/PRODUCT_INFO",buff);
    	}catch(Exception e){
    		android.util.Log.i("lxm", "NvRAMPROINFOUtils write logstart: " + e.getMessage());
    	}
		return result == 1;
	}

}

我们创建的这个文件就是实际操作nv区;我们这里以相机的picturesize的作为例子。我们遇到有些客户要求可以在手机刷机后自己随意选择default picturesize后;在恢复出厂设置后仍然保留之前的设置;我们就可以在相机选择default picturesize时去读取nv区设置的值,来达到打开相机后的default picturesize是之前的值(具体修改camera的picturesize这里就不多介绍了)!

你可能感兴趣的:(对Android系统的NV区写入配置信息实现手机恢复出厂设置后原有信息不丢失)