Android recovery 下删除第一次启动后的痕迹

 在Aandroid系统启动后,Android系统会把APK的资源文件解压到系统的/data/app; 启动OOBE(开机设置程序);第一次启动与通常的启动是不同的。

 在工厂生产系统时,为了测试产线的设备,必须需要开机测试。但是一但启动系统,产品到客户手中就不是第一次启动了。如果重新烧写系统,又比较耗费时间。为了解决这个矛盾,需要在生产线上,开机测试后清除第一次启动痕迹。

基本的方法如下:

1 在应用层,写一个小app,发出清除痕迹的命令。

2 在server层,添加一个ResetFactoryReceiver.java;接受应用层的“清除痕迹“的命令。

3 在recover层,添加功能reset-factory,处理“清除痕迹“的实现。具体就是删除/data/目录下面的所有内容,保留自己的备份文件夹。因为recover模式下,没有删除文件夹的功能函数,需要我们自己递归删除文件。

4 删除之后直接关机。具体代码如下:

 

1 的实现:发一个intent即可;

 

2 的实现;在/data/system/packages.xml文件,记录了文件启动的类名,只启动一次的程序OOBE,有属性disabled-components

删除disabled-components 属性,就可以让这个程序重新开机启动

packages.xml文件省略内容如下:

 

  
  
  
  
  1. <package name="com.android.oobeshell" codePath="/system/app/OOBESHELL.apk" nativeLibraryPath="/data/data/com.android.oobeshell/lib" flags="1" ft="134b20d6348" it="134b20d6348" ut="134b20d6348" version="13" userId="10016"> 
  2. <sigs count="1"> 
  3. <cert index="0" /> 
  4. </sigs> 
  5. <disabled-components> 
  6. <item name="com.android.oobeshell.DefaultActivity" /> 
  7. </disabled-components> 
  8. </package> 
  
  
  
  
  1. /**
  2. * ResetFactoryReceiver.java
  3. * delete </disabled-components> node
  4. **/
  5.  
  6. public class ResetFactoryReceiver extends BroadcastReceiver { 
  7.     private String TAG = "ResetFactoryReceiver"
  8.     private android.tv.TvManager mTM; 
  9.     private static final String xmlPath = "/data/system/packages.xml"
  10.     @Override 
  11.     public void onReceive(final Context context, Intent intent) { 
  12.         Log.i(TAG, TAG); 
  13.         Context mCx = context ; 
  14.         mTM = (TvManager) mCx.getSystemService(Context.TV_SERVICE); 
  15.         rm_Pkgxml(); 
  16.         if (intent.getAction().equals("android.intent.action.resetfactory")) { 
  17.             Thread thr = new Thread("resetfactory") { 
  18.                 @Override 
  19.                 public void run() { 
  20.                     try { 
  21.                         Log.i(TAG, "resetFactory"); 
  22.                         RecoverySystem.resetFactory(context); 
  23.                     } catch (IOException e) { 
  24.                         Slog.e(TAG, "Can't perform master resetfactory :", e); 
  25.                     } 
  26.  
  27.                 } 
  28.             }; 
  29.             thr.start(); 
  30.         } 
  31.     } 
  32.      
  33.     private void rm_Pkgxml() { 
  34.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
  35.         DocumentBuilder db; 
  36.         try { 
  37.             db = factory.newDocumentBuilder(); 
  38.             Document doc = (Document) db.parse(new File(xmlPath)); 
  39.             doc.normalize(); 
  40.             NodeList packagename = doc.getElementsByTagName("package"); 
  41.             int i = 0
  42.             for (; i < packagename.getLength(); i++) { 
  43.                 Element elt = (Element) packagename.item(i); 
  44.                 if (elt.getAttribute("name").equals("com.android.oobeshell")) { 
  45.                     NodeList list = elt.getChildNodes(); 
  46.                     if (list.getLength() > 0) { 
  47.                         for (int j = 0; j < list.getLength()-1; j++) { 
  48.                             Slog.d(TAG,list.item(j).getNodeName()); 
  49. //                          if("sigs".equals((list.item(j).getNodeName()))){ 
  50. //                              list.item(j).getChildNodes().item(0).getAttributes().item(0).setNodeValue("1"); 
  51. //                          } 
  52.                             if ((list.item(j).getNodeName()) 
  53.                                     .equals("disabled-components")) { 
  54.                                 elt.removeChild(list.item(j)); 
  55.                             } 
  56.                         } 
  57.                     } 
  58.                 } 
  59.             } 
  60.             doc2XmlFile(doc,xmlPath);   
  61.         } catch (ParserConfigurationException e) { 
  62.             Slog.e(TAG,"ParserConfigurationException",e); 
  63.         } catch (SAXException e) { 
  64.             Slog.e(TAG,"SAXException",e); 
  65.         } catch (IOException e) { 
  66.             Slog.e(TAG,"IOException",e); 
  67.         } catch(NullPointerException e){ 
  68.             Slog.e(TAG,"NullPointerException",e); 
  69.         } 
  70.  
  71.     } 

3,4 的实现: 

 

 

  
  
  
  
  1. /bootable/recovery/recovery.c  
  2.  
  3. //需要保留的目录 
  4. static char *preserve_file[] = { 
  5.     "/data/app"
  6.     "/data/res-private"
  7.     NULL 
  8. }; 
  9.  

 


  1. //bootable/recovery/recovery.c
     
  2. else if (wipe_data) 之后 
  3.  
  4.   } else if (wipe_data) { 
  5.         printf("wipe_data..., default INSTALL_SUCCESS value = %d\n", status); 
  6.         if (device_wipe_data()) status = INSTALL_ERROR; 
  7.         if (erase_volume("/data")) status = INSTALL_ERROR; 
  8.         if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; 
  9.         if (status != INSTALL_SUCCESS) ui_print("Data wipe failed.\n"); 
  10.  
  11.  
  12. /* add by lhc 2011-12-16 */ 
  13.     } else if (reset_data) { 
  14.         printf("reset_factory..., default INSTALL_SUCCESS value = %d\n", status); 
  15.         if (device_wipe_data()) status = INSTALL_ERROR; 
  16.  
  17.  
  18.         if (erase_file("/data")) status = INSTALL_ERROR; 
  19.  
  20.  
  21.         if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR; 
  22.         if (status != INSTALL_SUCCESS) ui_print("Data wipe failed.\n"); 
  23. /* add by lhc end */ 
  24.  
  25.  

 

  1. //添加函数,递归删除文件 
  2. int remove_file(char *rmpath) 
  3.     struct stat statbuf; 
  4.     struct dirent   *dirp; 
  5.     DIR     *dp; 
  6.     int     ret = 0; 
  7.     char        childpath[PATH_LEN] = {0}; 
  8.     char        **preserve_p; 
  9.  
  10.     if (lstat(rmpath, &statbuf) < 0) { 
  11.         printf("%s can't lstat.\n", rmpath); 
  12.         return -1; 
  13.     } 
  14.  
  15.     for (preserve_p = preserve_file; *preserve_p; preserve_p++) { 
  16.         if (!strcmp(rmpath, *preserve_p)) 
  17.             return 0; 
  18.     } 
  19.     printf("rmpath = %s\n", rmpath); 
  20.  
  21.     if (S_ISDIR(statbuf.st_mode) == 0) { 
  22.         unlink(rmpath); 
  23.         printf("%s is not a dir, is removed.\n", rmpath); 
  24.         return 0; 
  25.     } 
  26.  
  27.     if ((dp = opendir(rmpath)) == NULL) { 
  28.         printf("can't read dir: %s, %s\n", rmpath, strerror(errno)); 
  29.         return -1; 
  30.     } 
  31.  
  32.     while ((dirp = readdir(dp)) != NULL) { 
  33.         if (strcmp(dirp->d_name, ".") == 0 || 
  34.                 strcmp(dirp->d_name, "..") == 0) 
  35.             continue
  36.  
  37.         snprintf(childpath, PATH_LEN, "%s/%s", rmpath, dirp->d_name); 
  38.         if ((ret = remove_file(childpath)) != 0) /* R */ 
  39.             return -1; 
  40.     } 
  41.  
  42.     if (closedir(dp) < 0) { 
  43.         printf("closedir error.\n"); 
  44.         return -1; 
  45.     } 
  46.  
  47.     if (rmdir(rmpath) == -1) { 
  48.         for (preserve_p = preserve_file; *preserve_p; preserve_p++) { 
  49.             if (!strstr(*preserve_p, rmpath)) { 
  50.                 printf("rmdir %s error,%s.\n", rmpath, strerror(errno)); 
  51.                 return -1; 
  52.             } 
  53.         } 
  54.     } 
  55.  
  56.     printf("rmdir ok %s\n", rmpath); 
  57.  
  58.     return ret; 
  59.  
  60. //递归删除文件 
  61. static int 
  62. erase_file(const char *path) { 
  63.     ui_set_background(BACKGROUND_ICON_INSTALLING); 
  64.     ui_show_indeterminate_progress(); 
  65.     ui_print("erase %s...\n", path); 
  66.  
  67.     if (!strcmp(path, "/data")) { 
  68.         if (ensure_path_mounted(path) != 0) { 
  69.             LOGE("ensure_path_mounted failed to nmount \"%s\"\n", path); 
  70.             return -1; 
  71.      } 
  72.         return remove_file("/data"); 
  73.     } 
  74.  
  75.     return 0; 
  76.  
  77.  
  78.  
  79.  
  80.  
  81. /* add by lhc 2011-12-16 */ 
  82.     if (update_package) { 
  83.         set_recovery_status(status, "update"); 
  84.     } else { 
  85.         set_recovery_status(status, "recovery"); 
  86.     } 
  87. /* add by lhc end */ 
  88.  
  89.  
  90.  
  91.     //  
  92.     printf("before finish_recovery.\n"); 
  93.     finish_recovery(send_intent);  
  94.     printf("status = %d.\n", status); 
  95.     if (status == INSTALL_SUCCESS) { 
  96.  
  97. /* add by lhc 2011-12-16 */ 
  98. //power off  直接关机。
  99.         if (reset_data) { 
  100.             printf("Power off...\n"); 
  101.             android_reboot(ANDROID_RB_POWEROFF, 0, 0); 
  102.         } 
  103. /* add by lhc end */ 
  104.         printf("Rebooting...\n"); 
  105.         android_reboot(ANDROID_RB_RESTART, 0, 0); 
  106.     } 
  107. //} 
  108.     return EXIT_SUCCESS; 

 

本文出自 “lhc180” 博客,转载请与作者联系!

你可能感兴趣的:(android,android,职场,休闲,recovery,firstboot)