安卓底层知识拾零

来源:互联网 发布:计算机二级c语言知识点 编辑:程序博客网 时间:2024/06/06 12:26

本文转载自:http://blog.csdn.net/zhoumushui/article/details/41623903

1.Android字库文件

打开Android源码路径:

framework/base/data/fonts/

可以看到很多ttf文件,如下图:


这些文件都是做什么用的呢?查了些资料整理下:


字库文件 用途
=======================================================

AndroidClock.ttf  用于显示不同样式时间
AndroidClock_Highlight.ttf
AndroidClock_Solid.ttf

-------------------------------------------------------------------------------------------------
Clockopia.ttf 用于锁屏界面

-------------------------------------------------------------------------------------------------
AndroidEmoji.ttf 符号字形

-------------------------------------------------------------------------------------------------
DroidNaskh-Regular.ttf 波斯,阿拉伯语,乌尔都语字库
DroidNaskhUI-Regular.ttf

-------------------------------------------------------------------------------------------------
DroidSansArmenian.ttf 亚美尼亚语

-------------------------------------------------------------------------------------------------
DroidSansEthiopic-Regular.ttf 阿姆哈拉语、提格雷语(埃塞俄比亚)

-------------------------------------------------------------------------------------------------
DroidSansFallback.ttf 中文字库,CJK中日韩统一字符

-------------------------------------------------------------------------------------------------
DroidSansGeorgian.ttf 格鲁吉亚语

-------------------------------------------------------------------------------------------------
DroidSansHebrew-Bold.ttf 希伯来语
DroidSansHebrew-Regular.ttf

-------------------------------------------------------------------------------------------------
DroidSansMono.ttf 西里尔和拉丁字母扩充附加

-------------------------------------------------------------------------------------------------
DroidSerif-Bold.ttf 拉丁字母:衬线体
DroidSerif-BoldItalic.ttf
DroidSerif-Italic.ttf
DroidSerif-Regular.ttf

-------------------------------------------------------------------------------------------------
MTLmr3m.ttf 繁体中文字库

-------------------------------------------------------------------------------------------------
NanumGothic.ttf 谚文字母(朝鲜语、韩语)

-------------------------------------------------------------------------------------------------
padauk.ttf 官方缅甸语字库
ZawgyiOne.ttf 民间缅甸语字库

-------------------------------------------------------------------------------------------------
Roboto-Bold.ttf 欧洲使用的拉丁、西里尔字母
Roboto-Regular.ttf
External/noto-fonts

-------------------------------------------------------------------------------------------------
NotoColorEmoji.ttf 表情字符

-------------------------------------------------------------------------------------------------
NotoSansBengaliUI-Bold.ttf 孟加拉语字库
NotoSansBengaliUI-Regular.ttf

-------------------------------------------------------------------------------------------------
NotoSansDevanagariUI-Bold.ttf 印度语字库
NotoSansDevanagariUI-Regular.ttf

-------------------------------------------------------------------------------------------------
NotoSansKannadaUI-Bold.ttf 卡纳达语字库(印度)
NotoSansKannadaUI-Regular.ttf

-------------------------------------------------------------------------------------------------
NotoSansKhmerUI-Bold.ttf 高棉语字库(柬埔寨)
NotoSansKhmerUI-Regular.ttf

-------------------------------------------------------------------------------------------------
NotoSansLaoUI-Bold.ttf 老挝语字库
NotoSansLaoUI-Regular.ttf

-------------------------------------------------------------------------------------------------
NotoSansMalayalamUI-Bold.ttf 马拉雅拉姆文字库(印度)
NotoSansMalayalamUI-Regular.ttf

-------------------------------------------------------------------------------------------------
NotoSansTamilUI-Bold.ttf 泰米尔语字库(印度、斯里兰卡、新加坡)
NotoSansTamilUI-Regular.ttf

-------------------------------------------------------------------------------------------------
NotoSansTeluguUI-Bold.ttf 泰卢固语(印度)
NotoSansTeluguUI-Regular.ttf

-------------------------------------------------------------------------------------------------
NotoSansThaiUI-Bold.ttf 泰语字库
NotoSansThaiUI-Regular.ttf

=======================================================

2.Android手机做热点时,如何获取连过来设备的具体信息?

1、连接过来的设备的信息存放在/data/misc/dhcp/dnsmasq.leases中

2、它的格式是:

/系统id,不需取值/client mac地址/client ip地址/ client device name/加权后mac地址,也不需取值

[plain] view plaincopy
  1. 1357041758 88:00:12:34:56:78 192.168.43.133 android-184cc6c105d7a3b 01:88:00:12:34:56:78  

3、参考WifiServie.java的getClientIp()方法,可以自定义这个方法取得device name,具体如下:

[java] view plaincopy
  1. public String getClientDeviceName(String deviceAddress) {//传mac地址进来  
  2. enforceAccessPermission();  
  3. if (TextUtils.isEmpty(deviceAddress)) {  
  4. return null;  
  5. }  
  6. //读取对应的文件信息  
  7. for (String s : readClientList("/data/misc/dhcp/dnsmasq.leases")) {  
  8. if (s.indexOf(deviceAddress) != -1) {  
  9. String[] fields = s.split(" ");  
  10. //校验数据是否破损  
  11. if (fields.length > 4) {  
  12. //返回第4个栏位  
  13. return fields[3];  
  14. }  
  15. }  
  16. }  
  17. return null;  
  18. }  

3.在Fastboot里添加命令

fastboot 是android 默认的一种debug 方法,它的好处是在进入linux kernel 之前
即可操作。
默认fastboot 支持的命令:

[plain] view plaincopy
  1. usage: fastboot [ <option> ] <command>  
  2. commands:  
  3. update <filename> reflash device from  
  4. update.zip  
  5. flashall flash boot  
  6. + recovery + system  
  7. flash <partition> [ <filename> ] write a file to a flash  
  8. partition  
  9. erase <partition> erase a flash  
  10. partition  
  11. format <partition> format a flash  
  12. partition  
  13. getvar <variable> display a  
  14. bootloader variable  
  15. boot <kernel> [ <ramdisk> ] download and boot kernel  
  16. flash:raw boot <kernel> [ <ramdisk> ] create bootimage and flash it  
  17. devices list all  
  18. connected devices  
  19. continue continue  
  20. with autoboot  
  21. reboot reboot  
  22. device normally  
  23. reboot-bootloader reboot device  
  24. into bootloader  
  25. help show this  
  26. help message  
  27. options:  
  28. -w erase userdata and cache (and  
  29. format if supported by partition type)  
  30. -u do not first erase partition  
  31. before formatting  
  32. -s <specific device> specify device serial number or path to  
  33. device port  
  34. -l with "devices", lists device  
  35. paths  
  36. -p <product> specify product name  
  37. -c <cmdline> override kernel commandline  
  38. -i <vendor id> specify a custom USB vendor id  
  39. -b <base_addr> specify a custom kernel base  
  40. address  
  41. -n <page size> specify the nand page size.  
  42. default: 2048  
  43. -S <size>[K|M|G] automatically sparse files  
  44. greater than size. 0 to disable  

fastboot 提供了扩展的命令符号
[plain] view plaincopy
  1. fastboot oem command args  
下面以fastboot oem hello test 来说明如何扩展


(1).在bootable/bootloader/lk/app/mt_boot/fastboot.c
的fastboot_init 函数中添加一个新的register

[cpp] view plaincopy
  1. //第一个参数是命令的名称  
  2. //第二个参数是命令的执行函数  
  3. //第三个参数是在security IC 中是否还提供此命令  
  4. fastboot_register("oem hello", cmd_oem_hello, FALSE);  


(2). 实现cmd_oem_hello 函数
void cmd_oem_hello(const char *arg, void *data, unsigned size) {
[cpp] view plaincopy
  1. //注意args 是以command 结束开始,即" args"  
  2. if(!strncmp(arg, " OK", strlen(" OK"))){  
  3. fastboot_okey("OK");  
  4. }else{  
  5. fastboot_fail("Not OK");  
  6. }  
  7. }  


(3). 与PC 端交互
您可以使用下面已经定义好的三个函数与PC 端交互
[cpp] view plaincopy
  1. fastboot_okey(const char* result);  
  2. fastboot_fail(const char* reason);  
  3. fastboot_info(const char* reason);   

注意这三个打印字符串的长度都不能超过64-1-4 = 59 个字


4.在任意界面按某个实体键进入某个Activity

有些手机会有附加的功能键,比如拍照实体键,甚至有两端式的,轻按聚焦,深按拍照。那么类似功能是如何在Android手机上实现的呢?

可以修改源码下

frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java文件中的如下方法:

[java] view plaincopy
  1. public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event,int policyFlags)  

找到如下代码段:
[java] view plaincopy
  1. else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {  
  2. if (down && repeatCount == 0 && !keyguardOn) {  
  3. showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);  
  4. }  
  5. return -1;  
  6. }  

在这个else if后面增加相应代码:
[java] view plaincopy
  1. else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {  
  2. if (down && repeatCount == 0 && !keyguardOn) {  
  3. showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);  
  4. }  
  5. return -1;  
  6. //add begin  
  7. else if (keyCode == KeyEvent.KEYCODE_XXX) {  
  8. if (down && repeatCount == 0 && !keyguardOn) {  
  9. mContext.startActivity(new Intent("intent.xxx")  
  10. .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));  
  11. }  
  12. return -1;  
  13. // add end  


注意:
1、上面写的KeyEvent.KEYCODE_XXX是预设定好的实体键的键值,根据需要来设定即可;

2、startActivity(new Intent("intent.xxx")中的intent.xxx需要根据所启动的activity来写


5.在关机界面添加重启功能

Google原生的Android系统一般是没有“重启”这个选项的。有时候重启也是不可或缺的一个Feature,那么如何在源码环境下添加这个选项呢?


1. 在frameworks\base\core\res\res\values\strings.xml
中添加标签:

[html] view plaincopy
  1. <span style="font-size:14px;"><!--zms add start-->  
  2. <!-- label for item that power reboot in phone options dialog -->  
  3. <string name="zms_global_action_power_reboot">Reboot</string>  
  4. <!--zms add end--></span>  

当然这只是英语语系的,需要添加其它语系的标示,把"Reboot" 替换成其它语言。


2. 在alps\frameworks\base\core\res\res\drawable-hdpi 中添加图标:
zms_ic_lock_power_reboot.png


3. 打开frameworks\policies\base\phone\com\android\internal\policy\impl\GlobalActions.java
大概在这个文件的261行有这样的代码:

[java] view plaincopy
  1. mItems = Lists.newArrayList(  
  2. // silent mode  
  3. mSilentModeToggle,  
  4. // next: airplane mode  
  5. mAirplaneModeOn,  
  6. // last: power off  

在这里,我们添加power reboot 的新的item.
具体这个mItems 更新为如下:
[java] view plaincopy
  1. mItems = Lists.newArrayList(  
  2. // silent mode  
  3. mSilentModeToggle,  
  4. // next: airplane mode  
  5. mAirplaneModeOn,  
  6. // last: power off  
  7. new SinglePressAction(  
  8. com.android.internal.R.drawable.ic_lock_power_off,  
  9. R.string.global_action_power_off) {  
  10. public void onPress() {  
  11. // shutdown by making sure radio and power are handled  
  12. accordingly.  
  13. ShutdownThread.shutdown(mContext, true);  
  14. }  
  15. public boolean showDuringKeyguard() {  
  16. return true;  
  17. }  
  18. public boolean showBeforeProvisioning() {  
  19. return true;  
  20. }  
  21. }//zms add start  
  22. ,  
  23. new SinglePressAction(  
  24. com.android.internal.R.drawable.zms_ic_lock_power_reboot,  
  25. R.string.zms_global_action_power_reboot) {  
  26. public void onPress() {  
  27. // reboot by making sure radio and power are handled  
  28. accordingly.  
  29. ShutdownThread.reboot(mContext, nulltrue);  
  30. }  
  31. public boolean showDuringKeyguard() {  
  32. return true;  
  33. }  
  34. public boolean showBeforeProvisioning() {  
  35. return true;  
  36. }   
  37. }   
  38. //zms add end.  
  39. );   


经过这样的添加/修改后,这项feature 即可运行。
注意如果测试的话,因为有修改framework 中的文件,最好new 一下整个工程。
另外还需要修改一下ShutdownThread.java 中的那个dialog 显示描述,不然将依旧看到“关机”的信息。

位置:frameworks/base/services/java/com/android/server/power/ShutdownThread.java

不同版本的代码位置可能有所差别,可以在根目录下find一下:

[plain] view plaincopy
  1. find -name ShutdownThread.java  

如下:

[java] view plaincopy
  1. sConfirmDialog = new AlertDialog.Builder(context)    
  2.                     .setTitle((mReboot && !mRebootSafeMode)    
  3.             ? com.android.internal.R.string.reboot_title    
  4.                 : (mRebootSafeMode    
  5.                             ? com.android.internal.R.string.reboot_safemode_title    
  6.                             : com.android.internal.R.string.power_off))    
  7.                     .setMessage(resourceId)    
  8.                     .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {    
  9.                             public void onClick(DialogInterface dialog, int which) {    
  10.                             beginShutdownSequence(context);    
  11.                             if (sConfirmDialog != null) {    
  12.                             sConfirmDialog = null;    
  13.                             }    
  14.                             }    
  15.                             })    
  16.                 .setNegativeButton(com.android.internal.R.string.no, new DialogInterface.OnClickListener() {    
  17.                         public void onClick(DialogInterface dialog, int which) {    
  18.                         synchronized (sIsStartedGuard) {    
  19.                         sIsStarted = false;    
  20.                         }    
  21.                         if (sConfirmDialog != null) {    
  22.                         sConfirmDialog = null;    
  23.                         }    
  24.                         }    
  25.                         })    
  26.                 .create();    

6.使用init.rc触发脚本实现隐藏内置应用

【实现逻辑】

通过在property_service.c中设置标志位,在设置中实现接口改变标志位,
使用init.rc中声明的服务来侦听标志位的变化,显式启动声明的服务,执行对应的脚本,把应用后缀从apk重命名为bak,从而实现隐藏(显示逻辑相反)。

【实现步骤】以隐藏Google Play Store(system/priv-app/Phonesky.apk)为例:
1.首先在system/core/init/property_service.c中声明并初始化标志位,0为隐藏,1为显示,默认隐藏
[cpp] view plaincopy
  1. "app.launcher.start", AID_SYSTEM, 0},  
  2.  "app.phonesky.show", AID_SYSTEM, 0}, //Add By zj  
  3. "cdma.",        AID_RADIO,    0 },    //Add by gfzhu VIA  


2.在设置的开发者选项中实现对应的接口:
文件路径:packages/apps/Settings/src/com/android/settings/DevelopmentSettings.java
①声明和初始化:
[java] view plaincopy
  1. private static final String SHOW_PHONESKY = "show_phonesky";  
  2. private CheckBoxPreference mShowPhonesky;  
  3. mShowPhonesky = findAndInitCheckboxPref(SHOW_PHONESKY);  

②CheckBox的逻辑:
[java] view plaincopy
  1.        (BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB) : 0);  
  2. +      } else if (preference == mShowPhonesky) { // ZJ Add  
  3. +           if(mShowPhonesky.isChecked())  
  4. +           {  
  5. +              SystemProperties.set("app.phonesky.show","1");  
  6. +           }else{  
  7. +              SystemProperties.set("app.phonesky.show","0");  
  8. +           }  
  9.          } else if (preference == mBtHciSnoopLog) {  



③增加一个Preference:
packages/apps/Settings/res/xml/development_prefs.xml

[html] view plaincopy
  1.      android:targetClass="com.android.settings.SetFullBackupPassword" />  
  2.      </PreferenceScreen>  
  3. +       <CheckBoxPreference   
  4. +        android:key="show_phonesky"   
  5. +        android:title="@string/show_phonesky"   
  6. +        />  
  7.      <CheckBoxPreference   


④添加对应语言的string字符:
[html] view plaincopy
  1. <string name="show_phonesky">Show Google Play Store</string>  


⑤设置中新增一个监听,初始化Checkbox的逻辑:
packages/apps/Settings/src/com/android/settings/BootReceiver.java
内容如下:
[java] view plaincopy
  1. package com.android.settings;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.content.SharedPreferences;  
  7. import android.os.SystemClock;  
  8. import android.util.Log;  
  9. import android.os.SystemProperties;  
  10.   
  11. public class BootReceiver extends BroadcastReceiver{  
  12.   
  13.      @Override  
  14.      public void onReceive(Context arg0, Intent arg1) {  
  15.           // TODO Auto-generated method stub  
  16.             
  17.           String action = arg1.getAction();  
  18.           if(action.equals(Intent.ACTION_BOOT_COMPLETED))  
  19.           {   
  20.              SharedPreferences shared = arg0.getSharedPreferences("com.android.settings_preferences", Context.MODE_PRIVATE);  
  21.              boolean show_phonesky = shared.getBoolean("show_phonesky"false);  
  22.              if(show_phonesky){  
  23.                   SystemProperties.set("app.phonesky.show","1");       
  24.                }else{  
  25.                     SystemProperties.set("app.phonesky.show","0");       
  26.                }  
  27.           }  
  28.      }  
  29. }  


⑥在Settings的AndroidManifest文件中添加BroadcastReceiver的权限和声明:
[html] view plaincopy
  1. <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>  
  2. <receiver android:name=".BootReceiver">  
  3.             <intent-filter>  
  4.                 <action android:name="android.intent.action.BOOT_COMPLETED" />  
  5.                <category android:name="android.intent.category.DEFAULT" />          
  6.             </intent-filter>        
  7. </receiver>  


3.在init.rc中添加对应的服务和触发条件:
路径:mediatek/config/esky27_tb_ccn_mlc_kk/init.rc
[plain] view plaincopy
  1. +# ZJ Add START  
  2. +#Hide or Show Google Play Dynamicly  
  3. +#disabled:服务不会自动运行,必须显式地通过服务器来启动。  
  4. +#oneshot:当此服务退出时不会自动重启。  
  5. +service hidePhonesky /system/bin/hidePhonesky  
  6. +       disabled  
  7. +       oneshot      
  8. +service showPhonesky /system/bin/showPhonesky  
  9. +       disabled  
  10. +       oneshot      
  11. +#on property:sys.boot_completed=1  
  12. +#   start renamePhonesky  
  13. +on property:app.phonesky.show=1  
  14. +   start showPhonesky  
  15. +on property:app.phonesky.show=0  
  16. +   start hidePhonesky  
  17. +# ZJ Add END  


4.隐藏和显示应用的脚本:
隐藏应用:vendor/ThirdParty/App/dte/hidePhonesky
内容:
[plain] view plaincopy
  1. #!/system/bin/sh  
  2. #!/system/bin/busybox  
  3. mount -o remount,rw /system;  
  4. mv /system/priv-app/Phonesky.apk /system/priv-app/Phonesky.bak  

显示应用:vendor/ThirdParty/App/dte/showPhonesky
内容:
[java] view plaincopy
  1. #!/system/bin/sh  
  2. #!/system/bin/busybox  
  3. mount -o remount,rw /system;  
  4. mv /system/priv-app/Phonesky.bak /system/priv-app/Phonesky.apk  


5.拷贝脚本到system/bin目录下:
参考以下格式添加到对应的mk文件:
[plain] view plaincopy
  1. +#添加重命名GooglePlay脚本  
  2. +PRODUCT_COPY_FILES += \  
  3. +       vendor/ThirdParty/App/dte/hidePhonesky:system/bin/hidePhonesky \  
  4. +       vendor/ThirdParty/App/dte/showPhonesky:system/bin/showPhonesky \  
  5. +       vendor/ThirdParty/App/dte/Phonesky.bak:system/priv-app/Phonesky.bak  


7.修改链接电脑时的“总线已报告设备描述”显示名称

在:Android USB Gadget Driver中进行修改

[cpp] view plaincopy
  1. static const char longname[] = "Gadget Android";  
  2.   
  3. /* Default vendor and product IDs, overridden by userspace */  
  4. #define VENDOR_ID       0x0BB4  
  5. #define PRODUCT_ID      0x0001  
  6.   
  7. /* Default manufacturer and product string , overridden by userspace */  
  8. // 制造商  
  9. #define MANUFACTURER_STRING "MediaTek"  
  10.   
  11. // 设备描述,可以在“总线已报告设备描述”中看到  
  12. #define PRODUCT_STRING "MTP"  
  13.   
  14. #define USB_LOG "USB"  

8.开机动画包bootanimation的制作规范

除了一些特别厂商,其他大部分Android设备的开机动画包的文件名都是bootanimation.zip。可以通过adb查看system/media/路径查看,如果没有一般会调用系统开机动画,即android字样。这点三星有些不同,它的格式是bootsamsung.qmg。今天只说一下具有普适性的bootanimation.zip的制作。

这是三星的:



一、保证bootanimation.zip压缩包下的图片Size和格式完全统一

二、请写规范的配置文件desc.txt
desc.txt每个参数的实际意义,以如下的case为例:
480 854 10
p 1 0 part0
p 0 0 part1

1.第一行的参数前两位480和854分别表示要显示动画的width和height. 默认情况下应该与Display的width和height一致,如果设置比Display的size要小,则动画会居中显示,周边将用黑框填充.


2.第一行的第三个参数10是定义动画播放的预订帧率(FPS),这个帧率fps是指:每秒动画播放的帧数。此帧数是一个理想值,并不一定代表动画实际帧率,假设预订帧率为FPS_I,预订每一帧解析的时间t_I, 则t_I=1/FPS_I。

实际帧率的规则是:假设某一帧从解析到渲染耗时为t_r,当t_r<=t_l,则渲染完这一帧后,动画这个thread会sleep(t_l-t_r)的时间,也就说这一帧最后的耗时就t_l;假设某一帧从解析到渲染耗时为t_r,当t_r>t_l,则渲染完这一帧后,动画这个thread会马上开始下一帧,也就说这一帧最后的耗时就t_r。所以,desc.txt内设置的这个帧率并不能代表动画的实际帧率,实际的帧率是和系统开机的performance有关,因此不是说在desc.txt设置帧率越大越好,反而容易出现当某一帧耗时较长,就容易给用户某一帧卡顿的体验,目前这个FPS的值一般设置在13左右。当然,设置FPS为13并不是说系统的performance比较低,本身在开机动画阶段,系统进入Bootup Android阶段,许多进程需要启动,系统的主要工作应该集中与开机启动的进程,因此不建议动画的图片过于复杂,导致系统开机的Performance变差。


3.第二行和第三行情况类似,一般用于分别设置顺序播放和无限循环播放的相关参数.第一个参数p是google default的设计,请保留以p开头。第二个参数1表示这一行对应folder所需要循环播放的次数,如果是0则表示是无限循环播放,直到系统ready后通过被动退出。第三个参数0表示这一行对应folder里面的每一帧图片依次解析渲染完成后,要进入下一个循环,动画这个线程需要pause多久。第四个参数part0表示对应设置规则的folder的path。


Note1:默认的设计,都是将顺序播放的动画放在一个folder,定义这个folder所需要循环的次数;在无限循环的folder内放置一张图片,保证动画没有收到退出指令的时候,动画可以一直显示.


Note2:由于循环播放的folder中的每帧都是以纹理对象存储在纹理内存中再upload到GPU做渲染的,以便下次循环播放不需要重新解析.如果动画包中的图片太多或者图片的size很大时,则会导致占用较多的memory,因此为保证开机的performance,开机动画不建议太复杂.


注意事项:

1.压缩包里面除了desc.txt以外不能存在其他非图片格式的文件,否则会引起bootanimation程序崩溃,所以在windows系统下打包bootanimation.zip的时候,如果浏览过图片,要删掉生成隐藏文件Thumbs.db,或者在linux下打包。

2.压缩包内的文件结构是单层的,就是双击压缩包预览,直接看到part0,part1文件夹和sesc.txt文件,而不能是bootanimation文件夹。


3.desc.txt文件内容不要有多余的空行

4.制作完成后可以adb push到设备的/system/media/下面重启看一下效果。


9.修改内核版本编译信息中的user和host字段

有客户需要修改内核版本号中的字段,如下图红线标注区域:


修改方法:
以修改为“qizi@qizi001"为例:
打开kernel/scripts/mkcompile_h,做如下修改即可:
----------------------------------------------------------------------------------
@@ -73,8 +73,8 @@ UTS_TRUNCATE="cut -b -$UTS_LEN"

   echo \#define UTS_VERSION \"`echo $UTS_VERSION | $UTS_TRUNCATE`\"

-  echo \#define LINUX_COMPILE_BY \"`echo $LINUX_COMPILE_BY | $UTS_TRUNCATE`\"
-  echo \#define LINUX_COMPILE_HOST \"`echo $LINUX_COMPILE_HOST | $UTS_TRUNCATE`\"
+  echo \#define LINUX_COMPILE_BY \"`echo "qizi" | $UTS_TRUNCATE`\"
+  echo \#define LINUX_COMPILE_HOST \"`echo "qizi001" | $UTS_TRUNCATE`\"


   echo \#define LINUX_COMPILER \"`$CC -v 2>&1 | tail -n 1`\"
) > .tmpcompile
----------------------------------------------------------------------------------

附:
在对应的buildinfo文件中修改ro.build.user和ro.build.host两个属性不能达到预期效果。

10.Android 4.4限制Root权限的逻辑

android  4.4 版本后,su 权限严重被限制, 如无法直接访问data 区域,无法直接remount system image, 无法设置system property。

Google 不遗余力的提高android系统的安全性, 而针对su 这个即令人恨,又令人爱的命令,就痛下杀手。主要体现在三个方面:

1. 限制user 版本adbd process 的capabilities bound set。循环CAPBSET_DROP 动作,将Process的root capabilities 进行了强行限制。仅仅保留了CAP_SETUID, CAP_SETGID 这两项,用于run-as使用,可参考源码中system/core/adb/adb.c 中的drop_capabilities_bounding_set_if_need 函数。这样导致的情况是,在user 版本中usb debug 的su 受到极大的限制,仅仅能够模拟对应的uid/gid,而无法拿去真正的root 权限。

2. 限制所有app 的capabilities bound set, 在android 4.4 上,zygote fork app 时,特意对所有fork 出来的子进程,进行了CAPBSET_DROP 动作,将Process 的root capabilities 进行了强行限制。 使得即使这些APK 徒有Root 权限,而无真实的capabilites.

这样导致的情况是, app 执行su 时,其权限受到了严格的管控,比如无法逃脱DAC 权限管控。但因为依旧具有root uid/gid, 所以在framework 层的permission 限制上依旧畅通无阻。

3. SElinux 权限限制。 在user 版本上,没有导入有效的SElinux policy, 这样一旦本身受SElinux 限制的process 使用su 时,同样会受到SElinux 的限制。 目前只有4个process 会受到此影响,即zygote, netd, installd, vold.消除这种限制的手法即是external/sepolicy/android.mk 里面的

[plain] view plaincopy
  1. ifeq ($(TARGET_BUILD_VARIANT),user)  
  2. BOARD_SEPOLICY_IGNORE+=external/sepolicy/su.te  
  3. else  
  4. BOARD_SEPOLICY_IGNORE+=external/sepolicy/su_user.te  
  5. endif  

更新成:

[java] view plaincopy
  1. ifeq ($(TARGET_BUILD_VARIANT),user)  
  2. BOARD_SEPOLICY_IGNORE+=external/sepolicy/su_user.te  
  3. else  
  4. BOARD_SEPOLICY_IGNORE+=external/sepolicy/su_user.te  
  5. endif  

11.Android自动连接WiFi优先级规则,以及查看已连接WiFi的密码

目前Android的WiFi自动连接的优先级规则如下:

1、priority值的范围设定为[0,1000000),如果超出此范围则会reset;

2、最近连接过的AP拥有最高priority,在自动连接中会首先尝试连接它;
3、未连接过但是扫描到的AP,按其信号值强弱排序,越强的显示靠前,但是,还得综合
AP的安全因素,基本情况是:WPA/WPA2 > WEP > signal level high > signal level low > noise low > noise
high

4、如果是预置的AP,可能会人为设定其最高的priority;

看一下源码,代码路径:frameworks/base/wifi/java/android/net/wifi/


WifiConfigStore.java

[java] view plaincopy
  1. boolean selectNetwork(int netId) {  
  2.        if (VDBG) localLog("selectNetwork", netId);  
  3.        if (netId == INVALID_NETWORK_ID) return false;  
  4.   
  5.        // Reset the priority of each network at start or if it goes too high.  
  6.        if (mLastPriority == -1 || mLastPriority > 1000000) {  
  7.            Xlog.d(TAG, "Need to reset the priority, mLastPriority:" + mLastPriority);  
  8.            for(WifiConfiguration config : mConfiguredNetworks.values()) {  
  9.                if (config.networkId != INVALID_NETWORK_ID) {  
  10.                    config.priority = 0;  
  11.                    addOrUpdateNetworkNative(config);  
  12.                }  
  13.            }  
  14.            mLastPriority = 0;  
  15.        }  
  16.   
  17.        // Set to the highest priority and save the configuration.  
  18.        WifiConfiguration config = new WifiConfiguration();  
  19.        config.networkId = netId;  
  20.        config.priority = ++mLastPriority;  
  21.   
  22.        addOrUpdateNetworkNative(config);  
  23.        mWifiNative.saveConfig();  
  24.   
  25.        /* Enable the given network while disabling all other networks */  
  26.        enableNetworkWithoutBroadcast(netId, true);  
  27.   
  28.       /* Avoid saving the config & sending a broadcast to prevent settings 
  29.        * from displaying a disabled list of networks */  
  30.        return true;  
  31.    }  

有时候,我们会忘记已连接WiFi的密码,应用市场也有相关的应用可以帮我们读取。其实如有有Root权限,用RE文件管理器(Root Explorer)就可以查看了。文件路径:

/data/misc/wifi/sockets/wpa_supplicant.conf

每一个network包裹起来的就是一个连接过的WiFi热点,其中ssid是名字,psk就是密码了,也可以看到其他信息,包括加密类型key_mgmt和优先级priority,是否自动连接autojoin等,如下图:




12.让一个应用不在“全部应用列表”中显示

首先修改一下这个文件:

packages/apps/Settings/src/com/android/settings/applications/ApplicationsState.java

下面是Git Diff 的结果:

[java] view plaincopy
  1. diff --git a/packages/apps/Settings/src/com/android/settings/applications/ApplicationsState.java b/packages/apps/Settings/src/com/android/settings/applications/ApplicationsState.java  
  2. index e87d7cf..3f1a507 100644 (file)  
  3. --- a/packages/apps/Settings/src/com/android/settings/applications/ApplicationsState.java  
  4. +++ b/packages/apps/Settings/src/com/android/settings/applications/ApplicationsState.java  
  5. @@ -33,6 +33,8 @@ import java.util.HashMap;  
  6.  import java.util.List;  
  7.  import java.util.regex.Pattern;  
  8.    
  9. +import android.os.TCToolManager;  
  10. +  
  11.  /**  
  12.   * Keeps track of information about all installed applications, lazy-loading  
  13.   * as needed.  
  14. @@ -42,6 +44,8 @@ public class ApplicationsState {  
  15.      static final boolean DEBUG = false;  
  16.      static final boolean DEBUG_LOCKING = false;  
  17.    
  18. +       final TCToolManager mTCTool;  
  19. +  
  20.      public static interface Callbacks {  
  21.          public void onRunningStateChanged(boolean running);  
  22.          public void onPackageListChanged();  
  23. @@ -404,6 +408,8 @@ public class ApplicationsState {  
  24.          mThread.start();  
  25.          mBackgroundHandler = new BackgroundHandler(mThread.getLooper());  
  26.    
  27. +               mTCTool = (TCToolManager)mContext.getSystemService(Context.TCHIP_TOOL_SERVICE);  
  28. +  
  29.          // Only the owner can see all apps.  
  30.          if (UserHandle.myUserId() == 0) {  
  31.              mRetrieveFlags = PackageManager.GET_UNINSTALLED_PACKAGES |  
  32. @@ -548,6 +554,13 @@ public class ApplicationsState {  
  33.                          if (DEBUG_LOCKING) Log.v(TAG, "rebuild acquired lock");  
  34.                          AppEntry entry = getEntryLocked(info);  
  35.                          entry.ensureLabel(mContext);  
  36. +  
  37. +                        if (mTCTool.isHide(info.packageName)) {  
  38. +                            if(TCToolManager.DEBUG)  
  39. +                                TCToolManager.Log("hide app:" + info.loadLabel(mPm) + ":" + info.packageName);  
  40. +                            continue;  
  41. +                        }  
  42. +  
  43.                          if (DEBUG) Log.i(TAG, "Using " + info.packageName + ": " + entry);  
  44.                          filteredApps.add(entry);  
  45.                          if (DEBUG_LOCKING) Log.v(TAG, "rebuild releasing lock");  

然后添加以下三个文件到指定路径:

frameworks/base/core/java/android/os/ITCToolService.aidl:

[java] view plaincopy
  1. /** 
  2. * Copyright (c) 2007, The Android Open Source Project 
  3. * 
  4. * Licensed under the Apache License, Version 2.0 (the "License"); 
  5. * you may not use this file except in compliance with the License. 
  6. * You may obtain a copy of the License at 
  7. * 
  8. *     http://www.apache.org/licenses/LICENSE-2.0 
  9. * 
  10. * Unless required by applicable law or agreed to in writing, software 
  11. * distributed under the License is distributed on an "AS IS" BASIS, 
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13. * See the License for the specific language governing permissions and 
  14. * limitations under the License. 
  15. */  
  16.   
  17. package android.os;  
  18.    
  19. import android.content.Context;  
  20.    
  21.  /** {@hide} */  
  22. interface ITCToolService  
  23. {  
  24.     String getVersion();  
  25.        
  26.      boolean isHide(String name);  
  27.  }  


frameworks/base/core/java/android/os/TCToolManager.java:

[java] view plaincopy
  1.  1 /* 
  2.  2  * Copyright (C) 2006 The Android Open Source Project 
  3.  3  * 
  4.  4  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  5  * you may not use this file except in compliance with the License. 
  6.  6  * You may obtain a copy of the License at 
  7.  7  * 
  8.  8  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  9  * 
  10. 10  * Unless required by applicable law or agreed to in writing, software 
  11. 11  * distributed under the License is distributed on an "AS IS" BASIS, 
  12. 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13. 13  * See the License for the specific language governing permissions and 
  14. 14  * limitations under the License. 
  15. 15  */  
  16. 16   
  17. 17 package android.os;  
  18. 18   
  19. 19 import android.util.Log;  
  20. 20   
  21. 21   
  22. 22   
  23. 23 public class TCToolManager  
  24. 24 {  
  25. 25     private static final String TAG = "TCToolManager";  
  26. 26     public static final boolean DEBUG = true;  
  27. 27   
  28. 28     ITCToolService mService;  
  29. 29   
  30. 30     /** @hide */  
  31. 31     public TCToolManager(ITCToolService service)  
  32. 32     {  
  33. 33         mService = service;  
  34. 34         Log.d(TAG, "version: " + getVersion());  
  35. 35     }  
  36. 36   
  37. 37     public String getVersion() {  
  38. 38   
  39. 39         try {  
  40. 40             return mService.getVersion();  
  41. 41         } catch (RemoteException e) {  
  42. 42         }  
  43. 43   
  44. 44         return null;  
  45. 45     }  
  46. 46       
  47. 47     public boolean isHide(String name) {  
  48. 48         try {  
  49. 49             return mService.isHide(name);  
  50. 50         } catch (RemoteException e) {  
  51. 51         }  
  52. 52   
  53. 53         return false;  
  54. 54     }  
  55. 55       
  56. 56     // debug log out  
  57. 57     static public void Log(String log) {  
  58. 58         // TODO Auto-generated method stub  
  59. 59         Log.d(TAG, log);  
  60. 60     }  
  61. 61 }  


frameworks/base/services/java/com/android/server/TCToolService.java:
[java] view plaincopy
  1.   1 /* 
  2.   2  * Copyright (C) 2008 The Android Open Source Project 
  3.   3  * 
  4.   4  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.   5  * you may not use this file except in compliance with the License. 
  6.   6  * You may obtain a copy of the License at 
  7.   7  * 
  8.   8  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.   9  * 
  10.  10  * Unless required by applicable law or agreed to in writing, software 
  11.  11  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  13  * See the License for the specific language governing permissions and 
  14.  14  * limitations under the License. 
  15.  15  */  
  16.  16   
  17.  17 package com.android.server;  
  18.  18   
  19.  19 import android.content.Context;  
  20.  20 import android.content.Intent;  
  21.  21 import android.content.SharedPreferences;  
  22.  22 import android.os.ITCToolService;  
  23.  23 import android.os.storage.StorageEventListener;  
  24.  24 import android.os.storage.StorageManager;  
  25.  25 import android.preference.PreferenceManager;  
  26.  26 import android.util.Log;  
  27.  27 import android.util.Slog;  
  28.  28   
  29.  29 import java.io.BufferedReader;  
  30.  30 import java.io.DataOutputStream;  
  31.  31 import java.io.File;  
  32.  32 import java.io.FileInputStream;  
  33.  33 import java.io.FileNotFoundException;  
  34.  34 import java.io.FileOutputStream;  
  35.  35 import java.io.IOException;  
  36.  36 import java.io.InputStreamReader;  
  37.  37 import java.util.ArrayList;  
  38.  38 import java.util.Calendar;  
  39.  39   
  40.  40 public class TCToolService extends ITCToolService.Stub {  
  41.  41     private static final String TAG = "TCToolService";  
  42.  42     private static final String VERSION = "T-CHIP tool V1.0.1";  
  43.  43     private Context mContext;  
  44.  44     private final File mToolDir;  
  45.  45     private boolean inited = false;  
  46.  46   
  47.  47     private static final boolean DEBUG = true;  
  48.  48   
  49.  49     private static final String FILE = "hideapk.txt";  
  50.  50   
  51.  51     private static final String EXTSD_PATH = "/mnt/external_sd";  
  52.  52   
  53.  53     private static final String SYS_PATH = "/system/usr/data";  
  54.  54   
  55.  55     private ArrayList<String> mHideList = new ArrayList<String>();  
  56.  56   
  57.  57     private static final Object sLock = new Object();  
  58.  58     private StorageManager mStorageManager = null;  
  59.  59   
  60.  60     public String getVersion() {  
  61.  61         return VERSION;  
  62.  62     }  
  63.  63   
  64.  64     TCToolService(Context context, File path) {  
  65.  65         mContext = context;  
  66.  66         mToolDir = path;  
  67.  67   
  68.  68         initHideLocked(false);  
  69.  69     }  
  70.  70   
  71.  71     private void initHideLocked(boolean forceUpdate) {  
  72.  72         synchronized (sLock) {  
  73.  73             if (!inited || forceUpdate) {  
  74.  74                 inited = true;  
  75.  75                 initHide(forceUpdate);  
  76.  76             }  
  77.  77         }  
  78.  78     }  
  79.  79   
  80.  80     private void initHide(boolean forceUpdate) {  
  81.  81         File hideFile = null;  
  82.  82         File outFile = new File(mToolDir, FILE);  
  83.  83         boolean bWriteCfg = true;  
  84.  84   
  85.  85         if (!mToolDir.exists()) {  
  86.  86             mToolDir.mkdirs();  
  87.  87         }  
  88.  88   
  89.  89         if (outFile.exists() && !forceUpdate) {  
  90.  90             bWriteCfg = false;  
  91.  91         } else if ((hideFile = new File(EXTSD_PATH + "/" + FILE)).exists()) {  
  92.  92             setSDHideState(true);  
  93.  93             setSDHideDate(hideFile.lastModified());  
  94.  94             if (DEBUG)  
  95.  95                 Log.d(TAG, "Set bSDHideExists");  
  96.  96         }  
  97.  97   
  98.  98         if (DEBUG && null != hideFile)  
  99.  99                 Log.d(TAG, "Load hideapk.txt from " + hideFile.getPath());  
  100. 100           
  101. 101         mHideList.clear();  
  102. 102         readHideCfg(new File(SYS_PATH + "/" + FILE), mHideList);  
  103. 103         readHideCfg(hideFile, mHideList);  
  104. 104   
  105. 105         if (bWriteCfg && !mHideList.isEmpty()) {  
  106. 106             if (DEBUG)  
  107. 107                 Log.d(TAG, "Save hideapk.txt to app file");  
  108. 108             writeHideCfg(outFile, mHideList);  
  109. 109         }  
  110. 110   
  111. 111         if (null == mStorageManager) {  
  112. 112             mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);  
  113. 113             mStorageManager.registerListener(mStorageListener);  
  114. 114         }  
  115. 115     }  
  116. 116   
  117. 117     private void writeHideCfg(File hideFile, ArrayList<String> hidelist) {  
  118. 118         DataOutputStream out = null;  
  119. 119   
  120. 120         try {  
  121. 121             out = new DataOutputStream(new FileOutputStream(hideFile));  
  122. 122             for (String hide : hidelist) {  
  123. 123                 // out.writeUTF(hide + "\n");  
  124. 124                 out.writeBytes(hide + "\n");  
  125. 125             }  
  126. 126             out.flush();  
  127. 127         } catch (FileNotFoundException e) {  
  128. 128             // Ignore  
  129. 129             e.printStackTrace();  
  130. 130         } catch (IOException e) {  
  131. 131             e.printStackTrace();  
  132. 132             // noinspection ResultOfMethodCallIgnored  
  133. 133             hideFile.delete();  
  134. 134         } finally {  
  135. 135             if (out != null) {  
  136. 136                 try {  
  137. 137                     out.close();  
  138. 138                 } catch (IOException e) {  
  139. 139                     // Ignore  
  140. 140                 }  
  141. 141             }  
  142. 142         }  
  143. 143     }  
  144. 144   
  145. 145     private void readHideCfg(File hideFile, ArrayList<String> hidelist) {  
  146. 146         if (hideFile == null || !hideFile.exists())  
  147. 147             return;  
  148. 148   
  149. 149         try {  
  150. 150             FileInputStream inStream = new FileInputStream(hideFile);  
  151. 151   
  152. 152             if (inStream != null) {  
  153. 153                 BufferedReader rbf = new BufferedReader(new InputStreamReader(inStream));  
  154. 154   
  155. 155                 String linebuf = rbf.readLine();  
  156. 156                 while (linebuf != null) {  
  157. 157                     linebuf = linebuf.trim();  
  158. 158                     if (!linebuf.startsWith("#"0) && linebuf.length() != 0) {  
  159. 159                         if (DEBUG)  
  160. 160                             Log.d(TAG, "readHideCfg: " + linebuf);  
  161. 161                         hidelist.add(linebuf);  
  162. 162                     }  
  163. 163                     linebuf = rbf.readLine();  
  164. 164                 }  
  165. 165                 return;  
  166. 166             }  
  167. 167         } catch (FileNotFoundException e) {  
  168. 168             Log.e(TAG, "readHideCfg: " + "File is not found");  
  169. 169         } catch (Exception e) {  
  170. 170             Log.e(TAG, "Read hide config error");  
  171. 171             e.printStackTrace();  
  172. 172         }  
  173. 173     }  
  174. 174   
  175. 175     public boolean isHide(String name) {  
  176. 176         synchronized (sLock) {  
  177. 177             if (mHideList.contains(name)) {  
  178. 178                 return true;  
  179. 179             } else {  
  180. 180                 return false;  
  181. 181             }  
  182. 182         }  
  183. 183     }  
  184. 184   
  185. 185     /* 
  186. 186      * change condition: 1. original not exists but exists currently 2. current 
  187. 187      * is newer than original 3. exclude original exists but not exists 
  188. 188      * currently, keep original hide list 
  189. 189      */  
  190. 190     private boolean isSDHideFileChange() {  
  191. 191         File hideFile = new File(EXTSD_PATH + "/" + FILE);  
  192. 192   
  193. 193         if (DEBUG)  
  194. 194             Log.d(TAG, "isSDHideFileChange: new state-->" + hideFile.exists() + ", old state-->"  
  195. 195                     + getSDHideState());  
  196. 196   
  197. 197         if (hideFile.exists()) {  
  198. 198             /* original not exists but exists currently */  
  199. 199             if (!getSDHideState())  
  200. 200                 return true;  
  201. 201   
  202. 202             if (DEBUG) {  
  203. 203                 Calendar cal = Calendar.getInstance();  
  204. 204                 cal.setTimeInMillis(hideFile.lastModified());  
  205. 205                 Log.d(TAG, "isSDHideFileChange: new date-->" + hideFile.lastModified() + "="  
  206. 206                         + cal.getTime().toLocaleString());  
  207. 207                 cal.setTimeInMillis(getSDHideDate());  
  208. 208                 Log.d(TAG, "isSDHideFileChange: old date-->" + getSDHideDate() + "="  
  209. 209                         + cal.getTime().toLocaleString());  
  210. 210             }  
  211. 211             /* current is newer than original */  
  212. 212             if ((hideFile.lastModified() > getSDHideDate())) {  
  213. 213                 return true;  
  214. 214             }  
  215. 215         }  
  216. 216   
  217. 217         return false;  
  218. 218     }  
  219. 219   
  220. 220     private void setSDHideState(boolean state) {  
  221. 221         SharedPreferences preferences = PreferenceManager  
  222. 222                 .getDefaultSharedPreferences(mContext);  
  223. 223         SharedPreferences.Editor editor = preferences.edit();  
  224. 224   
  225. 225         editor.putBoolean("sd_hide_state", state);  
  226. 226         editor.commit();  
  227. 227     }  
  228. 228   
  229. 229     private boolean getSDHideState() {  
  230. 230         SharedPreferences preferences = PreferenceManager  
  231. 231                 .getDefaultSharedPreferences(mContext);  
  232. 232   
  233. 233         return preferences.getBoolean("sd_hide_state"false);  
  234. 234   
  235. 235     }  
  236. 236   
  237. 237     private void setSDHideDate(long date) {  
  238. 238         SharedPreferences preferences = PreferenceManager  
  239. 239                 .getDefaultSharedPreferences(mContext);  
  240. 240         SharedPreferences.Editor editor = preferences.edit();  
  241. 241   
  242. 242         editor.putLong("sd_hide_date", date);  
  243. 243         editor.commit();  
  244. 244     }  
  245. 245   
  246. 246     private long getSDHideDate() {  
  247. 247         SharedPreferences preferences = PreferenceManager  
  248. 248                 .getDefaultSharedPreferences(mContext);  
  249. 249   
  250. 250         return preferences.getLong("sd_hide_date", -1);  
  251. 251   
  252. 252     }  
  253. 253   
  254. 254     StorageEventListener mStorageListener = new StorageEventListener() {  
  255. 255   
  256. 256         @Override  
  257. 257         public void onStorageStateChanged(String path, String oldState, String newState) {  
  258. 258             if (DEBUG)  
  259. 259                 Log.d(TAG, "onStorageStateChanged: " + path + "--" + newState);  
  260. 260             if (newState.equals("mounted") && path.equals(EXTSD_PATH)) {  
  261. 261                 if (isSDHideFileChange()) {  
  262. 262                     initHideLocked(true);  
  263. 263   
  264. 264                     // TODO send Broadcast ACTION_TCTOOL_SDHIDE_CHANGED  
  265. 265                     Intent it = new Intent(Intent.ACTION_TCTOOL_SDHIDE_CHANGED);  
  266. 266                     mContext.sendBroadcast(it);  
  267. 267                     if (DEBUG)  
  268. 268                         Log.d(TAG, "Send sendBroadcast: ACTION_TCTOOL_SDHIDE_CHANGED");  
  269. 269                 }  
  270. 270             }  
  271. 271         }  
  272. 272     };  
  273. 273 }  

0 0
原创粉丝点击