From 1dac277f93a80c53a870b8924508dd2af81293de Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Fri, 26 Jun 2009 18:16:48 -0700 Subject: [PATCH] Implement issue #1943927 (need notification in status bar when adb is active) This is a little hacky -- we just assume that if adb is enabled and power is connected through usb, then it is active. The icons and text are temporary until final design is provided. --- api/current.xml | 11 +++ core/java/android/content/Intent.java | 7 ++ core/res/res/values/strings.xml | 5 + .../server/NotificationManagerService.java | 98 +++++++++++++++++++ .../server/status/StatusBarPolicy.java | 20 ++-- 5 files changed, 134 insertions(+), 7 deletions(-) diff --git a/api/current.xml b/api/current.xml index 787fcb41b8c82..1287f591503e9 100644 --- a/api/current.xml +++ b/api/current.xml @@ -31346,6 +31346,17 @@ visibility="public" > + + Format + + USB debugging connected + + A computer is connected to your phone. + diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 4a2808b50c3d1..854138c740854 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -25,15 +25,20 @@ import android.app.IActivityManager; import android.app.INotificationManager; import android.app.ITransientNotification; import android.app.Notification; +import android.app.NotificationManager; import android.app.PendingIntent; import android.app.StatusBarManager; import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.ContentQueryMap; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; +import android.database.ContentObserver; import android.media.AsyncPlayer; import android.media.AudioManager; import android.net.Uri; @@ -88,6 +93,12 @@ class NotificationManagerService extends INotificationManager.Stub private NotificationRecord mVibrateNotification; private Vibrator mVibrator = new Vibrator(); + // adb + private int mBatteryPlugged; + private boolean mAdbEnabled = false; + private boolean mAdbNotificationShown = false; + private Notification mAdbNotification; + private ArrayList mNotificationList; private ArrayList mToastQueue; @@ -297,6 +308,9 @@ class NotificationManagerService extends INotificationManager.Stub mBatteryFull = batteryFull; updateLights(); } + + mBatteryPlugged = intent.getIntExtra("plugged", 0); + updateAdbNotification(); } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED) || action.equals(Intent.ACTION_PACKAGE_RESTARTED)) { Uri uri = intent.getData(); @@ -312,6 +326,31 @@ class NotificationManagerService extends INotificationManager.Stub } }; + class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + 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(); + } + } + private final SettingsObserver mSettingsObserver; + NotificationManagerService(Context context, StatusBarService statusBar, HardwareService hardware) { @@ -333,6 +372,9 @@ class NotificationManagerService extends INotificationManager.Stub filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(Intent.ACTION_PACKAGE_RESTARTED); mContext.registerReceiver(mIntentReceiver, filter); + + mSettingsObserver = new SettingsObserver(mHandler); + mSettingsObserver.observe(); } // Toasts @@ -892,6 +934,62 @@ class NotificationManagerService extends INotificationManager.Stub return -1; } + // This is here instead of StatusBarPolicy because it is an important + // security feature that we don't want people customizing the platform + // to accidentally lose. + private void updateAdbNotification() { + if (mAdbEnabled && mBatteryPlugged == BatteryManager.BATTERY_PLUGGED_USB) { + if (!mAdbNotificationShown) { + NotificationManager notificationManager = (NotificationManager) mContext + .getSystemService(Context.NOTIFICATION_SERVICE); + if (notificationManager != null) { + Resources r = mContext.getResources(); + CharSequence title = r.getText( + com.android.internal.R.string.adb_active_notification_title); + CharSequence message = r.getText( + com.android.internal.R.string.adb_active_notification_message); + + if (mAdbNotification == null) { + mAdbNotification = new Notification(); + mAdbNotification.icon = com.android.internal.R.drawable.stat_sys_warning; + mAdbNotification.when = 0; + mAdbNotification.flags = Notification.FLAG_ONGOING_EVENT; + mAdbNotification.tickerText = title; + mAdbNotification.defaults |= Notification.DEFAULT_SOUND; + } + + Intent intent = new Intent( + Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | + Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + // Note: we are hard-coding the component because this is + // an important security UI that we don't want anyone + // intercepting. + intent.setComponent(new ComponentName("com.android.settings", + "com.android.settings.DevelopmentSettings")); + PendingIntent pi = PendingIntent.getActivity(mContext, 0, + intent, 0); + + mAdbNotification.setLatestEventInfo(mContext, title, message, pi); + + mAdbNotificationShown = true; + notificationManager.notify( + com.android.internal.R.string.adb_active_notification_title, + mAdbNotification); + } + } + + } else if (mAdbNotificationShown) { + NotificationManager notificationManager = (NotificationManager) mContext + .getSystemService(Context.NOTIFICATION_SERVICE); + if (notificationManager != null) { + mAdbNotificationShown = false; + notificationManager.cancel( + com.android.internal.R.string.adb_active_notification_title); + } + } + } + // ====================================================================== @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java index dd3d38c80f659..7a8d4e5ed40bd 100644 --- a/services/java/com/android/server/status/StatusBarPolicy.java +++ b/services/java/com/android/server/status/StatusBarPolicy.java @@ -99,7 +99,7 @@ public class StatusBarPolicy { private IBinder mBatteryIcon; private IconData mBatteryData; private boolean mBatteryFirst = true; - private boolean mBatteryPlugged; + private int mBatteryPlugged; private int mBatteryLevel; private int mBatteryThreshold = 0; // index into mBatteryThresholds private int[] mBatteryThresholds = new int[] { 20, 15, -1 }; @@ -108,6 +108,7 @@ public class StatusBarPolicy { private View mBatteryView; private int mBatteryViewSequence; private boolean mBatteryShowLowOnEndCall = false; + private boolean mSentLowBatteryBroadcast = false; private static final boolean SHOW_LOW_BATTERY_WARNING = true; // phone @@ -581,7 +582,7 @@ public class StatusBarPolicy { mBatteryData.iconLevel = intent.getIntExtra("level", 0); mService.updateIcon(mBatteryIcon, mBatteryData, null); - boolean plugged = intent.getIntExtra("plugged", 0) != 0; + int plugged = intent.getIntExtra("plugged", 0); int level = intent.getIntExtra("level", -1); if (false) { Log.d(TAG, "updateBattery level=" + level @@ -592,7 +593,7 @@ public class StatusBarPolicy { + " mBatteryFirst=" + mBatteryFirst); } - boolean oldPlugged = mBatteryPlugged; + int oldPlugged = mBatteryPlugged; int oldThreshold = mBatteryThreshold; pickNextBatteryLevel(level); @@ -619,11 +620,12 @@ public class StatusBarPolicy { Log.d(TAG, "plugged=" + plugged + " oldPlugged=" + oldPlugged + " level=" + level + " mBatteryThreshold=" + mBatteryThreshold + " oldThreshold=" + oldThreshold); } - if (!plugged - && ((oldPlugged && level < mBatteryThresholds[BATTERY_THRESHOLD_WARNING]) + if (plugged == 0 + && ((oldPlugged != 0 && level < mBatteryThresholds[BATTERY_THRESHOLD_WARNING]) || (mBatteryThreshold > oldThreshold && mBatteryThreshold > BATTERY_THRESHOLD_WARNING))) { // Broadcast the low battery warning + mSentLowBatteryBroadcast = true; mContext.sendBroadcast(new Intent(Intent.ACTION_BATTERY_LOW)); if (SHOW_LOW_BATTERY_WARNING) { @@ -639,7 +641,11 @@ public class StatusBarPolicy { mBatteryShowLowOnEndCall = true; } } - } else if (mBatteryThreshold == BATTERY_THRESHOLD_CLOSE_WARNING) { + } else if (mBatteryThreshold < BATTERY_THRESHOLD_WARNING) { + if (mSentLowBatteryBroadcast == true) { + mSentLowBatteryBroadcast = false; + mContext.sendBroadcast(new Intent(Intent.ACTION_BATTERY_OKAY)); + } if (SHOW_LOW_BATTERY_WARNING) { if (mLowBatteryDialog != null) { mLowBatteryDialog.dismiss(); @@ -763,7 +769,7 @@ public class StatusBarPolicy { } if (mPhoneState == TelephonyManager.CALL_STATE_IDLE) { if (mBatteryShowLowOnEndCall) { - if (!mBatteryPlugged) { + if (mBatteryPlugged == 0) { showLowBatteryWarning(); } mBatteryShowLowOnEndCall = false;