Android 恢复出厂备份wifi状态

背景:之前遇到有项目需要在恢复出厂设置之后,wifi能保持之前的状态,用户不需要重新输入密码,就可以连接上以前的热点。

对于recovery来说,有两种1、只清除data分区;2、清除data分区和cache分区。wifi状态,密码都是保存在data分区的,所以回复出厂后便会被清除掉。

要实现这个功能,修改及思路也比较简单,如下:
备份wifi状态->恢复出厂->还原wifi状态

恢复出厂是在recovery中控制的,这个我们就不修改了。
1、备份wifi状态

备份wifi状态选择在RecoverySystem类中去做,目录:frameworks/base/core/java/android/os/RecoverySystem.java
补丁如下:

     private static void bootCommand(Context context, String arg, Boolean update) throws IOException {
+       if(SystemProperties.getBoolean("persist.wifi.restore_enable",false) && !update && WIFI_SUPPLICANT_FILE.exists()){
+		    Log.d(TAG, "recovery: Wi-Fi backup!!!");
+		    WIFI_DIR.mkdirs();  // In case we need it
+		    WIFI_STATE_FILE.delete();  // In case it's not writable
+		    WIFI_SUPPLICANT_BACKUP_FILE.delete();  // In case it's not writable
+		    backupWifiSupplicantTemplate();
+		    backupWifiState(context);
+        }
+        //
         RECOVERY_DIR.mkdirs();  // In case we need it
         COMMAND_FILE.delete();  // In case it's not writable
         LOG_FILE.delete();
@@ -665,5 +682,42 @@
         return log;
     }
 

+    private static File WIFI_SUPPLICANT_FILE = new File("/data/misc/wifi/wpa_supplicant.conf");
+    private static File WIFI_DIR = new File("/backup/wifi");
+    private static File WIFI_STATE_FILE = new File(WIFI_DIR,"wifistate.conf");
+    private static File WIFI_SUPPLICANT_BACKUP_FILE = new File(WIFI_DIR,"wpa_supplicant.conf");
+
+    private static void backupWifiSupplicantTemplate() {
+	    try {
+		    BufferedReader br = new BufferedReader(new FileReader(WIFI_SUPPLICANT_FILE));
+		    BufferedWriter bw = new BufferedWriter(new FileWriter(WIFI_SUPPLICANT_BACKUP_FILE));
+
+	        char[] temp = new char[1024];
+	        int size;
+	        while ((size = br.read(temp)) > 0) {
+	            bw.write(temp, 0, size);
+	        }
+	        br.close();
+		    bw.close();
+	    } catch (Exception e) {
+		    Log.e(TAG, "backupWifiSupplicantTemplate error" );
+	    }		
+    }
+    
+    private static void backupWifiState(Context context) {
+		try{
+			final ContentResolver cr = context.getContentResolver();
+			int wifistate = Settings.Global.getInt(cr, Settings.Global.WIFI_ON);
+			
+			FileWriter file = new FileWriter(WIFI_STATE_FILE);
+			file.write(String.valueOf(wifistate));
+			file.close();
+		}
+		catch (Exception e) {
+			Log.e(TAG, "backupWifiState error" );
+		}
+    }
+    //
     private void RecoverySystem() { }  // Do not instantiate
 }

基本的流程就是在RecoverySystem增加对wifi状态的备份,备份两个东西:
1)wifi的ssid密码等信息。存放在/data/misc/wifi/wpa_supplicant.conf文件中的,wpa_supplicant会根据文件中的信息去进行wifi的连接。如果恢复出厂后没有该文件的话,会将system/etc/wifi/下的文件拷贝过去。
private static void backupWifiSupplicantTemplate() 对此过程实现。

2)wifi状态的开关。存放在数据库中Settings.Global.WIFI_ON字段。该字段如果是开着的话,开机会自动去连接wifi,framework有一整套wifi状态机来控制。
private static void backupWifiState(Context context) 对此过程实现。

2、还原wifi状态

还原wifi状态选择在SystemServer 中去处理,选择在wifiservice初始化之前。目录:frameworks/base/services/java/com/android/server/SystemServer.java
补丁如下:

+    private static File WIFI_SUPPLICANT_FILE = new File("/data/misc/wifi/wpa_supplicant.conf");
+    private static File WIFI_DIR = new File("/backup/wifi");
+    private static File WIFI_STATE_FILE = new File(WIFI_DIR,"wifistate.conf");
+    private static File WIFI_SUPPLICANT_BACKUP_FILE = new File(WIFI_DIR,"wpa_supplicant.conf");
+
+    private  void restoreWifi(){
+	    try {
+		    //cp "/backup/wifi/wpa_supplicant.conf" to "/data/misc/wifi/wpa_supplicant.conf"
+		    BufferedReader br = new BufferedReader(new FileReader(WIFI_SUPPLICANT_BACKUP_FILE));
+		    BufferedWriter bw = new BufferedWriter(new FileWriter(WIFI_SUPPLICANT_FILE));
+
+	        char[] temp = new char[1024];
+	        int size;
+	        while ((size = br.read(temp)) > 0) {
+	            bw.write(temp, 0, size);
+	        }
+	        br.close();
+		    bw.close();
+		    if(WIFI_SUPPLICANT_FILE.exists()){
+			    Process p = Runtime.getRuntime().exec("chmod 644 /data/misc/wifi/wpa_supplicant.conf");
+			    p.waitFor();
+		    }
+
+		    //put wifi_on to setting.db
+		    br = new BufferedReader(new FileReader(WIFI_STATE_FILE));
+		    String str = br.readLine();
+	        br.close();
+		    if(mContentResolver != null){
+			    Settings.Global.putInt(mContentResolver, Settings.Global.WIFI_ON, Integer.parseInt(str));
+		    }
+
+		    //"rm -rf backup/wifi/" 
+		    if(WIFI_DIR.exists()){
+			    Process p = Runtime.getRuntime().exec("rm -rf backup/wifi/");
+			    p.waitFor();
+		    }
+	    } catch (Exception e) {
+			Log.e(TAG, "restoreWifi error" );
+	    }	
+    }
+	//
     void reportWtf(String msg, Throwable e) {
         Slog.w(TAG, "***********************************************");
         Log.wtf(TAG, "BOOT FAILURE " + msg, e);
@@ -605,6 +655,13 @@
                 }
 
                try {	   		
+			   		if(firstBoot && WIFI_SUPPLICANT_BACKUP_FILE.exists()){
+						Slog.i(TAG, "firstBoot: Wi-Fi restore!!!");
+						restoreWifi();
+						WIFI_DIR.delete();
+					}
+					//end
                     Slog.i(TAG, "Wi-Fi Service");
                     wifi = new WifiService(context);
                     ServiceManager.addService(Context.WIFI_SERVICE, wifi);

和备份的流程差不多,就是将备份的wpa_supplicant.conf文件拷贝到/data/misc/wifi/wpa_supplicant.conf,权限改为644。把Settings.Global.WIFI_ON的状态重新写回数据库即可,也没什么好说的。这样在初始化wifiservice的时候,就会根据之前保存的状态进行wifi的连接了。

发布了58 篇原创文章 · 获赞 46 · 访问量 16万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章