HeadsUpManager.java revision b8f09cf5533d458868a335ce334e4880b2b0788d
1b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek/* 2b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * Copyright (C) 2011 The Android Open Source Project 3b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * 4b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * Licensed under the Apache License, Version 2.0 (the "License"); 5b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * you may not use this file except in compliance with the License. 6b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * You may obtain a copy of the License at 7b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * 8b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * http://www.apache.org/licenses/LICENSE-2.0 9b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * 10b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * Unless required by applicable law or agreed to in writing, software 11b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * distributed under the License is distributed on an "AS IS" BASIS, 12b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * See the License for the specific language governing permissions and 14b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * limitations under the License. 15b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek */ 16b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 17b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekpackage com.android.systemui.statusbar.policy; 18b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 19b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport android.content.Context; 20b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport android.content.res.Resources; 21b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport android.database.ContentObserver; 22b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport android.os.Handler; 23b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport android.os.SystemClock; 24b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport android.provider.Settings; 25b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport android.util.ArrayMap; 26b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport android.util.Log; 27b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport android.util.Pools; 28b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport android.view.View; 29b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport android.view.ViewTreeObserver; 30b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport android.view.accessibility.AccessibilityEvent; 31b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 32b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport com.android.systemui.R; 33b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport com.android.systemui.statusbar.NotificationData; 34b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport com.android.systemui.statusbar.phone.PhoneStatusBar; 35b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 36b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport java.io.FileDescriptor; 37b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport java.io.PrintWriter; 38b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport java.util.HashSet; 39b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport java.util.Stack; 40b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport java.util.TreeMap; 41b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 42b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekpublic class HeadsUpManager { 43b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private static final String TAG = "HeadsUpManager"; 44b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private static final boolean DEBUG = false; 45b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private static final String SETTING_HEADS_UP_SNOOZE_LENGTH_MS = "heads_up_snooze_length_ms"; 46b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 47b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private final int mHeadsUpNotificationDecay; 48b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private final int mMinimumDisplayTime; 49b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 50b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private final int mTouchSensitivityDelay; 51b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private final ArrayMap<String, Long> mSnoozedPackages; 52b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private final HashSet<OnHeadsUpChangedListener> mListeners = new HashSet<>(); 53b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private final int mDefaultSnoozeLengthMs; 54b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private final Handler mHandler = new Handler(); 55b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private final Pools.Pool<HeadsUpEntry> mEntryPool = new Pools.Pool<HeadsUpEntry>() { 56b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 57b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private Stack<HeadsUpEntry> mPoolObjects = new Stack<>(); 58b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 59b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek @Override 60b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public HeadsUpEntry acquire() { 61b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (!mPoolObjects.isEmpty()) { 62b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return mPoolObjects.pop(); 63b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 64b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return new HeadsUpEntry(); 65b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 66b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 67b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek @Override 68b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public boolean release(HeadsUpEntry instance) { 69b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek instance.removeAutoCancelCallbacks(); 70b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mPoolObjects.push(instance); 71b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return true; 72b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 73b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek }; 74b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 75b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 76b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private PhoneStatusBar mBar; 77b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private int mSnoozeLengthMs; 78b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private ContentObserver mSettingsObserver; 79b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 80b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private TreeMap<String ,HeadsUpEntry> mHeadsUpEntries = new TreeMap<>(); 81b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private HashSet<String> mSwipedOutKeys = new HashSet<>(); 82b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private int mUser; 83b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private Clock mClock; 84b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private boolean mReleaseOnExpandFinish; 85b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private boolean mTrackingHeadsUp; 86b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>(); 87b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private boolean mIsExpanded; 88b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private boolean mHasPinnedHeadsUp; 89b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 90b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public HeadsUpManager(final Context context) { 91b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek Resources resources = context.getResources(); 92b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mTouchSensitivityDelay = resources.getInteger(R.integer.heads_up_sensitivity_delay); 93b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (DEBUG) Log.v(TAG, "create() " + mTouchSensitivityDelay); 94b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mSnoozedPackages = new ArrayMap<>(); 95b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mDefaultSnoozeLengthMs = resources.getInteger(R.integer.heads_up_default_snooze_length_ms); 96b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mSnoozeLengthMs = mDefaultSnoozeLengthMs; 97b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mMinimumDisplayTime = resources.getInteger(R.integer.heads_up_notification_minimum_time); 98b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mHeadsUpNotificationDecay = 2000000; 99b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mClock = new Clock(); 100b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek // TODO: shadow mSwipeHelper.setMaxSwipeProgress(mMaxAlpha); 101b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 102b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mSnoozeLengthMs = Settings.Global.getInt(context.getContentResolver(), 103b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek SETTING_HEADS_UP_SNOOZE_LENGTH_MS, mDefaultSnoozeLengthMs); 104b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mSettingsObserver = new ContentObserver(mHandler) { 105b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek @Override 106b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void onChange(boolean selfChange) { 107b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek final int packageSnoozeLengthMs = Settings.Global.getInt( 108b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek context.getContentResolver(), SETTING_HEADS_UP_SNOOZE_LENGTH_MS, -1); 109b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (packageSnoozeLengthMs > -1 && packageSnoozeLengthMs != mSnoozeLengthMs) { 110b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mSnoozeLengthMs = packageSnoozeLengthMs; 111b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (DEBUG) Log.v(TAG, "mSnoozeLengthMs = " + mSnoozeLengthMs); 112b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 113b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 114b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek }; 115b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek context.getContentResolver().registerContentObserver( 116b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek Settings.Global.getUriFor(SETTING_HEADS_UP_SNOOZE_LENGTH_MS), false, 117b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mSettingsObserver); 118b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (DEBUG) Log.v(TAG, "mSnoozeLengthMs = " + mSnoozeLengthMs); 119b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 120b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek // TODO: investigate whether this is still needed 121b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek// if (!mHeadsUpEntries.isEmpty()) { 122b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek// whoops, we're on already! 123b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek// showNotification(mHeadsUpEntries); 124b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek// } 125b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 126b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 127b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void setBar(PhoneStatusBar bar) { 128b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mBar = bar; 129b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 130b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 131b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void addListener(OnHeadsUpChangedListener listener) { 132b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mListeners.add(listener); 133b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 134b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 135b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public PhoneStatusBar getBar() { 136b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return mBar; 137b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 138b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 139b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek /** 140b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * Called when posting a new notification to the heads up. 141b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek */ 142b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void showNotification(NotificationData.Entry headsUp) { 143b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (DEBUG) Log.v(TAG, "showNotification"); 144b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek addHeadsUpEntry(headsUp); 145b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek updateNotification(headsUp, true); 146b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek headsUp.setInterruption(); 147b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek updatePinnedHeadsUpState(false); 148b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 149b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 150b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek /** 151b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * Called when updating or posting a notification to the heads up. 152b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek */ 153b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void updateNotification(NotificationData.Entry headsUp, boolean alert) { 154b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (DEBUG) Log.v(TAG, "updateNotification"); 155b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 156b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek headsUp.row.setChildrenExpanded(false /* expanded */, false /* animated */); 157b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek headsUp.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); 158b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 159b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (alert) { 160b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(headsUp.key); 161b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek headsUpEntry.updateEntry(); 162b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek headsUpEntry.entry.row.setInShade(mIsExpanded); 163b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 164b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 165b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 166b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private void addHeadsUpEntry(NotificationData.Entry entry) { 167b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek boolean wasEmpty = mHeadsUpEntries.isEmpty(); 168b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek HeadsUpEntry headsUpEntry = mEntryPool.acquire(); 169b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek headsUpEntry.setEntry(entry); 170b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mHeadsUpEntries.put(entry.key, headsUpEntry); 171b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek for (OnHeadsUpChangedListener listener : mListeners) { 172b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek listener.OnHeadsUpStateChanged(entry, true); 173b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 174b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); 175b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek entry.row.setHeadsUp(true); 176b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 177b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 178b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private void removeHeadsUpEntry(NotificationData.Entry entry) { 179b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek HeadsUpEntry remove = mHeadsUpEntries.remove(entry.key); 180b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mEntryPool.release(remove); 181b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); 182b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek entry.row.setHeadsUp(false); 183b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek for (OnHeadsUpChangedListener listener : mListeners) { 184b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek listener.OnHeadsUpStateChanged(entry, false); 185b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 186b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek updatePinnedHeadsUpState(false); 187b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 188b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 189b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private void updatePinnedHeadsUpState(boolean forceImmediate) { 190b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek boolean hasPinnedHeadsUp = hasPinnedHeadsUpInternal(); 191b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (hasPinnedHeadsUp == mHasPinnedHeadsUp) { 192b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return; 193b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 194b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mHasPinnedHeadsUp = hasPinnedHeadsUp; 195b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek for (OnHeadsUpChangedListener listener :mListeners) { 196b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek listener.OnPinnedHeadsUpExistChanged(hasPinnedHeadsUp, forceImmediate); 197b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 198b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 199b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 200b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek /** 201b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * React to the removal of the notification in the heads up. 202b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * 203b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * @return true if the notification was removed and false if it still needs to be kept around 204b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * for a bit since it wasn't shown long enough 205b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek */ 206b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public boolean removeNotification(String key) { 207b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (DEBUG) Log.v(TAG, "remove"); 208b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (wasShownLongEnough(key)) { 209b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek releaseImmediately(key); 210b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return true; 211b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } else { 212b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek getHeadsUpEntry(key).hideAsSoonAsPossible(); 213b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return false; 214b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 215b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 216b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 217b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private boolean wasShownLongEnough(String key) { 218b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek HeadsUpEntry headsUpEntry = getHeadsUpEntry(key); 219b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek HeadsUpEntry topEntry = getTopEntry(); 220b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (mSwipedOutKeys.contains(key)) { 221b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek // We always instantly dismiss views being manually swiped out. 222b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mSwipedOutKeys.remove(key); 223b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return true; 224b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 225b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (headsUpEntry != topEntry) { 226b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return true; 227b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 228b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return headsUpEntry.wasShownLongEnough(); 229b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 230b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 231b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public boolean isHeadsUp(String key) { 232b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return mHeadsUpEntries.containsKey(key); 233b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 234b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 235b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 236b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek /** 237b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * Push any current Heads Up notification down into the shade. 238b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek */ 239b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void releaseAllImmediately() { 240b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (DEBUG) Log.v(TAG, "releaseAllImmediately"); 241b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek for (String key: mHeadsUpEntries.keySet()) { 242b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek releaseImmediately(key); 243b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 244b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 245b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 246b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void releaseImmediately(String key) { 247b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek HeadsUpEntry headsUpEntry = getHeadsUpEntry(key); 248b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (headsUpEntry == null) { 249b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return; 250b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 251b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek NotificationData.Entry shadeEntry = headsUpEntry.entry; 252b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek removeHeadsUpEntry(shadeEntry); 253b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 254b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 255b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public boolean isSnoozed(String packageName) { 256b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek final String key = snoozeKey(packageName, mUser); 257b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek Long snoozedUntil = mSnoozedPackages.get(key); 258b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (snoozedUntil != null) { 259b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (snoozedUntil > SystemClock.elapsedRealtime()) { 260b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (DEBUG) Log.v(TAG, key + " snoozed"); 261b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return true; 262b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 263b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mSnoozedPackages.remove(packageName); 264b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 265b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return false; 266b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 267b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 268b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void snooze() { 269b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek for (String key: mHeadsUpEntries.keySet()) { 270b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek HeadsUpEntry entry = mHeadsUpEntries.get(key); 271b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek String packageName = entry.entry.notification.getPackageName(); 272b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mSnoozedPackages.put(snoozeKey(packageName, mUser), 273b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek SystemClock.elapsedRealtime() + mSnoozeLengthMs); 274b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 275b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mReleaseOnExpandFinish = true; 276b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 277b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 278b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private static String snoozeKey(String packageName, int user) { 279b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return user + "," + packageName; 280b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 281b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 282b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private HeadsUpEntry getHeadsUpEntry(String key) { 283b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return mHeadsUpEntries.get(key); 284b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 285b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 286b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public NotificationData.Entry getEntry(String key) { 287b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return mHeadsUpEntries.get(key).entry; 288b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 289b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 290b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public TreeMap<String, HeadsUpEntry> getEntries() { 291b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return mHeadsUpEntries; 292b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 293b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 294b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public HeadsUpEntry getTopEntry() { 295b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return mHeadsUpEntries.isEmpty() ? null : mHeadsUpEntries.lastEntry().getValue(); 296b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 297b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 298b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek /** 299b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * @param key the key of the touched notification 300b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek * @return whether the touch is valid and should not be discarded 301b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek */ 302b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public boolean shouldSwallowClick(String key) { 303b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (mClock.currentTimeMillis() < mHeadsUpEntries.get(key).postTime) { 304b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return true; 305b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 306b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return false; 307b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 308b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 309b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress) { 310b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek // TODO: handle the shadow 311b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek //getBackground().setAlpha((int) (255 * swipeProgress)); 312b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return false; 313b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 314b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 315b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) { 316b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek // TODO: Look into touchable region 317b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek// mContentHolder.getLocationOnScreen(mTmpTwoArray); 318b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek// 319b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek// info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); 320b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek// info.touchableRegion.set(mTmpTwoArray[0], mTmpTwoArray[1], 321b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek// mTmpTwoArray[0] + mContentHolder.getWidth(), 322b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek// mTmpTwoArray[1] + mContentHolder.getHeight()); 323b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 324b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 325b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void setUser(int user) { 326b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mUser = user; 327b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 328b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 329b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 330b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek pw.println("HeadsUpManager state:"); 331b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek pw.print(" mTouchSensitivityDelay="); pw.println(mTouchSensitivityDelay); 332b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek pw.print(" mSnoozeLengthMs="); pw.println(mSnoozeLengthMs); 333b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek pw.print(" now="); pw.println(SystemClock.elapsedRealtime()); 334b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek pw.print(" mUser="); pw.println(mUser); 335b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek for (String key: mHeadsUpEntries.keySet()) { 336b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek pw.print(" HeadsUpEntry="); pw.println(mHeadsUpEntries.get(key)); 337b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 338b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek int N = mSnoozedPackages.size(); 339b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek pw.println(" snoozed packages: " + N); 340b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek for (int i = 0; i < N; i++) { 341b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek pw.print(" "); pw.print(mSnoozedPackages.valueAt(i)); 342b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek pw.print(", "); pw.println(mSnoozedPackages.keyAt(i)); 343b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 344b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 345b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 346b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public boolean hasPinnedHeadsUp() { 347b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return mHasPinnedHeadsUp; 348b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 349b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 350b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private boolean hasPinnedHeadsUpInternal() { 351b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek for (String key: mHeadsUpEntries.keySet()) { 352b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek HeadsUpEntry entry = mHeadsUpEntries.get(key); 353b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (!entry.entry.row.isInShade()) { 354b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return true; 355b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 356b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 357b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return false; 358b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 359b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 360b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void addSwipedOutKey(String key) { 361b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mSwipedOutKeys.add(key); 362b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 363b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 364b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public float getHighestPinnedHeadsUp() { 365b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek float max = 0; 366b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek for (String key: mHeadsUpEntries.keySet()) { 367b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek HeadsUpEntry entry = mHeadsUpEntries.get(key); 368b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (!entry.entry.row.isInShade()) { 369b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek max = Math.max(max, entry.entry.row.getActualHeight()); 370b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 371b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 372b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return max; 373b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 374b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 375b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void releaseAllToShade() { 376b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek for (String key: mHeadsUpEntries.keySet()) { 377b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek HeadsUpEntry entry = mHeadsUpEntries.get(key); 378b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek entry.entry.row.setInShade(true); 379b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 380b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek updatePinnedHeadsUpState(true); 381b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 382b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 383b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void onExpandingFinished() { 384b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (mReleaseOnExpandFinish) { 385b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek releaseAllImmediately(); 386b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mReleaseOnExpandFinish = false; 387b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } else { 388b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek for (NotificationData.Entry entry : mEntriesToRemoveAfterExpand) { 389b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek removeHeadsUpEntry(entry); 390b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 391b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mEntriesToRemoveAfterExpand.clear(); 392b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 393b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 394b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 395b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void setTrackingHeadsUp(boolean trackingHeadsUp) { 396b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mTrackingHeadsUp = trackingHeadsUp; 397b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 398b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 399b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void setIsExpanded(boolean isExpanded) { 400b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mIsExpanded = isExpanded; 401b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 402b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 403b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public int getTopHeadsUpHeight() { 404b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek HeadsUpEntry topEntry = getTopEntry(); 405b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return topEntry != null ? topEntry.entry.row.getHeadsUpHeight() : 0; 406b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 407b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 408b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public class HeadsUpEntry implements Comparable<HeadsUpEntry> { 409b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public NotificationData.Entry entry; 410b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public long postTime; 411b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public long earliestRemovaltime; 412b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek private Runnable mRemoveHeadsUpRunnable; 413b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 414b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void setEntry(final NotificationData.Entry entry) { 415b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek this.entry = entry; 416b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 417b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek // The actual post time will be just after the heads-up really slided in 418b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek postTime = mClock.currentTimeMillis() + mTouchSensitivityDelay; 419b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mRemoveHeadsUpRunnable = new Runnable() { 420b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek @Override 421b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void run() { 422b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (!mTrackingHeadsUp) { 423b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek removeHeadsUpEntry(entry); 424b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } else { 425b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mEntriesToRemoveAfterExpand.add(entry); 426b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 427b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 428b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek }; 429b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek updateEntry(); 430b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 431b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 432b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void updateEntry() { 433b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek long currentTime = mClock.currentTimeMillis(); 434b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek postTime = Math.max(postTime, currentTime); 435b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek long finishTime = postTime + mHeadsUpNotificationDecay; 436b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime); 437b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek earliestRemovaltime = currentTime + mMinimumDisplayTime; 438b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek removeAutoCancelCallbacks(); 439b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mHandler.postDelayed(mRemoveHeadsUpRunnable, removeDelay); 440b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 441b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 442b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek @Override 443b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public int compareTo(HeadsUpEntry o) { 444b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return postTime < o.postTime ? -1 445b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek : postTime == o.postTime ? 0 446b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek : 1; 447b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 448b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 449b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void removeAutoCancelCallbacks() { 450b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mHandler.removeCallbacks(mRemoveHeadsUpRunnable); 451b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 452b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 453b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public boolean wasShownLongEnough() { 454b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return earliestRemovaltime < mClock.currentTimeMillis(); 455b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 456b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 457b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void hideAsSoonAsPossible() { 458b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek removeAutoCancelCallbacks(); 459b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mHandler.postDelayed(mRemoveHeadsUpRunnable, 460b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek earliestRemovaltime - mClock.currentTimeMillis()); 461b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 462b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 463b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 464b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public static class Clock { 465b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public long currentTimeMillis() { 466b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek return SystemClock.elapsedRealtime(); 467b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 468b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 469b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 470b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public interface OnHeadsUpChangedListener { 471b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly); 472b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp); 473b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 474b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek} 475