1、验证SSID和密码配置文件功能:
手动在setting中添加网络,必须有SSID配置,如xxx,保存后进行如下adb操作
adb shell
cd /data/misc/wifi
grep xxx WifiConfigStore.xml
在该配置文件中找到包含该xxx字符的行,即表示添加网络并保存成功
2、通过ifconfig命令可查看IPv4/IPv6地址(如果支持IPv6的话)
3、查看android源码版本号,可以在文件(build\core\version_defaults.mk)中找到,如:
PLATFORM_VERSION := 4.0.4
PLATFORM_SDK_VERSION := 15
下面为android 4以上的对照表:
平台版本 SDK版本 版本名称
Android 10.0 29 Android 10
Android 9.0 28 Pie/P
Android 8.1 27 Oreo/O_MR1
Android 8.0 26 Oreo
Android 7.1 25 Nougat
Android 7.0 24 Nougat
Android 6.0 23 Marshmallow
Android 5.1 22 Lollipop
Android 5.0 21 Lollipop
Android 4.4 19 KITKAT
Android 4.3 18 JELLY_BEAN_MR2
Android 4.2, 4.2.2 17 JELLY_BEAN_MR1
Android 4.1, 4.1.1 16 JELLY_BEAN
Android 4.0.3, 4.0.4 15 ICE_CREAM_SANDWICH_MR1
Android 4.0, 4.0.1, 4.0.2 14 ICE_CREAM_SANDWICH
注意:Android 10即代表android Q版本
4、android上一些有固定键值的keycode
键名 描述 键值
KEYCODE_MENU 菜单键 82
KEYCODE_HOME 按键Home 3
KEYCODE_BACK 返回键 4
KEYCODE_POWER 电源键 26
KEYCODE_SEARCH 搜索键 84
KEYCODE_CAMERA 拍照键 27
KEYCODE_VOLUME_UP 音量增加键 24
KEYCODE_VOLUME_DOWN 音量减小键 25
注意:
Android利用命令“adb shell input keyevent <键值>”可以实现自动化。例如“adb shell input keyevent 3”就可以按下Home键。
getevent:显示当前有那些输入设备,数量与 /dev/input 目录下相同
5、通过aidl添加服务函数
1.在/frameworks/base/wifi/java/android/net/wifi/IWifiManager.aidl中添加新服务方法声明,如:void dhxAIDLTest();
2.在/frameworks/base/wifi/java/android/net/wifi/WifiManager.java中添加封装调用新服务方法的API函数,如:
public void dhxAIDLTest(){ //此封装方法名可与新服务方法名不同
try {
Log.d(TAG,"WifiManagerdhxAIDLTest is starting");
mService.dhxAIDLTest(); //此处为调用新服务方法的地方
Log.d(TAG,"WifiManagerdhxAIDLTest is end");
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
注意:此处封装时,最好采用try-catch的格式,以防止编译出现错误
编译完成后会在/frameworks/base/api/current.txt中添加此封装方法名的声明,如:method public void dhxAIDLTest();
然后把此API函数放在该文件在或其他地方要调用的方法中即可
3.在/frameworks/base/wifi/java/com/android/server/wifi/BaseWifiService.java中添加新服务方法的一次简单实现,如:
@Override
public void dhxAIDLTest(){
throw new UnsupportedOperationException();
}
注意:WifiServiceImpl继承了BaseWifiService,故
4.在/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java中添加添加新服务方法的二次真正实现,如:
@Override
public void dhxAIDLTest(){
Log.d(TAG, "this is WifiService dhxAIDLTest");
}
6、通过RSSI限制wifi扫描列表的显示数量
1.在/frameworks/base/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java中添加判断RSSI的新方法,如;
/** Return true if the current RSSI is less than -70, and false otherwise. */
public boolean isDisplayable() {
return mRssi >= -70; //即只显示RSSI大于等于-70的AP
}
2.在/packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java->updateAccessPointPreferences中添加对新方法的调用
if (accessPoint.isReachable() && accessPoint.isDisplayable())
7、Android手机中热点配置文件保存路径
热点配置文件在手机中保存路径:/data/misc/wifi/softap.conf
VPN配置文件在手机中保存路径:/data/misc/keystore/user_0
8、如何添加Dialog(必要前提:该类中必须已引入context变量)
1.先引入如下与Dialog相关的类
import android.app.Dialog;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
2.建立触发Dialog的API函数(注意OnClickListener()监听器必须要添加!),如:
public void click(){
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle("warning");
builder.setMessage("Pls do not use W52/W53 5GHz band outside");
builder.setPositiveButton("Positive",new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which){
Log.d(TAG, "Positive");//此处日志只是为了方便验证结果
}
});
final Dialog dialog = builder.create();
dialog.show();
}
3.编译完成后会在.../api/current.txt下生成相应的方法声明,如:
method public void click();
4.在需要弹出此Dialog的地方调用此API函数即可
9、adb写入蓝牙和wifi的mac地址(即写死,若不写即为:00:00:00:00:00:00 此时系统是随即生成mac地址并分配 两者是互斥的!)
1.蓝牙写入:
adb shell audioelectric start 拉起audioelectric服务
adb shell audioelectric setbtmac 18:DC:56:90:3B:89 写入BT的mac地址,成功后返回success
adb shell audioelectric getbtmac 读取验证BT的mac地址,成功后返回success
2.wifi写入:
adb shell audioelectric start 拉起audioelectric服务
adb shell audioelectric setwifimac 18:DC:56:90:3B:88 写入wifi的mac地址,成功后返回success
adb shell audioelectric getwifimac 读取验证wifi的mac地址,成功后返回success
补充:如何读取BT和wifi的mac地址
adb shell audioelectric start
adb shell audioelectric getwifimac
adb shell audioelectric getbtmac
10、remount方式 若某次remount不成功时使用,执行如下:
adb shell setprop sys.verity 1
adb disable-verity (若此处执行无效,则应该是adb版本太低,待验证!)
adb reboot
adb root
adb remount
一般出现如下提示时表示remount成功:
[libfs_mgr]dt_fstab: Skip disabled entry for partition vendor
[libfs_mgr]dt_fstab: Skip disabled entry for partition vendor
[libfs_mgr]dt_fstab: Skip disabled entry for partition vendor
[libfs_mgr]dt_fstab: Skip disabled entry for partition vendor
remount succeeded
11、adb devices时出现offline,找不到adb设备的一个处理方式,执行如下:
adb kill-server 终止adb服务
adb start-server 启动adb服务
adb remount
adb reboot
12、获取或查看软件版本号(其中包含modem、wlan等等的版本号,一般提case时直接把modem的版本号贴上去即可)
方法1:
直接从源码目录中找到类似about.html的文件即可(类似路径:/AMSS/RELEASE.NOTES/about.html)
方法2:
直接从手机查看或者获取
adb shell cat /vendor/firmware_mnt/verinfo/ver_info.txt
adb pull /vendor/firmware_mnt/verinfo/ver_info.txt .
13、蓝牙btsnoop日志获取方法
1.Turn off bluetooth
2.adb shell setprop persist.bluetooth.btsnoopenable true (O/P) and adb shell setprop persist.bluetooth.btsnooplogmode full(Q)
3.Turn on bluetooth
btsnoop log will be saved into /data/misc/bluetooth/logs/hci_snoopXXXXXXXXXXXXXX.cfa
14、//蓝牙logcat日志获取方法(仅供参考!)
1.Turn off bluetooth
2.adb root and adb remount
3.adb pull /etc/bluetooth/bt_stack.conf
4.set all trace levels to 6
5.Enable new C++ logs by modifying as below
LoggingV=--v=0
LoggingVModule=--vmodule=*/btm/*=1,btm_ble_multi*=2,*/bta/gatt/*=1,*/stack/gatt/*=1,*/stack/smp/*=1,btif_ble*=1
6.adb push back bt_stack.conf
7.logcat -b all -v threadtime > Logcat_All.log &
8.Turn on bluetooth(进行相关的bug复现操作)
15、一个完整的 HIDL 接口的实现(此处以WiFi获取 MacAddress 为例)
1./frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java
public String getMacAddress(@NonNull String ifaceName) {
return mSupplicantStaIfaceHal.getMacAddress(ifaceName);
}
2./frameworks/opt/net/wifi/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
public String getMacAddress(@NonNull String ifaceName) {
synchronized (mLock) {
final String methodStr = "getMacAddress";
ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
if (iface == null) return null;
Mutable<String> gotMac = new Mutable<>();
try {
iface.getMacAddress((SupplicantStatus status,
byte[/* 6 */] macAddr) -> {
if (checkStatusAndLogFailure(status, methodStr)) {
gotMac.value = NativeUtil.macAddressFromByteArray(macAddr);
}
});
} catch (RemoteException e) {
handleRemoteException(e, methodStr);
}
return gotMac.value;
}
}
3./hardware/interfaces/wifi/supplicant/1.0/ISupplicantStaIface.hal
getMacAddress()
generates (SupplicantStatus status, MacAddress macAddr);
4./external/wpa_supplicant_8/wpa_supplicant/hidl/1.0/sta_iface.cpp
Return<void> StaIface::getMacAddress(getMacAddress_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&StaIface::getMacAddressInternal, _hidl_cb);
}
StaIface::getMacAddressInternal()
{
struct wpa_supplicant *wpa_s = retrieveIfacePtr();
std::vector<char> cmd(
kGetMacAddress, kGetMacAddress + sizeof(kGetMacAddress));
char driver_cmd_reply_buf[4096] = {};
int ret = wpa_drv_driver_cmd(
wpa_s, cmd.data(), driver_cmd_reply_buf,
sizeof(driver_cmd_reply_buf));
// Reply is of the format: "Macaddr = XX:XX:XX:XX:XX:XX"
std::string reply_str = driver_cmd_reply_buf;
if (ret < 0 || reply_str.empty() ||
reply_str.find("=") == std::string::npos) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
}
// Remove all whitespace first and then split using the delimiter "=".
reply_str.erase(
remove_if(reply_str.begin(), reply_str.end(), isspace),
reply_str.end());
std::string mac_addr_str =
reply_str.substr(reply_str.find("=") + 1, reply_str.size());
std::array<uint8_t, 6> mac_addr;
if (hwaddr_aton(mac_addr_str.c_str(), mac_addr.data())) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
}
return {{SupplicantStatusCode::SUCCESS, ""}, mac_addr};
}