Skip to content

Commit fa7887b

Browse files
committed
Intruder alerts with actions and swipe-to-cancel.
Change-Id: I1d8c7d32bcbf4d3910bb866431e92a8639e4e28b
1 parent fc90b6a commit fa7887b

File tree

7 files changed

+292
-56
lines changed

7 files changed

+292
-56
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Copyright (C) 2012 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+
<selector xmlns:android="http://schemas.android.com/apk/res/android"
18+
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
19+
<item android:state_pressed="true" android:drawable="@drawable/intruder_bg_pressed" />
20+
</selector>
272 Bytes
Loading

packages/SystemUI/res/layout/intruder_alert.xml

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,22 @@
1919
-->
2020

2121
<!-- android:background="@drawable/status_bar_closed_default_background" -->
22-
<FrameLayout
22+
<com.android.systemui.statusbar.policy.IntruderAlertView
2323
xmlns:android="http://schemas.android.com/apk/res/android"
24-
android:layout_height="32dip"
24+
android:layout_height="wrap_content"
2525
android:layout_width="match_parent"
26-
android:paddingLeft="8dip"
27-
android:paddingRight="8dip"
26+
android:orientation="vertical"
2827
>
29-
30-
<LinearLayout
31-
android:id="@+id/intruder_alert_content"
28+
<FrameLayout
29+
android:layout_height="wrap_content"
3230
android:layout_width="match_parent"
33-
android:layout_height="match_parent"
34-
android:gravity="center"
35-
android:animationCache="false"
36-
android:orientation="horizontal"
37-
android:background="@drawable/alert_bar_background"
38-
android:clickable="true"
39-
android:focusable="true"
40-
android:descendantFocusability="afterDescendants"
41-
>
42-
43-
<ImageView
44-
android:id="@+id/alertIcon"
45-
android:layout_width="25dip"
46-
android:layout_height="25dip"
47-
android:layout_marginLeft="6dip"
48-
android:layout_marginRight="8dip"
49-
/>
50-
<TextView
51-
android:id="@+id/alertText"
52-
android:textAppearance="@style/TextAppearance.StatusBar.IntruderAlert"
53-
android:layout_width="match_parent"
54-
android:layout_height="wrap_content"
55-
android:singleLine="true"
56-
/>
57-
</LinearLayout>
58-
</FrameLayout>
31+
android:id="@+id/contentHolder"
32+
android:background="@drawable/intruder_window_bg"
33+
/>
34+
<!-- <ImageView
35+
android:layout_width="match_parent"
36+
android:layout_height="wrap_content"
37+
android:src="@drawable/title_bar_shadow"
38+
android:scaleType="fitXY"
39+
/> -->
40+
</com.android.systemui.statusbar.policy.IntruderAlertView>

packages/SystemUI/res/values/colors.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@
3030
<color name="notification_list_shadow_top">#80000000</color>
3131
<drawable name="recents_callout_line">#99ffffff</drawable>
3232
<drawable name="notification_item_background_legacy_color">#ffaaaaaa</drawable>
33+
<drawable name="intruder_bg_pressed">#ff33B5E5</drawable>
3334
</resources>

packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,4 +158,8 @@ public void onClick(View v) {
158158
}
159159
return vetoButton;
160160
}
161+
162+
public void dismissIntruder() {
163+
// pass
164+
}
161165
}

packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

Lines changed: 76 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import android.view.MotionEvent;
5757
import android.view.VelocityTracker;
5858
import android.view.View;
59+
import android.view.ViewConfiguration;
5960
import android.view.ViewGroup;
6061
import android.view.ViewGroup.LayoutParams;
6162
import android.view.Window;
@@ -77,6 +78,7 @@
7778
import com.android.internal.statusbar.StatusBarNotification;
7879

7980
import com.android.systemui.R;
81+
import com.android.systemui.SwipeHelper;
8082
import com.android.systemui.recent.RecentTasksLoader;
8183
import com.android.systemui.recent.RecentsPanelView;
8284
import com.android.systemui.recent.TaskDescription;
@@ -86,6 +88,7 @@
8688
import com.android.systemui.statusbar.SignalClusterView;
8789
import com.android.systemui.statusbar.policy.DateView;
8890
import com.android.systemui.statusbar.policy.BatteryController;
91+
import com.android.systemui.statusbar.policy.IntruderAlertView;
8992
import com.android.systemui.statusbar.policy.LocationController;
9093
import com.android.systemui.statusbar.policy.NetworkController;
9194
import com.android.systemui.statusbar.policy.NotificationRowLayout;
@@ -102,7 +105,7 @@ public class PhoneStatusBar extends BaseStatusBar {
102105
public static final String ACTION_STATUSBAR_START
103106
= "com.android.internal.policy.statusbar.START";
104107

105-
private static final boolean ENABLE_INTRUDERS = false;
108+
private static final boolean ENABLE_INTRUDERS = true;
106109

107110
static final int EXPANDED_LEAVE_ALONE = -10000;
108111
static final int EXPANDED_FULL_OPEN = -10001;
@@ -117,7 +120,7 @@ public class PhoneStatusBar extends BaseStatusBar {
117120
private static final int MSG_CLOSE_RECENTS_PANEL = 1021;
118121

119122
// will likely move to a resource or other tunable param at some point
120-
private static final int INTRUDER_ALERT_DECAY_MS = 10000;
123+
private static final int INTRUDER_ALERT_DECAY_MS = 0; // disabled, was 10000;
121124

122125
private static final boolean CLOSE_PANEL_WHEN_EMPTIED = true;
123126

@@ -185,7 +188,7 @@ public class PhoneStatusBar extends BaseStatusBar {
185188
DateView mDateView;
186189

187190
// for immersive activities
188-
private View mIntruderAlertView;
191+
private IntruderAlertView mIntruderAlertView;
189192

190193
// on-screen navigation buttons
191194
private NavigationBarView mNavigationBarView = null;
@@ -294,9 +297,9 @@ protected View makeStatusBarView() {
294297
}
295298
mNotificationPanel = expanded.findViewById(R.id.notification_panel);
296299

297-
mIntruderAlertView = View.inflate(context, R.layout.intruder_alert, null);
300+
mIntruderAlertView = (IntruderAlertView) View.inflate(context, R.layout.intruder_alert, null);
298301
mIntruderAlertView.setVisibility(View.GONE);
299-
mIntruderAlertView.setClickable(true);
302+
mIntruderAlertView.setBar(this);
300303

301304
PhoneStatusBarView sb = (PhoneStatusBarView)View.inflate(context,
302305
R.layout.status_bar, null);
@@ -455,6 +458,7 @@ public void onClick(View v) {
455458
toggleRecentApps();
456459
}
457460
};
461+
private StatusBarNotification mCurrentlyIntrudingNotification;
458462

459463
private void prepareNavigationBarView() {
460464
mNavigationBarView.reorient();
@@ -510,7 +514,7 @@ private void addIntruderView() {
510514
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
511515
ViewGroup.LayoutParams.MATCH_PARENT,
512516
ViewGroup.LayoutParams.WRAP_CONTENT,
513-
WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL,
517+
WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, // above the status bar!
514518
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
515519
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
516520
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
@@ -519,7 +523,7 @@ private void addIntruderView() {
519523
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
520524
PixelFormat.TRANSLUCENT);
521525
lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
522-
lp.y += height * 1.5; // FIXME
526+
//lp.y += height * 1.5; // FIXME
523527
lp.setTitle("IntruderAlert");
524528
lp.packageName = mContext.getPackageName();
525529
lp.windowAnimations = R.style.Animation_StatusBar_IntruderAlert;
@@ -562,30 +566,39 @@ public void addNotification(IBinder key, StatusBarNotification notification) {
562566
} catch (RemoteException ex) {
563567
}
564568
if (ENABLE_INTRUDERS && (
565-
(notification.score >= mIntruderInImmersiveMinScore)
566-
|| (!immersive && (notification.score > mIntruderMinScore)))) {
569+
// TODO(dsandler): Only if the screen is on
570+
notification.notification.intruderView != null)) {
571+
// notification.notification.fullScreenIntent != null
572+
// || (notification.score >= mIntruderInImmersiveMinScore)
573+
// || (!immersive && (notification.score > mIntruderMinScore)))) {
567574
Slog.d(TAG, "Presenting high-priority notification");
568575
// special new transient ticker mode
569576
// 1. Populate mIntruderAlertView
577+
578+
if (notification.notification.intruderView == null) {
579+
Slog.e(TAG, notification.notification.toString() + " wanted to intrude but intruderView was null");
580+
return;
581+
}
570582

571-
ImageView alertIcon = (ImageView) mIntruderAlertView.findViewById(R.id.alertIcon);
572-
TextView alertText = (TextView) mIntruderAlertView.findViewById(R.id.alertText);
573-
alertIcon.setImageDrawable(StatusBarIconView.getIcon(
574-
alertIcon.getContext(),
575-
iconView.getStatusBarIcon()));
576-
alertText.setText(notification.notification.tickerText);
583+
// bind the click event to the content area
584+
PendingIntent contentIntent = notification.notification.contentIntent;
585+
final View.OnClickListener listener = (contentIntent != null)
586+
? new NotificationClicker(contentIntent,
587+
notification.pkg, notification.tag, notification.id)
588+
: null;
577589

578-
View button = mIntruderAlertView.findViewById(R.id.intruder_alert_content);
579-
button.setOnClickListener(
580-
new NotificationClicker(notification.notification.contentIntent,
581-
notification.pkg, notification.tag, notification.id));
590+
mIntruderAlertView.applyIntruderContent(notification.notification.intruderView, listener);
582591

592+
mCurrentlyIntrudingNotification = notification;
593+
583594
// 2. Animate mIntruderAlertView in
584595
mHandler.sendEmptyMessage(MSG_SHOW_INTRUDER);
585596

586597
// 3. Set alarm to age the notification off (TODO)
587598
mHandler.removeMessages(MSG_HIDE_INTRUDER);
588-
mHandler.sendEmptyMessageDelayed(MSG_HIDE_INTRUDER, INTRUDER_ALERT_DECAY_MS);
599+
if (INTRUDER_ALERT_DECAY_MS > 0) {
600+
mHandler.sendEmptyMessageDelayed(MSG_HIDE_INTRUDER, INTRUDER_ALERT_DECAY_MS);
601+
}
589602
} else if (notification.notification.fullScreenIntent != null) {
590603
// not immersive & a full-screen alert should be shown
591604
Slog.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
@@ -596,8 +609,10 @@ public void addNotification(IBinder key, StatusBarNotification notification) {
596609
} else {
597610
// usual case: status bar visible & not immersive
598611

599-
// show the ticker
600-
tick(notification);
612+
// show the ticker if there isn't an intruder too
613+
if (mCurrentlyIntrudingNotification == null) {
614+
tick(notification);
615+
}
601616
}
602617

603618
// Recalculate the position of the sliding windows and the titles.
@@ -708,18 +723,33 @@ public void updateNotification(IBinder key, StatusBarNotification notification)
708723
// Recalculate the position of the sliding windows and the titles.
709724
setAreThereNotifications();
710725
updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
726+
727+
// See if we need to update the intruder.
728+
if (oldNotification == mCurrentlyIntrudingNotification) {
729+
if (DEBUG) Slog.d(TAG, "updating the current intruder:" + notification);
730+
// XXX: this is a hack for Alarms. The real implementation will need to *update*
731+
// the intruder.
732+
if (notification.notification.fullScreenIntent == null) { // TODO(dsandler): consistent logic with add()
733+
if (DEBUG) Slog.d(TAG, "no longer intrudes!");
734+
mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
735+
}
736+
}
711737
}
712738

713739
public void removeNotification(IBinder key) {
714-
if (SPEW) Slog.d(TAG, "removeNotification key=" + key);
715740
StatusBarNotification old = removeNotificationViews(key);
741+
if (SPEW) Slog.d(TAG, "removeNotification key=" + key + " old=" + old);
716742

717743
if (old != null) {
718744
// Cancel the ticker if it's still running
719745
mTicker.removeEntry(old);
720746

721747
// Recalculate the position of the sliding windows and the titles.
722748
updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
749+
750+
if (old == mCurrentlyIntrudingNotification) {
751+
mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
752+
}
723753

724754
if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0 && !mAnimating) {
725755
animateCollapse();
@@ -1080,6 +1110,7 @@ public void handleMessage(Message m) {
10801110
break;
10811111
case MSG_HIDE_INTRUDER:
10821112
setIntruderAlertVisibility(false);
1113+
mCurrentlyIntrudingNotification = null;
10831114
break;
10841115
case MSG_OPEN_RECENTS_PANEL:
10851116
if (DEBUG) Slog.d(TAG, "opening recents panel");
@@ -1576,6 +1607,12 @@ private class NotificationClicker implements View.OnClickListener {
15761607
}
15771608

15781609
public void onClick(View v) {
1610+
if (DEBUG) {
1611+
Slog.v(TAG, "NotificationClicker: intent=" + mIntent
1612+
+ " pkg=" + mPkg
1613+
+ " tag=" + mTag
1614+
+ " id=" + mId);
1615+
}
15791616
try {
15801617
// The intent we are sending is for the application, which
15811618
// won't have permission to immediately start an activity after
@@ -2182,9 +2219,25 @@ else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
21822219
};
21832220

21842221
private void setIntruderAlertVisibility(boolean vis) {
2222+
if (DEBUG) {
2223+
Slog.v(TAG, (vis ? "showing" : "hiding") + " intruder alert window");
2224+
}
21852225
mIntruderAlertView.setVisibility(vis ? View.VISIBLE : View.GONE);
21862226
}
21872227

2228+
public void dismissIntruder() {
2229+
if (mCurrentlyIntrudingNotification == null) return;
2230+
2231+
try {
2232+
mBarService.onNotificationClear(
2233+
mCurrentlyIntrudingNotification.pkg,
2234+
mCurrentlyIntrudingNotification.tag,
2235+
mCurrentlyIntrudingNotification.id);
2236+
} catch (android.os.RemoteException ex) {
2237+
// oh well
2238+
}
2239+
}
2240+
21882241
/**
21892242
* Reload some of our resources when the configuration changes.
21902243
*

0 commit comments

Comments
 (0)