diff options
7 files changed, 292 insertions, 56 deletions
diff --git a/packages/SystemUI/res/drawable/intruder_row_bg.xml b/packages/SystemUI/res/drawable/intruder_row_bg.xml new file mode 100644 index 0000000..1c7c9c4 --- /dev/null +++ b/packages/SystemUI/res/drawable/intruder_row_bg.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2012 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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android" + android:exitFadeDuration="@android:integer/config_mediumAnimTime"> + <item android:state_pressed="true" android:drawable="@drawable/intruder_bg_pressed" /> +</selector> diff --git a/packages/SystemUI/res/drawable/intruder_window_bg.9.png b/packages/SystemUI/res/drawable/intruder_window_bg.9.png Binary files differnew file mode 100644 index 0000000..caad169 --- /dev/null +++ b/packages/SystemUI/res/drawable/intruder_window_bg.9.png diff --git a/packages/SystemUI/res/layout/intruder_alert.xml b/packages/SystemUI/res/layout/intruder_alert.xml index ba4a774..c4141ae 100644 --- a/packages/SystemUI/res/layout/intruder_alert.xml +++ b/packages/SystemUI/res/layout/intruder_alert.xml @@ -19,40 +19,22 @@ --> <!-- android:background="@drawable/status_bar_closed_default_background" --> -<FrameLayout +<com.android.systemui.statusbar.policy.IntruderAlertView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_height="32dip" + android:layout_height="wrap_content" android:layout_width="match_parent" - android:paddingLeft="8dip" - android:paddingRight="8dip" + android:orientation="vertical" > - - <LinearLayout - android:id="@+id/intruder_alert_content" + <FrameLayout + android:layout_height="wrap_content" android:layout_width="match_parent" - android:layout_height="match_parent" - android:gravity="center" - android:animationCache="false" - android:orientation="horizontal" - android:background="@drawable/alert_bar_background" - android:clickable="true" - android:focusable="true" - android:descendantFocusability="afterDescendants" - > - - <ImageView - android:id="@+id/alertIcon" - android:layout_width="25dip" - android:layout_height="25dip" - android:layout_marginLeft="6dip" - android:layout_marginRight="8dip" - /> - <TextView - android:id="@+id/alertText" - android:textAppearance="@style/TextAppearance.StatusBar.IntruderAlert" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:singleLine="true" - /> - </LinearLayout> -</FrameLayout> + android:id="@+id/contentHolder" + android:background="@drawable/intruder_window_bg" + /> +<!-- <ImageView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:src="@drawable/title_bar_shadow" + android:scaleType="fitXY" + /> --> +</com.android.systemui.statusbar.policy.IntruderAlertView> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 7f00c38..c8e3fad 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -30,4 +30,5 @@ <color name="notification_list_shadow_top">#80000000</color> <drawable name="recents_callout_line">#99ffffff</drawable> <drawable name="notification_item_background_legacy_color">#ffaaaaaa</drawable> + <drawable name="intruder_bg_pressed">#ff33B5E5</drawable> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 36d9316..3a06127 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -158,4 +158,8 @@ public abstract class BaseStatusBar extends SystemUI implements CommandQueue.Cal } return vetoButton; } + + public void dismissIntruder() { + // pass + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 9306127..85e0a8a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -56,6 +56,7 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.Window; @@ -77,6 +78,7 @@ import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.statusbar.StatusBarNotification; import com.android.systemui.R; +import com.android.systemui.SwipeHelper; import com.android.systemui.recent.RecentTasksLoader; import com.android.systemui.recent.RecentsPanelView; import com.android.systemui.recent.TaskDescription; @@ -86,6 +88,7 @@ import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.SignalClusterView; import com.android.systemui.statusbar.policy.DateView; import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.IntruderAlertView; import com.android.systemui.statusbar.policy.LocationController; import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.NotificationRowLayout; @@ -102,7 +105,7 @@ public class PhoneStatusBar extends BaseStatusBar { public static final String ACTION_STATUSBAR_START = "com.android.internal.policy.statusbar.START"; - private static final boolean ENABLE_INTRUDERS = false; + private static final boolean ENABLE_INTRUDERS = true; static final int EXPANDED_LEAVE_ALONE = -10000; static final int EXPANDED_FULL_OPEN = -10001; @@ -117,7 +120,7 @@ public class PhoneStatusBar extends BaseStatusBar { private static final int MSG_CLOSE_RECENTS_PANEL = 1021; // will likely move to a resource or other tunable param at some point - private static final int INTRUDER_ALERT_DECAY_MS = 10000; + private static final int INTRUDER_ALERT_DECAY_MS = 0; // disabled, was 10000; private static final boolean CLOSE_PANEL_WHEN_EMPTIED = true; @@ -185,7 +188,7 @@ public class PhoneStatusBar extends BaseStatusBar { DateView mDateView; // for immersive activities - private View mIntruderAlertView; + private IntruderAlertView mIntruderAlertView; // on-screen navigation buttons private NavigationBarView mNavigationBarView = null; @@ -294,9 +297,9 @@ public class PhoneStatusBar extends BaseStatusBar { } mNotificationPanel = expanded.findViewById(R.id.notification_panel); - mIntruderAlertView = View.inflate(context, R.layout.intruder_alert, null); + mIntruderAlertView = (IntruderAlertView) View.inflate(context, R.layout.intruder_alert, null); mIntruderAlertView.setVisibility(View.GONE); - mIntruderAlertView.setClickable(true); + mIntruderAlertView.setBar(this); PhoneStatusBarView sb = (PhoneStatusBarView)View.inflate(context, R.layout.status_bar, null); @@ -455,6 +458,7 @@ public class PhoneStatusBar extends BaseStatusBar { toggleRecentApps(); } }; + private StatusBarNotification mCurrentlyIntrudingNotification; private void prepareNavigationBarView() { mNavigationBarView.reorient(); @@ -510,7 +514,7 @@ public class PhoneStatusBar extends BaseStatusBar { WindowManager.LayoutParams lp = new WindowManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, - WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL, + WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, // above the status bar! WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL @@ -519,7 +523,7 @@ public class PhoneStatusBar extends BaseStatusBar { | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, PixelFormat.TRANSLUCENT); lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL; - lp.y += height * 1.5; // FIXME + //lp.y += height * 1.5; // FIXME lp.setTitle("IntruderAlert"); lp.packageName = mContext.getPackageName(); lp.windowAnimations = R.style.Animation_StatusBar_IntruderAlert; @@ -562,30 +566,39 @@ public class PhoneStatusBar extends BaseStatusBar { } catch (RemoteException ex) { } if (ENABLE_INTRUDERS && ( - (notification.score >= mIntruderInImmersiveMinScore) - || (!immersive && (notification.score > mIntruderMinScore)))) { + // TODO(dsandler): Only if the screen is on + notification.notification.intruderView != null)) { +// notification.notification.fullScreenIntent != null +// || (notification.score >= mIntruderInImmersiveMinScore) +// || (!immersive && (notification.score > mIntruderMinScore)))) { Slog.d(TAG, "Presenting high-priority notification"); // special new transient ticker mode // 1. Populate mIntruderAlertView + + if (notification.notification.intruderView == null) { + Slog.e(TAG, notification.notification.toString() + " wanted to intrude but intruderView was null"); + return; + } - ImageView alertIcon = (ImageView) mIntruderAlertView.findViewById(R.id.alertIcon); - TextView alertText = (TextView) mIntruderAlertView.findViewById(R.id.alertText); - alertIcon.setImageDrawable(StatusBarIconView.getIcon( - alertIcon.getContext(), - iconView.getStatusBarIcon())); - alertText.setText(notification.notification.tickerText); + // bind the click event to the content area + PendingIntent contentIntent = notification.notification.contentIntent; + final View.OnClickListener listener = (contentIntent != null) + ? new NotificationClicker(contentIntent, + notification.pkg, notification.tag, notification.id) + : null; - View button = mIntruderAlertView.findViewById(R.id.intruder_alert_content); - button.setOnClickListener( - new NotificationClicker(notification.notification.contentIntent, - notification.pkg, notification.tag, notification.id)); + mIntruderAlertView.applyIntruderContent(notification.notification.intruderView, listener); + mCurrentlyIntrudingNotification = notification; + // 2. Animate mIntruderAlertView in mHandler.sendEmptyMessage(MSG_SHOW_INTRUDER); // 3. Set alarm to age the notification off (TODO) mHandler.removeMessages(MSG_HIDE_INTRUDER); - mHandler.sendEmptyMessageDelayed(MSG_HIDE_INTRUDER, INTRUDER_ALERT_DECAY_MS); + if (INTRUDER_ALERT_DECAY_MS > 0) { + mHandler.sendEmptyMessageDelayed(MSG_HIDE_INTRUDER, INTRUDER_ALERT_DECAY_MS); + } } else if (notification.notification.fullScreenIntent != null) { // not immersive & a full-screen alert should be shown Slog.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent"); @@ -596,8 +609,10 @@ public class PhoneStatusBar extends BaseStatusBar { } else { // usual case: status bar visible & not immersive - // show the ticker - tick(notification); + // show the ticker if there isn't an intruder too + if (mCurrentlyIntrudingNotification == null) { + tick(notification); + } } // Recalculate the position of the sliding windows and the titles. @@ -708,11 +723,22 @@ public class PhoneStatusBar extends BaseStatusBar { // Recalculate the position of the sliding windows and the titles. setAreThereNotifications(); updateExpandedViewPos(EXPANDED_LEAVE_ALONE); + + // See if we need to update the intruder. + if (oldNotification == mCurrentlyIntrudingNotification) { + if (DEBUG) Slog.d(TAG, "updating the current intruder:" + notification); + // XXX: this is a hack for Alarms. The real implementation will need to *update* + // the intruder. + if (notification.notification.fullScreenIntent == null) { // TODO(dsandler): consistent logic with add() + if (DEBUG) Slog.d(TAG, "no longer intrudes!"); + mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER); + } + } } public void removeNotification(IBinder key) { - if (SPEW) Slog.d(TAG, "removeNotification key=" + key); StatusBarNotification old = removeNotificationViews(key); + if (SPEW) Slog.d(TAG, "removeNotification key=" + key + " old=" + old); if (old != null) { // Cancel the ticker if it's still running @@ -720,6 +746,10 @@ public class PhoneStatusBar extends BaseStatusBar { // Recalculate the position of the sliding windows and the titles. updateExpandedViewPos(EXPANDED_LEAVE_ALONE); + + if (old == mCurrentlyIntrudingNotification) { + mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER); + } if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0 && !mAnimating) { animateCollapse(); @@ -1080,6 +1110,7 @@ public class PhoneStatusBar extends BaseStatusBar { break; case MSG_HIDE_INTRUDER: setIntruderAlertVisibility(false); + mCurrentlyIntrudingNotification = null; break; case MSG_OPEN_RECENTS_PANEL: if (DEBUG) Slog.d(TAG, "opening recents panel"); @@ -1576,6 +1607,12 @@ public class PhoneStatusBar extends BaseStatusBar { } public void onClick(View v) { + if (DEBUG) { + Slog.v(TAG, "NotificationClicker: intent=" + mIntent + + " pkg=" + mPkg + + " tag=" + mTag + + " id=" + mId); + } try { // The intent we are sending is for the application, which // won't have permission to immediately start an activity after @@ -2182,9 +2219,25 @@ public class PhoneStatusBar extends BaseStatusBar { }; private void setIntruderAlertVisibility(boolean vis) { + if (DEBUG) { + Slog.v(TAG, (vis ? "showing" : "hiding") + " intruder alert window"); + } mIntruderAlertView.setVisibility(vis ? View.VISIBLE : View.GONE); } + public void dismissIntruder() { + if (mCurrentlyIntrudingNotification == null) return; + + try { + mBarService.onNotificationClear( + mCurrentlyIntrudingNotification.pkg, + mCurrentlyIntrudingNotification.tag, + mCurrentlyIntrudingNotification.id); + } catch (android.os.RemoteException ex) { + // oh well + } + } + /** * Reload some of our resources when the configuration changes. * diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IntruderAlertView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IntruderAlertView.java new file mode 100644 index 0000000..ee5c863 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IntruderAlertView.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2011 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 com.android.systemui.statusbar.policy; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.LayoutTransition; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.TypedArray; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.util.Log; +import android.util.Slog; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.RemoteViews; + +import com.android.systemui.R; +import com.android.systemui.SwipeHelper; +import com.android.systemui.statusbar.BaseStatusBar; + +import java.util.HashMap; + +public class IntruderAlertView extends LinearLayout implements SwipeHelper.Callback { + private static final String TAG = "IntruderAlertView"; + private static final boolean DEBUG = false; + + Rect mTmpRect = new Rect(); + + private SwipeHelper mSwipeHelper; + + BaseStatusBar mBar; + private ViewGroup mContentHolder; + + private RemoteViews mIntruderRemoteViews; + private OnClickListener mOnClickListener; + + public IntruderAlertView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public IntruderAlertView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + setOrientation(LinearLayout.VERTICAL); + } + + @Override + public void onAttachedToWindow() { + float densityScale = getResources().getDisplayMetrics().density; + float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop(); + mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop); + + mContentHolder = (ViewGroup) findViewById(R.id.contentHolder); + if (mIntruderRemoteViews != null) { + // whoops, we're on already! + applyIntruderContent(mIntruderRemoteViews, mOnClickListener); + } + } + + public void setBar(BaseStatusBar bar) { + mBar = bar; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()"); + return mSwipeHelper.onInterceptTouchEvent(ev) || + super.onInterceptTouchEvent(ev); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + return mSwipeHelper.onTouchEvent(ev) || + super.onTouchEvent(ev); + } + + public boolean canChildBeDismissed(View v) { + return true; + } + + public void onChildDismissed(View v) { + Slog.v(TAG, "User swiped intruder to dismiss"); + mBar.dismissIntruder(); + } + + public void onBeginDrag(View v) { + } + + public void onDragCancelled(View v) { + mContentHolder.setAlpha(1f); // sometimes this isn't quite reset + } + + public View getChildAtPosition(MotionEvent ev) { + return mContentHolder; + } + + public View getChildContentView(View v) { + return v; + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + float densityScale = getResources().getDisplayMetrics().density; + mSwipeHelper.setDensityScale(densityScale); + float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop(); + mSwipeHelper.setPagingTouchSlop(pagingTouchSlop); + } + + @Override + public void onDraw(android.graphics.Canvas c) { + super.onDraw(c); + if (DEBUG) { + //Slog.d(TAG, "onDraw: canvas height: " + c.getHeight() + "px; measured height: " + // + getMeasuredHeight() + "px"); + c.save(); + c.clipRect(6, 6, c.getWidth() - 6, getMeasuredHeight() - 6, + android.graphics.Region.Op.DIFFERENCE); + c.drawColor(0xFFcc00cc); + c.restore(); + } + } + + public void applyIntruderContent(RemoteViews intruderView, OnClickListener listener) { + if (DEBUG) { + Slog.v(TAG, "applyIntruderContent: view=" + intruderView + " listener=" + listener); + } + mIntruderRemoteViews = intruderView; + mOnClickListener = listener; + if (mContentHolder == null) { + // too soon! + return; + } + mContentHolder.setX(0); + mContentHolder.setVisibility(View.VISIBLE); + mContentHolder.setAlpha(1f); + mContentHolder.removeAllViews(); + final View content = intruderView.apply(getContext(), mContentHolder); + if (listener != null) { + content.setOnClickListener(listener); + + //content.setBackgroundResource(R.drawable.intruder_row_bg); + Drawable bg = getResources().getDrawable(R.drawable.intruder_row_bg); + if (bg == null) { + Log.e(TAG, String.format("Can't find background drawable id=0x%08x", R.drawable.intruder_row_bg)); + } else { + content.setBackgroundDrawable(bg); + } + } + mContentHolder.addView(content); + + } +}
\ No newline at end of file |
