本文转载自: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地址,也不需取值
- 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,具体如下:
- public String getClientDeviceName(String deviceAddress) {//传mac地址进来
- enforceAccessPermission();
- if (TextUtils.isEmpty(deviceAddress)) {
- return null;
- }
- //读取对应的文件信息
- for (String s : readClientList("/data/misc/dhcp/dnsmasq.leases")) {
- if (s.indexOf(deviceAddress) != -1) {
- String[] fields = s.split(" ");
- //校验数据是否破损
- if (fields.length > 4) {
- //返回第4个栏位
- return fields[3];
- }
- }
- }
- return null;
- }
fastboot 是android 默认的一种debug 方法,它的好处是在进入linux kernel 之前
即可操作。
默认fastboot 支持的命令:
- usage: fastboot [ <option> ] <command>
- commands:
- update <filename> reflash device from
- update.zip
- flashall flash boot
- + recovery + system
- flash <partition> [ <filename> ] write a file to a flash
- partition
- erase <partition> erase a flash
- partition
- format <partition> format a flash
- partition
- getvar <variable> display a
- bootloader variable
- boot <kernel> [ <ramdisk> ] download and boot kernel
- flash:raw boot <kernel> [ <ramdisk> ] create bootimage and flash it
- devices list all
- connected devices
- continue continue
- with autoboot
- reboot reboot
- device normally
- reboot-bootloader reboot device
- into bootloader
- help show this
- help message
- options:
- -w erase userdata and cache (and
- format if supported by partition type)
- -u do not first erase partition
- before formatting
- -s <specific device> specify device serial number or path to
- device port
- -l with "devices", lists device
- paths
- -p <product> specify product name
- -c <cmdline> override kernel commandline
- -i <vendor id> specify a custom USB vendor id
- -b <base_addr> specify a custom kernel base
- address
- -n <page size> specify the nand page size.
- default: 2048
- -S <size>[K|M|G] automatically sparse files
- greater than size. 0 to disable
fastboot 提供了扩展的命令符号
- fastboot oem command args
(1).在bootable/bootloader/lk/app/mt_boot/fastboot.c
的fastboot_init 函数中添加一个新的register
- //第一个参数是命令的名称
- //第二个参数是命令的执行函数
- //第三个参数是在security IC 中是否还提供此命令
- fastboot_register("oem hello", cmd_oem_hello, FALSE);
void cmd_oem_hello(const char *arg, void *data, unsigned size) {
- //注意args 是以command 结束开始,即" args"
- if(!strncmp(arg, " OK", strlen(" OK"))){
- fastboot_okey("OK");
- }else{
- fastboot_fail("Not OK");
- }
- }
您可以使用下面已经定义好的三个函数与PC 端交互
- fastboot_okey(const char* result);
- fastboot_fail(const char* reason);
- fastboot_info(const char* reason);
注意这三个打印字符串的长度都不能超过64-1-4 = 59 个字
有些手机会有附加的功能键,比如拍照实体键,甚至有两端式的,轻按聚焦,深按拍照。那么类似功能是如何在Android手机上实现的呢?
可以修改源码下
frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java文件中的如下方法:
- public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event,int policyFlags)
找到如下代码段:
- else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
- if (down && repeatCount == 0 && !keyguardOn) {
- showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
- }
- return -1;
- }
在这个else if后面增加相应代码:
- else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
- if (down && repeatCount == 0 && !keyguardOn) {
- showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
- }
- return -1;
- } //add begin
- else if (keyCode == KeyEvent.KEYCODE_XXX) {
- if (down && repeatCount == 0 && !keyguardOn) {
- mContext.startActivity(new Intent("intent.xxx")
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
- }
- return -1;
- } // add end
注意:
1、上面写的KeyEvent.KEYCODE_XXX是预设定好的实体键的键值,根据需要来设定即可;
2、startActivity(new Intent("intent.xxx")中的intent.xxx需要根据所启动的activity来写
Google原生的Android系统一般是没有“重启”这个选项的。有时候重启也是不可或缺的一个Feature,那么如何在源码环境下添加这个选项呢?
1. 在frameworks\base\core\res\res\values\strings.xml
中添加标签:
- <span style="font-size:14px;"><!--zms add start-->
- <!-- label for item that power reboot in phone options dialog -->
- <string name="zms_global_action_power_reboot">Reboot</string>
- <!--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行有这样的代码:
- mItems = Lists.newArrayList(
- // silent mode
- mSilentModeToggle,
- // next: airplane mode
- mAirplaneModeOn,
- // last: power off
在这里,我们添加power reboot 的新的item.
具体这个mItems 更新为如下:
- mItems = Lists.newArrayList(
- // silent mode
- mSilentModeToggle,
- // next: airplane mode
- mAirplaneModeOn,
- // last: power off
- new SinglePressAction(
- com.android.internal.R.drawable.ic_lock_power_off,
- R.string.global_action_power_off) {
- public void onPress() {
- // shutdown by making sure radio and power are handled
- accordingly.
- ShutdownThread.shutdown(mContext, true);
- }
- public boolean showDuringKeyguard() {
- return true;
- }
- public boolean showBeforeProvisioning() {
- return true;
- }
- }//zms add start
- ,
- new SinglePressAction(
- com.android.internal.R.drawable.zms_ic_lock_power_reboot,
- R.string.zms_global_action_power_reboot) {
- public void onPress() {
- // reboot by making sure radio and power are handled
- accordingly.
- ShutdownThread.reboot(mContext, null, true);
- }
- public boolean showDuringKeyguard() {
- return true;
- }
- public boolean showBeforeProvisioning() {
- return true;
- }
- }
- //zms add end.
- );
经过这样的添加/修改后,这项feature 即可运行。
注意如果测试的话,因为有修改framework 中的文件,最好new 一下整个工程。
另外还需要修改一下ShutdownThread.java 中的那个dialog 显示描述,不然将依旧看到“关机”的信息。
位置:frameworks/base/services/java/com/android/server/power/ShutdownThread.java
不同版本的代码位置可能有所差别,可以在根目录下find一下:
- find -name ShutdownThread.java
如下:
- sConfirmDialog = new AlertDialog.Builder(context)
- .setTitle((mReboot && !mRebootSafeMode)
- ? com.android.internal.R.string.reboot_title
- : (mRebootSafeMode
- ? com.android.internal.R.string.reboot_safemode_title
- : com.android.internal.R.string.power_off))
- .setMessage(resourceId)
- .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- beginShutdownSequence(context);
- if (sConfirmDialog != null) {
- sConfirmDialog = null;
- }
- }
- })
- .setNegativeButton(com.android.internal.R.string.no, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- synchronized (sIsStartedGuard) {
- sIsStarted = false;
- }
- if (sConfirmDialog != null) {
- sConfirmDialog = null;
- }
- }
- })
- .create();
6.使用init.rc触发脚本实现隐藏内置应用
【实现逻辑】
- { "app.launcher.start", AID_SYSTEM, 0},
- "app.phonesky.show", AID_SYSTEM, 0}, //Add By zj
- { "cdma.", AID_RADIO, 0 }, //Add by gfzhu VIA
- private static final String SHOW_PHONESKY = "show_phonesky";
- private CheckBoxPreference mShowPhonesky;
- mShowPhonesky = findAndInitCheckboxPref(SHOW_PHONESKY);
- (BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB) : 0);
- + } else if (preference == mShowPhonesky) { // ZJ Add
- + if(mShowPhonesky.isChecked())
- + {
- + SystemProperties.set("app.phonesky.show","1");
- + }else{
- + SystemProperties.set("app.phonesky.show","0");
- + }
- } else if (preference == mBtHciSnoopLog) {
- android:targetClass="com.android.settings.SetFullBackupPassword" />
- </PreferenceScreen>
- + <CheckBoxPreference
- + android:key="show_phonesky"
- + android:title="@string/show_phonesky"
- + />
- <CheckBoxPreference
- <string name="show_phonesky">Show Google Play Store</string>
- package com.android.settings;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.SharedPreferences;
- import android.os.SystemClock;
- import android.util.Log;
- import android.os.SystemProperties;
- public class BootReceiver extends BroadcastReceiver{
- @Override
- public void onReceive(Context arg0, Intent arg1) {
- // TODO Auto-generated method stub
- String action = arg1.getAction();
- if(action.equals(Intent.ACTION_BOOT_COMPLETED))
- {
- SharedPreferences shared = arg0.getSharedPreferences("com.android.settings_preferences", Context.MODE_PRIVATE);
- boolean show_phonesky = shared.getBoolean("show_phonesky", false);
- if(show_phonesky){
- SystemProperties.set("app.phonesky.show","1");
- }else{
- SystemProperties.set("app.phonesky.show","0");
- }
- }
- }
- }
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
- <receiver android:name=".BootReceiver">
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </receiver>
- +# ZJ Add START
- +#Hide or Show Google Play Dynamicly
- +#disabled:服务不会自动运行,必须显式地通过服务器来启动。
- +#oneshot:当此服务退出时不会自动重启。
- +service hidePhonesky /system/bin/hidePhonesky
- + disabled
- + oneshot
- +service showPhonesky /system/bin/showPhonesky
- + disabled
- + oneshot
- +#on property:sys.boot_completed=1
- +# start renamePhonesky
- +on property:app.phonesky.show=1
- + start showPhonesky
- +on property:app.phonesky.show=0
- + start hidePhonesky
- +# ZJ Add END
- #!/system/bin/sh
- #!/system/bin/busybox
- mount -o remount,rw /system;
- mv /system/priv-app/Phonesky.apk /system/priv-app/Phonesky.bak
内容:
- #!/system/bin/sh
- #!/system/bin/busybox
- mount -o remount,rw /system;
- mv /system/priv-app/Phonesky.bak /system/priv-app/Phonesky.apk
- +#添加重命名GooglePlay脚本
- +PRODUCT_COPY_FILES += \
- + vendor/ThirdParty/App/dte/hidePhonesky:system/bin/hidePhonesky \
- + vendor/ThirdParty/App/dte/showPhonesky:system/bin/showPhonesky \
- + vendor/ThirdParty/App/dte/Phonesky.bak:system/priv-app/Phonesky.bak
- static const char longname[] = "Gadget Android";
- /* Default vendor and product IDs, overridden by userspace */
- #define VENDOR_ID 0x0BB4
- #define PRODUCT_ID 0x0001
- /* Default manufacturer and product string , overridden by userspace */
- // 制造商
- #define MANUFACTURER_STRING "MediaTek"
- // 设备描述,可以在“总线已报告设备描述”中看到
- #define PRODUCT_STRING "MTP"
- #define USB_LOG "USB"
8.开机动画包bootanimation的制作规范
除了一些特别厂商,其他大部分Android设备的开机动画包的文件名都是bootanimation.zip。可以通过adb查看system/media/路径查看,如果没有一般会调用系统开机动画,即android字样。这点三星有些不同,它的格式是bootsamsung.qmg。今天只说一下具有普适性的bootanimation.zip的制作。
这是三星的:
一、保证bootanimation.zip压缩包下的图片Size和格式完全统一
二、请写规范的配置文件desc.txtdesc.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 里面的
- ifeq ($(TARGET_BUILD_VARIANT),user)
- BOARD_SEPOLICY_IGNORE+=external/sepolicy/su.te
- else
- BOARD_SEPOLICY_IGNORE+=external/sepolicy/su_user.te
- endif
更新成:
- ifeq ($(TARGET_BUILD_VARIANT),user)
- BOARD_SEPOLICY_IGNORE+=external/sepolicy/su_user.te
- else
- BOARD_SEPOLICY_IGNORE+=external/sepolicy/su_user.te
- 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
- boolean selectNetwork(int netId) {
- if (VDBG) localLog("selectNetwork", netId);
- if (netId == INVALID_NETWORK_ID) return false;
- // Reset the priority of each network at start or if it goes too high.
- if (mLastPriority == -1 || mLastPriority > 1000000) {
- Xlog.d(TAG, "Need to reset the priority, mLastPriority:" + mLastPriority);
- for(WifiConfiguration config : mConfiguredNetworks.values()) {
- if (config.networkId != INVALID_NETWORK_ID) {
- config.priority = 0;
- addOrUpdateNetworkNative(config);
- }
- }
- mLastPriority = 0;
- }
- // Set to the highest priority and save the configuration.
- WifiConfiguration config = new WifiConfiguration();
- config.networkId = netId;
- config.priority = ++mLastPriority;
- addOrUpdateNetworkNative(config);
- mWifiNative.saveConfig();
- /* Enable the given network while disabling all other networks */
- enableNetworkWithoutBroadcast(netId, true);
- /* Avoid saving the config & sending a broadcast to prevent settings
- * from displaying a disabled list of networks */
- return true;
- }
有时候,我们会忘记已连接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 的结果:
- diff --git a/packages/apps/Settings/src/com/android/settings/applications/ApplicationsState.java b/packages/apps/Settings/src/com/android/settings/applications/ApplicationsState.java
- index e87d7cf..3f1a507 100644 (file)
- --- a/packages/apps/Settings/src/com/android/settings/applications/ApplicationsState.java
- +++ b/packages/apps/Settings/src/com/android/settings/applications/ApplicationsState.java
- @@ -33,6 +33,8 @@ import java.util.HashMap;
- import java.util.List;
- import java.util.regex.Pattern;
- +import android.os.TCToolManager;
- +
- /**
- * Keeps track of information about all installed applications, lazy-loading
- * as needed.
- @@ -42,6 +44,8 @@ public class ApplicationsState {
- static final boolean DEBUG = false;
- static final boolean DEBUG_LOCKING = false;
- + final TCToolManager mTCTool;
- +
- public static interface Callbacks {
- public void onRunningStateChanged(boolean running);
- public void onPackageListChanged();
- @@ -404,6 +408,8 @@ public class ApplicationsState {
- mThread.start();
- mBackgroundHandler = new BackgroundHandler(mThread.getLooper());
- + mTCTool = (TCToolManager)mContext.getSystemService(Context.TCHIP_TOOL_SERVICE);
- +
- // Only the owner can see all apps.
- if (UserHandle.myUserId() == 0) {
- mRetrieveFlags = PackageManager.GET_UNINSTALLED_PACKAGES |
- @@ -548,6 +554,13 @@ public class ApplicationsState {
- if (DEBUG_LOCKING) Log.v(TAG, "rebuild acquired lock");
- AppEntry entry = getEntryLocked(info);
- entry.ensureLabel(mContext);
- +
- + if (mTCTool.isHide(info.packageName)) {
- + if(TCToolManager.DEBUG)
- + TCToolManager.Log("hide app:" + info.loadLabel(mPm) + ":" + info.packageName);
- + continue;
- + }
- +
- if (DEBUG) Log.i(TAG, "Using " + info.packageName + ": " + entry);
- filteredApps.add(entry);
- if (DEBUG_LOCKING) Log.v(TAG, "rebuild releasing lock");
然后添加以下三个文件到指定路径:
frameworks/base/core/java/android/os/ITCToolService.aidl:
- /**
- * Copyright (c) 2007, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package android.os;
- import android.content.Context;
- /** {@hide} */
- interface ITCToolService
- {
- String getVersion();
- boolean isHide(String name);
- }
- 1 /*
- 2 * Copyright (C) 2006 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.util.Log;
- 20
- 21
- 22
- 23 public class TCToolManager
- 24 {
- 25 private static final String TAG = "TCToolManager";
- 26 public static final boolean DEBUG = true;
- 27
- 28 ITCToolService mService;
- 29
- 30 /** @hide */
- 31 public TCToolManager(ITCToolService service)
- 32 {
- 33 mService = service;
- 34 Log.d(TAG, "version: " + getVersion());
- 35 }
- 36
- 37 public String getVersion() {
- 38
- 39 try {
- 40 return mService.getVersion();
- 41 } catch (RemoteException e) {
- 42 }
- 43
- 44 return null;
- 45 }
- 46
- 47 public boolean isHide(String name) {
- 48 try {
- 49 return mService.isHide(name);
- 50 } catch (RemoteException e) {
- 51 }
- 52
- 53 return false;
- 54 }
- 55
- 56 // debug log out
- 57 static public void Log(String log) {
- 58 // TODO Auto-generated method stub
- 59 Log.d(TAG, log);
- 60 }
- 61 }
- 1 /*
- 2 * Copyright (C) 2008 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 com.android.server;
- 18
- 19 import android.content.Context;
- 20 import android.content.Intent;
- 21 import android.content.SharedPreferences;
- 22 import android.os.ITCToolService;
- 23 import android.os.storage.StorageEventListener;
- 24 import android.os.storage.StorageManager;
- 25 import android.preference.PreferenceManager;
- 26 import android.util.Log;
- 27 import android.util.Slog;
- 28
- 29 import java.io.BufferedReader;
- 30 import java.io.DataOutputStream;
- 31 import java.io.File;
- 32 import java.io.FileInputStream;
- 33 import java.io.FileNotFoundException;
- 34 import java.io.FileOutputStream;
- 35 import java.io.IOException;
- 36 import java.io.InputStreamReader;
- 37 import java.util.ArrayList;
- 38 import java.util.Calendar;
- 39
- 40 public class TCToolService extends ITCToolService.Stub {
- 41 private static final String TAG = "TCToolService";
- 42 private static final String VERSION = "T-CHIP tool V1.0.1";
- 43 private Context mContext;
- 44 private final File mToolDir;
- 45 private boolean inited = false;
- 46
- 47 private static final boolean DEBUG = true;
- 48
- 49 private static final String FILE = "hideapk.txt";
- 50
- 51 private static final String EXTSD_PATH = "/mnt/external_sd";
- 52
- 53 private static final String SYS_PATH = "/system/usr/data";
- 54
- 55 private ArrayList<String> mHideList = new ArrayList<String>();
- 56
- 57 private static final Object sLock = new Object();
- 58 private StorageManager mStorageManager = null;
- 59
- 60 public String getVersion() {
- 61 return VERSION;
- 62 }
- 63
- 64 TCToolService(Context context, File path) {
- 65 mContext = context;
- 66 mToolDir = path;
- 67
- 68 initHideLocked(false);
- 69 }
- 70
- 71 private void initHideLocked(boolean forceUpdate) {
- 72 synchronized (sLock) {
- 73 if (!inited || forceUpdate) {
- 74 inited = true;
- 75 initHide(forceUpdate);
- 76 }
- 77 }
- 78 }
- 79
- 80 private void initHide(boolean forceUpdate) {
- 81 File hideFile = null;
- 82 File outFile = new File(mToolDir, FILE);
- 83 boolean bWriteCfg = true;
- 84
- 85 if (!mToolDir.exists()) {
- 86 mToolDir.mkdirs();
- 87 }
- 88
- 89 if (outFile.exists() && !forceUpdate) {
- 90 bWriteCfg = false;
- 91 } else if ((hideFile = new File(EXTSD_PATH + "/" + FILE)).exists()) {
- 92 setSDHideState(true);
- 93 setSDHideDate(hideFile.lastModified());
- 94 if (DEBUG)
- 95 Log.d(TAG, "Set bSDHideExists");
- 96 }
- 97
- 98 if (DEBUG && null != hideFile)
- 99 Log.d(TAG, "Load hideapk.txt from " + hideFile.getPath());
- 100
- 101 mHideList.clear();
- 102 readHideCfg(new File(SYS_PATH + "/" + FILE), mHideList);
- 103 readHideCfg(hideFile, mHideList);
- 104
- 105 if (bWriteCfg && !mHideList.isEmpty()) {
- 106 if (DEBUG)
- 107 Log.d(TAG, "Save hideapk.txt to app file");
- 108 writeHideCfg(outFile, mHideList);
- 109 }
- 110
- 111 if (null == mStorageManager) {
- 112 mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
- 113 mStorageManager.registerListener(mStorageListener);
- 114 }
- 115 }
- 116
- 117 private void writeHideCfg(File hideFile, ArrayList<String> hidelist) {
- 118 DataOutputStream out = null;
- 119
- 120 try {
- 121 out = new DataOutputStream(new FileOutputStream(hideFile));
- 122 for (String hide : hidelist) {
- 123 // out.writeUTF(hide + "\n");
- 124 out.writeBytes(hide + "\n");
- 125 }
- 126 out.flush();
- 127 } catch (FileNotFoundException e) {
- 128 // Ignore
- 129 e.printStackTrace();
- 130 } catch (IOException e) {
- 131 e.printStackTrace();
- 132 // noinspection ResultOfMethodCallIgnored
- 133 hideFile.delete();
- 134 } finally {
- 135 if (out != null) {
- 136 try {
- 137 out.close();
- 138 } catch (IOException e) {
- 139 // Ignore
- 140 }
- 141 }
- 142 }
- 143 }
- 144
- 145 private void readHideCfg(File hideFile, ArrayList<String> hidelist) {
- 146 if (hideFile == null || !hideFile.exists())
- 147 return;
- 148
- 149 try {
- 150 FileInputStream inStream = new FileInputStream(hideFile);
- 151
- 152 if (inStream != null) {
- 153 BufferedReader rbf = new BufferedReader(new InputStreamReader(inStream));
- 154
- 155 String linebuf = rbf.readLine();
- 156 while (linebuf != null) {
- 157 linebuf = linebuf.trim();
- 158 if (!linebuf.startsWith("#", 0) && linebuf.length() != 0) {
- 159 if (DEBUG)
- 160 Log.d(TAG, "readHideCfg: " + linebuf);
- 161 hidelist.add(linebuf);
- 162 }
- 163 linebuf = rbf.readLine();
- 164 }
- 165 return;
- 166 }
- 167 } catch (FileNotFoundException e) {
- 168 Log.e(TAG, "readHideCfg: " + "File is not found");
- 169 } catch (Exception e) {
- 170 Log.e(TAG, "Read hide config error");
- 171 e.printStackTrace();
- 172 }
- 173 }
- 174
- 175 public boolean isHide(String name) {
- 176 synchronized (sLock) {
- 177 if (mHideList.contains(name)) {
- 178 return true;
- 179 } else {
- 180 return false;
- 181 }
- 182 }
- 183 }
- 184
- 185 /*
- 186 * change condition: 1. original not exists but exists currently 2. current
- 187 * is newer than original 3. exclude original exists but not exists
- 188 * currently, keep original hide list
- 189 */
- 190 private boolean isSDHideFileChange() {
- 191 File hideFile = new File(EXTSD_PATH + "/" + FILE);
- 192
- 193 if (DEBUG)
- 194 Log.d(TAG, "isSDHideFileChange: new state-->" + hideFile.exists() + ", old state-->"
- 195 + getSDHideState());
- 196
- 197 if (hideFile.exists()) {
- 198 /* original not exists but exists currently */
- 199 if (!getSDHideState())
- 200 return true;
- 201
- 202 if (DEBUG) {
- 203 Calendar cal = Calendar.getInstance();
- 204 cal.setTimeInMillis(hideFile.lastModified());
- 205 Log.d(TAG, "isSDHideFileChange: new date-->" + hideFile.lastModified() + "="
- 206 + cal.getTime().toLocaleString());
- 207 cal.setTimeInMillis(getSDHideDate());
- 208 Log.d(TAG, "isSDHideFileChange: old date-->" + getSDHideDate() + "="
- 209 + cal.getTime().toLocaleString());
- 210 }
- 211 /* current is newer than original */
- 212 if ((hideFile.lastModified() > getSDHideDate())) {
- 213 return true;
- 214 }
- 215 }
- 216
- 217 return false;
- 218 }
- 219
- 220 private void setSDHideState(boolean state) {
- 221 SharedPreferences preferences = PreferenceManager
- 222 .getDefaultSharedPreferences(mContext);
- 223 SharedPreferences.Editor editor = preferences.edit();
- 224
- 225 editor.putBoolean("sd_hide_state", state);
- 226 editor.commit();
- 227 }
- 228
- 229 private boolean getSDHideState() {
- 230 SharedPreferences preferences = PreferenceManager
- 231 .getDefaultSharedPreferences(mContext);
- 232
- 233 return preferences.getBoolean("sd_hide_state", false);
- 234
- 235 }
- 236
- 237 private void setSDHideDate(long date) {
- 238 SharedPreferences preferences = PreferenceManager
- 239 .getDefaultSharedPreferences(mContext);
- 240 SharedPreferences.Editor editor = preferences.edit();
- 241
- 242 editor.putLong("sd_hide_date", date);
- 243 editor.commit();
- 244 }
- 245
- 246 private long getSDHideDate() {
- 247 SharedPreferences preferences = PreferenceManager
- 248 .getDefaultSharedPreferences(mContext);
- 249
- 250 return preferences.getLong("sd_hide_date", -1);
- 251
- 252 }
- 253
- 254 StorageEventListener mStorageListener = new StorageEventListener() {
- 255
- 256 @Override
- 257 public void onStorageStateChanged(String path, String oldState, String newState) {
- 258 if (DEBUG)
- 259 Log.d(TAG, "onStorageStateChanged: " + path + "--" + newState);
- 260 if (newState.equals("mounted") && path.equals(EXTSD_PATH)) {
- 261 if (isSDHideFileChange()) {
- 262 initHideLocked(true);
- 263
- 264 // TODO send Broadcast ACTION_TCTOOL_SDHIDE_CHANGED
- 265 Intent it = new Intent(Intent.ACTION_TCTOOL_SDHIDE_CHANGED);
- 266 mContext.sendBroadcast(it);
- 267 if (DEBUG)
- 268 Log.d(TAG, "Send sendBroadcast: ACTION_TCTOOL_SDHIDE_CHANGED");
- 269 }
- 270 }
- 271 }
- 272 };
- 273 }