USB充电插拔与USB Debugging connect提示
在 packages/apps/Settings/src/com/android/settings/DevelopmentSettings.java 找到关于 USB Debug Enable 的代码:
1 Settings.Secure.putInt(getContentResolver(), Settings.Secure.ADB_ENABLED, 0 );
Settings.Secure.putInt(getContentResolver(), Settings.Secure.ADB_ENABLED, 0);
别处将根据其值动态变化做出相应动作如状态栏消息提示。
void observe() { ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.ADB_ENABLED), false , this ); update(); } @Override public void onChange( boolean selfChange) { update(); } public void update() { ContentResolver resolver = mContext.getContentResolver(); mAdbEnabled = Settings.Secure.getInt(resolver, Settings.Secure.ADB_ENABLED, 0 ) != 0 ; updateAdbNotification(); }
void observe() { ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.ADB_ENABLED), false, this); update(); } @Override public void onChange(boolean selfChange) { update(); } public void update() { ContentResolver resolver = mContext.getContentResolver(); mAdbEnabled = Settings.Secure.getInt(resolver, Settings.Secure.ADB_ENABLED, 0) != 0; updateAdbNotification(); }
当激活时,在状态栏中给出通知提示:
notificationManager.notify( com.android.internal .R. string .adb_active_notification_title, mAdbNotification);
notificationManager.notify( com.android.internal.R.string.adb_active_notification_title, mAdbNotification);
知的内容在资源字符串(英文)在字符串资源文件 frameworks/base/core/res/res/values/strings.xml 中, 定义如下:
<!-- Title of notification shown when ADB is actively connected to the phone. --> < string name = "adbactivenotificationtitle" > USB debugging connected </ string > <!-- Message of notification shown when ADB is actively connected to the phone. --> < string name = "adbactivenotificationmessage" > A computer is connected to your phone. </ string >
<!-- Title of notification shown when ADB is actively connected to the phone. --> <string name="adbactivenotificationtitle">USB debugging connected</string> <!-- Message of notification shown when ADB is actively connected to the phone. --> <string name="adbactivenotificationmessage">A computer is connected to your phone.</string>
改变该 Settings 值将通过如下方式影响到实际使用:
在文件中 frameworks/base/services/java/com/android/server/SystemServer.java
private class AdbSettingsObserver extends ContentObserver { public AdbSettingsObserver() { super ( null ); } @Override public void onChange( boolean selfChange) { boolean enableAdb = (Settings.Secure.getInt(mContentResolver, Settings.Secure.ADB_ENABLED, 0 ) > 0 ); // setting this secure property will start or stop adbd SystemProperties.set("persist.service.adb.enable" , enableAdb ? "1" : "0" ); } }
private class AdbSettingsObserver extends ContentObserver { public AdbSettingsObserver() { super(null); } @Override public void onChange(boolean selfChange) { boolean enableAdb = (Settings.Secure.getInt(mContentResolver, Settings.Secure.ADB_ENABLED, 0) > 0); // setting this secure property will start or stop adbd SystemProperties.set("persist.service.adb.enable", enableAdb ? "1" : "0"); } }
可见,当设置系统属性 persist.service.adb.enable 的值时,将影响到 adbd 守护进程相应动作 ( 停止和开启 ) ,这将影响到是否查看 log 等供开发者使用的 adb 功能。
Bug 案例分析:
private void updateAdbNotification() { Log.d(TAG, "2. mBatteryPlugged=" +mBatteryPlugged); if (mAdbEnabled && mBatteryPlugged == BatteryManager.BATTERYPLUGGEDUSB) { Log.d(TAG, "adb enabled, Battery Plugged usb" ); if ( "0" .equals(SystemProperties.get( "persist.adb.notify" ))) { Log.d(TAG, "return directly" ); return ; } if (!mAdbNotificationShown) { //…省略部分代码 mAdbNotificationShown = true ; notificationManager.notify( com.android.internal.R.string.adb_active_notification_title, mAdbNotification); } } } else if (mAdbNotificationShown) { //…省略部分代码 mAdbNotificationShown = false ; notificationManager.cancel( com.android.internal.R.string.adb_active_notification_title); } } }
private void updateAdbNotification() { Log.d(TAG, "2. mBatteryPlugged="+mBatteryPlugged); if (mAdbEnabled && mBatteryPlugged == BatteryManager.BATTERYPLUGGEDUSB) { Log.d(TAG, "adb enabled, Battery Plugged usb"); if ("0".equals(SystemProperties.get("persist.adb.notify"))) { Log.d(TAG, "return directly"); return; } if (!mAdbNotificationShown) { //…省略部分代码 mAdbNotificationShown = true; notificationManager.notify( com.android.internal.R.string.adb_active_notification_title, mAdbNotification); } } } else if (mAdbNotificationShown) { //…省略部分代码 mAdbNotificationShown = false; notificationManager.cancel( com.android.internal.R.string.adb_active_notification_title); } } }
症状:当插上 USB 线与 PC 相连再拔掉时,才显示“ USB Debugging connected ”
分析:通过上述介绍的代码搜索,只有 NotificationManagerService.java 才会出现此提示,也就是说只要当监测到用户修改Settings 中的设置值时和接收到 intent (即 usb 插拔充电)时才会调用 updateAdbNotification() 函数:
D/NotificationService( 1557): mBatteryPlugged = 1 D/NotificationService( 1557): 2. mBatteryPlugged = 1 D/NotificationService( 1557): mBatteryPlugged = 1 D/NotificationService( 1557): 2. mBatteryPlugged = 1 D/NotificationService( 1557): mBatteryPlugged = 2 D/NotificationService( 1557): 2. mBatteryPlugged = 2 D/NotificationService( 1557): adb enabled, Battery Plugged usb D/NotificationService( 1557): adb show notification D/NotificationService( 1557): mBatteryPlugged = 0 D/NotificationService( 1557): 2. mBatteryPlugged = 0 D/NotificationService( 1557): adb cancel notification D/NotificationService( 1557): mBatteryPlugged = 0 D/NotificationService( 1557): 2. mBatteryPlugged = 0
D/NotificationService( 1557): mBatteryPlugged=1 D/NotificationService( 1557): 2. mBatteryPlugged=1 D/NotificationService( 1557): mBatteryPlugged=1 D/NotificationService( 1557): 2. mBatteryPlugged=1 D/NotificationService( 1557): mBatteryPlugged=2 D/NotificationService( 1557): 2. mBatteryPlugged=2 D/NotificationService( 1557): adb enabled, Battery Plugged usb D/NotificationService( 1557): adb show notification D/NotificationService( 1557): mBatteryPlugged=0 D/NotificationService( 1557): 2. mBatteryPlugged=0 D/NotificationService( 1557): adb cancel notification D/NotificationService( 1557): mBatteryPlugged=0 D/NotificationService( 1557): 2. mBatteryPlugged=0
结合 log 看出, mBatteryPlugged 在usb线连上时 为 1 (即 BATTERY_PLUGGED_AC ,不是2即BatteryManager.BATTERY_PLUGGED_USB )而不能进入,在拔掉瞬间为 2 ,则发出提示;在拔掉之后为0。
mBatteryPlugged 的值来自于 Intent :
mBatteryPlugged = intent.getIntExtra( "plugged" , 0 ); updateAdbNotification();
mBatteryPlugged = intent.getIntExtra("plugged", 0); updateAdbNotification();
它发起于下面代码(见文件 frameworks/base/services/java/com/android/server/ BatteryService.java )
private synchronized final void update() { native_update();//JNI层去读取各种值 boolean logOutlier = false ; long dischargeDuration = 0; mBatteryLevelCritical = mBatteryLevel <= CRITICAL_BATTERY_LEVEL; if (mAcOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_AC; } else if (mUsbOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_USB; } else { mPlugType = BATTERY_PLUGGED_NONE; }
private synchronized final void update() { native_update();//JNI层去读取各种值 boolean logOutlier = false; long dischargeDuration = 0; mBatteryLevelCritical = mBatteryLevel <= CRITICAL_BATTERY_LEVEL; if (mAcOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_AC; } else if (mUsbOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_USB; } else { mPlugType = BATTERY_PLUGGED_NONE; }
在文件中 com_android_server_BatteryService.cpp 中,函数:
static void android_server_BatteryService_update(JNIEnv* env, jobject obj)
static void android_server_BatteryService_update(JNIEnv* env, jobject obj)
会从 sys 系统下读取需要的值:
#define AC_ONLINE_PATH "/sys/class/power_supply/ac/online" #define USB_ONLINE_PATH "/sys/class/power_supply/usb/online" #define BATTERY_STATUS_PATH "/sys/class/power_supply/battery/status" #define BATTERY_HEALTH_PATH "/sys/class/power_supply/battery/health" #define BATTERY_PRESENT_PATH "/sys/class/power_supply/battery/present" #define BATTERY_CAPACITY_PATH "/sys/class/power_supply/battery/capacity" #define BATTERY_VOLTAGE_PATH "/sys/class/power_supply/battery/batt_vol" #define BATTERY_TEMPERATURE_PATH "/sys/class/power_supply/battery/batt_temp" #define BATTERY_TECHNOLOGY_PATH "/sys/class/power_supply/battery/technology"
#define AC_ONLINE_PATH "/sys/class/power_supply/ac/online" #define USB_ONLINE_PATH "/sys/class/power_supply/usb/online" #define BATTERY_STATUS_PATH "/sys/class/power_supply/battery/status" #define BATTERY_HEALTH_PATH "/sys/class/power_supply/battery/health" #define BATTERY_PRESENT_PATH "/sys/class/power_supply/battery/present" #define BATTERY_CAPACITY_PATH "/sys/class/power_supply/battery/capacity" #define BATTERY_VOLTAGE_PATH "/sys/class/power_supply/battery/batt_vol" #define BATTERY_TEMPERATURE_PATH "/sys/class/power_supply/battery/batt_temp" #define BATTERY_TECHNOLOGY_PATH "/sys/class/power_supply/battery/technology"
其中前 2 项标明了是 AC 还是 USB 充电。
因此,问题产生在系统底层识别 usb 充电信息错误,导致错误的时刻去显示 USB Debugging connect 信息。
总结:
当系统的 BatteryService ( BatteryService.java )调用 JNI 层( com_android_server_BatteryService.cpp ),通过 sys 系统文件获得充电(如 usb 充电)及电池信息,然后通过 intent 发送出去。 NotificationManagerService.java 在接收到广播信息后,分析是 usb 充电则采取相应的提示信息。
另外, NotificationManagerService 还监听着 Settings 里用户是否修改了设置的值,采取相应动作(是否更新提示信息、是否停掉或开启 adbd 守护进程等)。