/*
* Copyright (C) 2014 ParanoidAndroid 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.reindeercrafts.notificationpeek.peek;
import android.animation.LayoutTransition;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.reindeercrafts.notificationpeek.NotificationHub;
import com.reindeercrafts.notificationpeek.NotificationService;
import com.reindeercrafts.notificationpeek.R;
import com.reindeercrafts.notificationpeek.settings.appearance.WallpaperFactory;
import com.reindeercrafts.notificationpeek.utils.NotificationPeekViewUtils;
import com.reindeercrafts.notificationpeek.utils.UnlockGesture;
import java.util.ArrayList;
import java.util.List;
public class NotificationPeek implements SensorActivityHandler.SensorChangedCallback {
private final static String TAG = "NotificationPeek";
public final static boolean DEBUG = true;
public static final float ICON_LOW_OPACITY = 0.3f;
private static final int NOTIFICATION_PEEK_TIME = 5000; // 5 secs
private static final int PARTIAL_WAKELOCK_TIME = 10000; // 10 secs
private static final long SCREEN_ON_START_DELAY = 300; // 300 ms
private static final long REMOVE_VIEW_DELAY = 300; // 300 ms
private static final int COL_NUM = 10;
private static final long SCREEN_WAKELOCK_TIMEOUT = 2000; // 1 sec
private static final int SENSOR_TIME_OUT_INFINITE = -1;
private SensorActivityHandler mSensorHandler;
private KeyguardManager mKeyguardManager;
private PowerManager mPowerManager;
private DevicePolicyManager mDevicePolicyManager;
private WallpaperFactory mWallpaperFactory;
private PowerManager.WakeLock mPartialWakeLock;
private PowerManager.WakeLock mScreenWakeLock;
private Runnable mPartialWakeLockRunnable;
private Runnable mLockScreenRunnable;
private Handler mWakeLockHandler;
private Handler mHandler;
private static RelativeLayout sPeekView;
private List<StatusBarNotification> mShownNotifications =
new ArrayList<StatusBarNotification>();
private StatusBarNotification mNextNotification;
private LinearLayout mNotificationView;
private GridLayout mNotificationsContainer;
private ImageView mNotificationIcon;
private TextView mNotificationText;
private ImageView mPeekBackgroundImageView;
private Context mContext;
private boolean mShowing;
private boolean mEnabled = true;
private boolean mAnimating;
private boolean mEventsRegistered;
private NotificationHub mNotificationHub;
// Peek timeout multiplier, the final peek timeout period is 5000 * mPeekTimeoutMultiplier.
private int mPeekTimeoutMultiplier;
// Sensor listener timeout, the final sensor timeout period is 10000 * mSensorTimeoutMultiplier.
private int mSensorTimeoutMultiplier;
// Display notification content regardless lock screen methods.
private boolean mShowContent;
private NotificationHelper mNotificationHelper;
public NotificationPeek(NotificationHub notificationHub, Context context) {
mNotificationHub = notificationHub;
mContext = context;
mNotificationHelper = new NotificationHelper(context);
mWallpaperFactory = new WallpaperFactory(context);
mSensorHandler = new SensorActivityHandler(context, this);
mHandler = new Handler(Looper.getMainLooper());
mWakeLockHandler = new Handler();
mSensorHandler.registerScreenReceiver();
mPartialWakeLockRunnable = new Runnable() {
@Override
public void run() {
// After PARTIAL_WAKELOCK_TIME with no user interaction, release CPU wakelock
// and unregister event listeners.
if (mPartialWakeLock.isHeld()) {
if (mEventsRegistered) {
if (DEBUG) {
Log.d(TAG, "Removing event listeners");
}
tryUnregisterEventListeners();
mEventsRegistered = false;
}
mPartialWakeLock.release();
}
}
};
mLockScreenRunnable = new Runnable() {
@Override
public void run() {
if (mShowing) {
if (DEBUG) {
Log.d(TAG, "Turning screen off");
}
mDevicePolicyManager.lockNow();
if (mScreenWakeLock.isHeld()) {
mScreenWakeLock.release();
}
}
}
};
mDevicePolicyManager =
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
getClass().getSimpleName() + "_partial");
// Screen dim wakelock for waking up screen.
mScreenWakeLock = mPowerManager.newWakeLock(
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
getClass().getSimpleName() + "_screen");
// build the layout
sPeekView = new RelativeLayout(context) {
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) {
if (action == MotionEvent.ACTION_DOWN) {
mHandler.removeCallbacksAndMessages(null);
}
}
if (action == MotionEvent.ACTION_UP) {
scheduleTasks();
}
return super.onInterceptTouchEvent(event);
}
};
// Setup double-tap gesture detector.
sPeekView.setOnTouchListener(UnlockGesture
.createTouchListener(mContext, new UnlockGesture.UnlockGestureCallback() {
@Override
public void onUnlocked() {
dismissNotification();
}
}));
// root view
NotificationLayout rootView = new NotificationLayout(context);
rootView.setOrientation(LinearLayout.VERTICAL);
rootView.setNotificationPeek(NotificationPeek.this);
rootView.setId(R.id.notification_layout);
sPeekView.addView(rootView);
RelativeLayout.LayoutParams rootLayoutParams =
new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
rootLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
rootView.setLayoutParams(rootLayoutParams);
// notification container
mNotificationView = new LinearLayout(context);
mNotificationView.setOrientation(LinearLayout.VERTICAL);
mNotificationView.setId(R.id.notification_view);
rootView.addView(mNotificationView);
// current notification icon
mNotificationIcon = new ImageView(context);
mNotificationIcon.setId(R.id.notification_icon);
mNotificationIcon.setScaleType(ImageView.ScaleType.CENTER_CROP);
mNotificationIcon
.setOnTouchListener(NotificationHelper.getHighlightTouchListener(Color.DKGRAY));
// current notification text
mNotificationText = new TextView(context);
mNotificationText.setId(R.id.notification_text);
Typeface typeface = Typeface.create("sans-serif-condensed", Typeface.NORMAL);
mNotificationText.setTypeface(typeface);
mNotificationText.setGravity(Gravity.CENTER);
mNotificationText.setEllipsize(TextUtils.TruncateAt.END);
mNotificationText.setSingleLine(true);
mNotificationText
.setPadding(0, mContext.getResources().getDimensionPixelSize(R.dimen.item_padding),
0, 0);
mNotificationView.addView(mNotificationIcon);
// Move NotificationText out of NotificationView, so that it won't be swiped away with
// the icon.
rootView.addView(mNotificationText);
int iconSize =
mContext.getResources().getDimensionPixelSize(R.dimen.notification_icon_size);
LinearLayout.LayoutParams linearLayoutParams =
new LinearLayout.LayoutParams(iconSize, iconSize);
linearLayoutParams.gravity = Gravity.CENTER_HORIZONTAL;
mNotificationIcon.setLayoutParams(linearLayoutParams);
linearLayoutParams = new LinearLayout.LayoutParams(
mContext.getResources().getDimensionPixelSize(R.dimen.notification_text_width),
LinearLayout.LayoutParams.WRAP_CONTENT);
linearLayoutParams.gravity = Gravity.CENTER_HORIZONTAL;
mNotificationText.setLayoutParams(linearLayoutParams);
// notification icons
// Use GridLayout instead of LinearLayout to avoid having too many notifications in the
// container in just one line. (It's not likely to happen but still possible)
mNotificationsContainer = new GridLayout(context) {
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) {
StatusBarNotification n = getNotificationFromEvent(ev);
if (n != null) {
updateSelection(n);
}
}
return true;
}
};
mNotificationsContainer.setId(R.id.notification_container);
mNotificationsContainer.setColumnCount(COL_NUM);
mNotificationsContainer.setOrientation(GridLayout.HORIZONTAL);
mNotificationsContainer.setPadding(0,
mContext.getResources().getDimensionPixelSize(R.dimen.item_padding) * 2, 0, 0);
LayoutTransition transitioner = new LayoutTransition();
transitioner.enableTransitionType(LayoutTransition.CHANGING);
transitioner.disableTransitionType(LayoutTransition.DISAPPEARING);
transitioner.disableTransitionType(LayoutTransition.APPEARING);
transitioner.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
transitioner.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
mNotificationsContainer.setLayoutTransition(transitioner);
sPeekView.addView(mNotificationsContainer);
RelativeLayout.LayoutParams notificationsLayoutParams =
new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
notificationsLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
notificationsLayoutParams.addRule(RelativeLayout.BELOW, rootView.getId());
mNotificationsContainer.setLayoutParams(notificationsLayoutParams);
updateBackgroundImageView();
}
public static RelativeLayout getPeekView() {
return sPeekView;
}
public void updateNotificationTextAlpha(float alpha) {
mNotificationText.setAlpha(alpha);
}
/**
* Update background ImageView to display proper background according to user preference.
*/
public void updateBackgroundImageView() {
boolean used = WallpaperFactory.isWallpaperThemeSelected(mContext) &&
!WallpaperFactory.isLiveWallpaperUsed(mContext);
if (mPeekBackgroundImageView == null) {
mPeekBackgroundImageView = new ImageView(mContext);
ViewGroup.LayoutParams params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mPeekBackgroundImageView.setLayoutParams(params);
mPeekBackgroundImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
}
if (used) {
mPeekBackgroundImageView.setImageBitmap(mWallpaperFactory.getPrefSystemWallpaper());
if (!isBackgroundImageViewAdded()) {
sPeekView.addView(mPeekBackgroundImageView, 0);
}
} else {
if (isBackgroundImageViewAdded()) {
sPeekView.removeViewAt(0);
}
}
}
private boolean isBackgroundImageViewAdded() {
return sPeekView.getChildAt(0) instanceof ImageView;
}
/* If mSensorTimeoutMultiplier is -1, we don't remove listeners, but let them keep listening. */
private void tryUnregisterEventListeners() {
if (mSensorTimeoutMultiplier != SENSOR_TIME_OUT_INFINITE) {
mSensorHandler.unregisterEventListeners();
}
}
private boolean isKeyguardSecureShowing() {
return !mShowContent &&
(mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure());
}
public View getNotificationView() {
return mNotificationView;
}
public NotificationHub getNotificationHub() {
return mNotificationHub;
}
public void setAnimating(boolean animating) {
mAnimating = animating;
}
private void scheduleTasks() {
mHandler.removeCallbacksAndMessages(null);
// turn on screen task
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (DEBUG) {
Log.d(TAG, "Turning screen on");
}
mScreenWakeLock.acquire(SCREEN_WAKELOCK_TIMEOUT);
}
}, SCREEN_ON_START_DELAY);
// turn off screen task
mHandler.postDelayed(mLockScreenRunnable,
SCREEN_ON_START_DELAY + NOTIFICATION_PEEK_TIME * mPeekTimeoutMultiplier);
// remove view task (make sure screen is off by delaying a bit)
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
dismissNotification();
}
}, SCREEN_ON_START_DELAY + (NOTIFICATION_PEEK_TIME * mPeekTimeoutMultiplier * (long) 1.3));
}
/**
* Show notification according to user preferences.
*
* @param n Notificaiton to display.
* @param update If the given notification is an update.
* @param peekTimeoutMultiplier User preference: timeout.
* @param sensorTimeout User preference: sensor timeout.
* @param showContent User preference: always show content.
*/
public void showNotification(StatusBarNotification n, boolean update, int peekTimeoutMultiplier,
int sensorTimeout, boolean showContent) {
mSensorTimeoutMultiplier = sensorTimeout;
mShowContent = showContent;
mPeekTimeoutMultiplier = peekTimeoutMultiplier;
showNotification(n, update, false);
updateNotificationTextAlpha(1);
}
private void showNotification(StatusBarNotification n, boolean update, boolean force) {
boolean shouldDisplay = shouldDisplayNotification(n) || force;
addNotification(n);
if (!mEnabled /* peek is disabled */ || (mPowerManager.isScreenOn() && !mShowing) /* no peek when screen is on */ ||
!shouldDisplay /* notification has already been displayed */ || !n.isClearable() /* persistent notification */ ||
mNotificationHelper.isRingingOrConnected() /* is phone ringing? */ ||
mNotificationHelper.isSimPanelShowing() /* is sim pin lock screen is shown? */) {
return;
}
if (isNotificationActive(n) && (!update || (update && shouldDisplay))) {
// update information
if (!mShowing) {
updateNotificationIcons();
updateSelection(n);
} else {
mContext.sendBroadcast(new Intent(NotificationPeekActivity.
NotificationPeekReceiver.ACTION_UPDATE_NOTIFICATION_ICONS
));
}
// check if phone is in the pocket or lying on a table
if (mSensorHandler.isInPocket() || mSensorHandler.isOnTable()) {
if (DEBUG) {
Log.d(TAG, "Queueing notification");
}
// use partial wakelock to get sensors working
if (mPartialWakeLock.isHeld()) {
if (DEBUG) {
Log.d(TAG, "Releasing partial wakelock");
}
mPartialWakeLock.release();
}
if (DEBUG) {
Log.d(TAG, "Acquiring partial wakelock");
}
mPartialWakeLock.acquire();
if (!mEventsRegistered) {
mSensorHandler.registerEventListeners();
mEventsRegistered = true;
}
mWakeLockHandler.removeCallbacks(mPartialWakeLockRunnable);
// If always listening is selected, we still release the wake lock in 10 sec, but
// we do not unregister sensor listeners.
int multiplier = Math.max(1, mSensorTimeoutMultiplier);
mWakeLockHandler
.postDelayed(mPartialWakeLockRunnable, PARTIAL_WAKELOCK_TIME * multiplier);
mNextNotification = n;
return;
}
mWakeLockHandler.removeCallbacks(mPartialWakeLockRunnable);
addNotificationView(); // add view instantly
if (!mAnimating) {
scheduleTasks();
}
}
}
private void addNotificationView() {
if (!mShowing) {
mShowing = true;
Intent intent = new Intent(mContext, NotificationPeekActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_NO_HISTORY |
Intent.FLAG_ACTIVITY_NO_ANIMATION);
mContext.startActivity(intent);
}
}
public void dismissNotification() {
if (mShowing) {
mShowing = false;
mContext.sendBroadcast(new Intent(
NotificationPeekActivity.NotificationPeekReceiver.ACTION_FINISH_PEEK));
if (mPartialWakeLock.isHeld()) {
if (DEBUG) {
Log.d(TAG, "Releasing partial wakelock");
}
mPartialWakeLock.release();
}
mHandler.removeCallbacks(mLockScreenRunnable);
}
}
public void addNotification(StatusBarNotification n) {
for (int i = 0; i < mShownNotifications.size(); i++) {
if (NotificationHelper.getContentDescription(n)
.equals(NotificationHelper.getContentDescription(mShownNotifications.get(i)))) {
mShownNotifications.set(i, n);
return;
}
}
mShownNotifications.add(n);
}
public void removeNotification(StatusBarNotification n) {
for (int i = 0; i < mShownNotifications.size(); i++) {
if (NotificationHelper.getContentDescription(n)
.equals(NotificationHelper.getContentDescription(mShownNotifications.get(i)))) {
mShownNotifications.remove(i);
i--;
}
}
updateNotificationIcons();
}
private void updateNotificationIcons() {
mNotificationsContainer.removeAllViews();
int iconSize =
mContext.getResources().getDimensionPixelSize(R.dimen.small_notification_icon_size);
int padding = mContext.getResources()
.getDimensionPixelSize(R.dimen.small_notification_icon_padding);
Object tag = mNotificationView.getTag();
String currentNotification = tag != null ? tag.toString() : null;
boolean foundCurrentNotification = false;
int notificationCount = mNotificationHub.getNotificationCount();
mNotificationsContainer.setVisibility(View.VISIBLE);
if (notificationCount <= 1) {
mNotificationsContainer.setVisibility(View.GONE);
}
StatusBarNotification lastNotification = null;
for (StatusBarNotification notification : mNotificationHub.getNotifications()) {
final StatusBarNotification n = notification;
ImageView icon = new ImageView(mContext);
if (n.toString().equals(currentNotification)) {
foundCurrentNotification = true;
} else {
icon.setAlpha(ICON_LOW_OPACITY);
}
icon.setPadding(padding, 0, padding, 0);
icon.setImageDrawable(NotificationPeekViewUtils.getIconFromResource(mContext, n));
icon.setTag(n);
mNotificationsContainer.addView(icon);
LinearLayout.LayoutParams linearLayoutParams =
new LinearLayout.LayoutParams(iconSize, iconSize);
// Wrap LayoutParams to GridLayout.LayoutParams.
GridLayout.LayoutParams gridLayoutParams =
new GridLayout.LayoutParams(linearLayoutParams);
icon.setLayoutParams(gridLayoutParams);
if (lastNotification == null) {
lastNotification = n;
}
}
if (!foundCurrentNotification) {
if (notificationCount > 0) {
updateSelection(lastNotification);
} else {
dismissNotification();
}
}
}
private void updateSelection(StatusBarNotification n) {
String oldNotif = NotificationHelper
.getContentDescription((StatusBarNotification) mNotificationView.getTag());
String newNotif = NotificationHelper.getContentDescription(n);
boolean sameNotification = newNotif.equals(oldNotif);
if (!mAnimating || sameNotification) {
// update big icon
Bitmap b = n.getNotification().largeIcon;
if (b != null) {
mNotificationIcon.setImageDrawable(
NotificationPeekViewUtils.getRoundedShape(mContext.getResources(), b));
} else {
mNotificationIcon.setImageDrawable(
NotificationPeekViewUtils.getIconFromResource(mContext, n));
}
final PendingIntent contentIntent = n.getNotification().contentIntent;
if (contentIntent != null) {
mNotificationIcon
.setOnClickListener(new NotificationClicker(mContext, contentIntent, this));
} else {
mNotificationIcon.setOnClickListener(null);
}
mNotificationText
.setText(NotificationPeekViewUtils.getNotificationDisplayText(mContext, n));
mNotificationText.setVisibility(isKeyguardSecureShowing() ? View.GONE : View.VISIBLE);
mNotificationView.setTag(n);
// If the notification view is moved before, we need to restore its position before
// displaying new notification.
if (!sameNotification || mNotificationView.getX() != 0) {
mNotificationView.setAlpha(1f);
mNotificationView.setX(0);
}
}
// update small icons
for (int i = 0; i < mNotificationsContainer.getChildCount(); i++) {
ImageView view = (ImageView) mNotificationsContainer.getChildAt(i);
if ((mAnimating ? oldNotif : newNotif).equals(NotificationHelper
.getContentDescription((StatusBarNotification) view.getTag()))) {
view.setAlpha(1f);
} else {
view.setAlpha(ICON_LOW_OPACITY);
}
}
}
private boolean isNotificationActive(StatusBarNotification n) {
for (StatusBarNotification notification : mNotificationHub.getNotifications()) {
if (NotificationHelper.getContentDescription(n)
.equals(NotificationHelper.getContentDescription(notification))) {
return true;
}
}
return false;
}
private boolean shouldDisplayNotification(StatusBarNotification n) {
if (n.getNotification().priority < Notification.PRIORITY_DEFAULT) {
return false;
}
for (StatusBarNotification shown : mShownNotifications) {
if (NotificationHelper.getContentDescription(n)
.equals(NotificationHelper.getContentDescription(shown))) {
return NotificationHelper.shouldDisplayNotification(shown, n);
}
}
return true;
}
private StatusBarNotification getNotificationFromEvent(MotionEvent event) {
for (int i = 0; i < mNotificationsContainer.getChildCount(); i++) {
View view = mNotificationsContainer.getChildAt(i);
Rect rect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
if (rect.contains((int) event.getX(), (int) event.getY())) {
if (view.getTag() instanceof StatusBarNotification) {
return (StatusBarNotification) view.getTag();
}
}
}
return null;
}
public void unregisterScreenReceiver() {
mSensorHandler.unregisterScreenReceiver();
sPeekView = null;
}
public void unregisterEventListeners() {
if (mEventsRegistered) {
mSensorHandler.unregisterEventListeners();
mEventsRegistered = false;
}
}
@Override
public void onPocketModeChanged(boolean inPocket) {
// If we set to use always listening, if we detect the device is out of pocket,
// we restore mNextNotification, and let showNotification to decide whether it is active
// or not.
if (inPocket && mSensorTimeoutMultiplier == SENSOR_TIME_OUT_INFINITE &&
mNextNotification == null) {
mNextNotification = mNotificationHub.getCurrentNotification();
}
if (!inPocket && mNextNotification != null) {
showNotification(mNextNotification, false, true);
mNextNotification = null;
}
}
@Override
public void onTableModeChanged(boolean onTable) {
// If we set to use always listening, if we detect the device is held on hand,
// we restore mNextNotification, and let showNotification to decide whether it is active
// or not.
if (!onTable && mSensorTimeoutMultiplier == SENSOR_TIME_OUT_INFINITE &&
mNextNotification == null) {
mNextNotification = mNotificationHub.getCurrentNotification();
}
if (!onTable && mNextNotification != null) {
showNotification(mNextNotification, false, true);
mNextNotification = null;
}
}
@Override
public void onScreenStateChanged(boolean screenOn) {
if (!screenOn) {
mHandler.removeCallbacksAndMessages(null);
dismissNotification();
}
}
/**
* Send broadcast to NotificationService, and let it perform the final dismiss action.
*
* @param pkg package name associated with the notification to be dismissed.
* @param tag tag associated with the notification to be dismissed.
* @param id notification id associated with the notification to be dismissed.
*/
public void onChildDismissed(String description, String pkg, String tag, int id) {
// Send broadcast to NotificationService for dismiss action.
Intent intent = new Intent(NotificationService.ACTION_DISMISS_NOTIFICATION);
intent.putExtra(NotificationService.EXTRA_PACKAGE_NAME, pkg);
intent.putExtra(NotificationService.EXTRA_NOTIFICATION_TAG, tag);
intent.putExtra(NotificationService.EXTRA_NOTIFICATION_ID, id);
mContext.sendBroadcast(intent);
// Send broadcast to NotificationPeekActivity for updating NotificationView.
Intent updateViewIntent = new Intent(
NotificationPeekActivity.NotificationPeekReceiver.ACTION_DIMISS_NOTIFICATION);
updateViewIntent.putExtra(
NotificationPeekActivity.NotificationPeekReceiver.EXTRA_NOTIFICATION_DESCRIPTION,
description);
mContext.sendBroadcast(updateViewIntent);
}
/* Called after click event is triggered, used to clean up event listeners and
* set mNextNotification to null. */
public void onPostClick() {
dismissNotification();
removeNotification((StatusBarNotification) mNotificationView.getTag());
mSensorHandler.unregisterEventListeners();
mNextNotification = null;
}
}