blob: 2446535ae73dcdf029b8a151195f294958aeeb08 [file] [log] [blame]
Chris Wren51c75102013-07-16 20:49:17 -04001/*
2 * Copyright (C) 2013 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
17package com.android.systemui.statusbar;
18
Mady Mellor4b80b102016-01-22 08:03:58 -080019import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.animation.AnimatorSet;
22import android.animation.ObjectAnimator;
23import android.animation.ValueAnimator;
24import android.animation.ValueAnimator.AnimatorUpdateListener;
Selim Cineka6c6bfb2015-10-29 16:27:08 -070025import android.app.Notification;
Chris Wren51c75102013-07-16 20:49:17 -040026import android.content.Context;
Selim Cinekcab4a602014-09-03 14:47:57 +020027import android.graphics.drawable.AnimatedVectorDrawable;
28import android.graphics.drawable.AnimationDrawable;
Selim Cinekb5605e52015-02-20 18:21:41 +010029import android.graphics.drawable.ColorDrawable;
Selim Cinekcab4a602014-09-03 14:47:57 +020030import android.graphics.drawable.Drawable;
Selim Cinekda42d652015-12-04 15:51:16 -080031import android.os.Build;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +020032import android.service.notification.StatusBarNotification;
Chris Wren51c75102013-07-16 20:49:17 -040033import android.util.AttributeSet;
Selim Cinek01af3342016-02-09 19:25:31 -080034import android.view.LayoutInflater;
Selim Cinek6183d122016-01-14 18:48:41 -080035import android.view.MotionEvent;
Selim Cinekeaa29ca2015-11-23 13:51:13 -080036import android.view.NotificationHeaderView;
Dan Sandlera5e0f412014-01-23 15:11:54 -050037import android.view.View;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +020038import android.view.ViewStub;
Jorim Jaggife40f7d2014-04-28 15:20:04 +020039import android.view.accessibility.AccessibilityEvent;
Selim Cinek98713a42015-09-21 15:47:20 +020040import android.widget.Chronometer;
Selim Cinekcab4a602014-09-03 14:47:57 +020041import android.widget.ImageView;
Selim Cinekeaa29ca2015-11-23 13:51:13 -080042import android.widget.RemoteViews;
Selim Cinekb5605e52015-02-20 18:21:41 +010043
Dan Sandlera5e0f412014-01-23 15:11:54 -050044import com.android.systemui.R;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070045import com.android.systemui.classifier.FalsingManager;
Selim Cinekc897bd32016-03-18 17:32:31 -070046import com.android.systemui.statusbar.notification.HybridNotificationView;
Selim Cinek0ffbda62016-01-01 20:29:12 +010047import com.android.systemui.statusbar.notification.NotificationViewWrapper;
Selim Cinekb5605e52015-02-20 18:21:41 +010048import com.android.systemui.statusbar.phone.NotificationGroupManager;
Selim Cinek31aada42015-12-18 17:51:15 -080049import com.android.systemui.statusbar.policy.HeadsUpManager;
Selim Cinekb5605e52015-02-20 18:21:41 +010050import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
51import com.android.systemui.statusbar.stack.StackScrollState;
52import com.android.systemui.statusbar.stack.StackStateAnimator;
53import com.android.systemui.statusbar.stack.StackViewState;
54
Mady Mellor4b80b102016-01-22 08:03:58 -080055import java.util.ArrayList;
Selim Cinekb5605e52015-02-20 18:21:41 +010056import java.util.List;
Dan Sandlera5e0f412014-01-23 15:11:54 -050057
Jorim Jaggi4222d9a2014-04-23 16:13:15 +020058public class ExpandableNotificationRow extends ActivatableNotificationView {
Selim Cinekb5605e52015-02-20 18:21:41 +010059
60 private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
61 private static final int COLORED_DIVIDER_ALPHA = 0x7B;
Selim Cinek01af3342016-02-09 19:25:31 -080062 private int mNotificationMinHeightLegacy;
63 private int mMaxHeadsUpHeightLegacy;
64 private int mMaxHeadsUpHeight;
65 private int mNotificationMinHeight;
66 private int mNotificationMaxHeight;
Chris Wren51c75102013-07-16 20:49:17 -040067
Selim Cinek1685e632014-04-08 02:27:49 +020068 /** Does this row contain layouts that can adapt to row expansion */
Chris Wren51c75102013-07-16 20:49:17 -040069 private boolean mExpandable;
Selim Cinek1685e632014-04-08 02:27:49 +020070 /** Has the user actively changed the expansion state of this row */
71 private boolean mHasUserChangedExpansion;
72 /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */
Chris Wren51c75102013-07-16 20:49:17 -040073 private boolean mUserExpanded;
Selim Cinek31aada42015-12-18 17:51:15 -080074
75 /**
76 * Has this notification been expanded while it was pinned
77 */
78 private boolean mExpandedWhenPinned;
Selim Cinek1685e632014-04-08 02:27:49 +020079 /** Is the user touching this row */
Chris Wren51c75102013-07-16 20:49:17 -040080 private boolean mUserLocked;
Selim Cinek1685e632014-04-08 02:27:49 +020081 /** Are we showing the "public" version */
Dan Sandlera5e0f412014-01-23 15:11:54 -050082 private boolean mShowingPublic;
Jorim Jaggiae441282014-08-01 02:45:18 +020083 private boolean mSensitive;
Selim Cinek3c76d502016-02-19 15:16:33 -080084 private boolean mSensitiveHiddenInGeneral;
Jorim Jaggiae441282014-08-01 02:45:18 +020085 private boolean mShowingPublicInitialized;
Selim Cinek60122be2015-04-15 18:16:50 -070086 private boolean mHideSensitiveForIntrinsicHeight;
Chris Wren51c75102013-07-16 20:49:17 -040087
Selim Cinek1685e632014-04-08 02:27:49 +020088 /**
89 * Is this notification expanded by the system. The expansion state can be overridden by the
90 * user expansion.
91 */
92 private boolean mIsSystemExpanded;
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020093
94 /**
Selim Cinek83bc7832015-10-22 13:26:54 -070095 * Whether the notification is on the keyguard and the expansion is disabled.
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020096 */
Selim Cinek83bc7832015-10-22 13:26:54 -070097 private boolean mOnKeyguard;
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020098
Mady Mellor4b80b102016-01-22 08:03:58 -080099 private AnimatorSet mTranslateAnim;
100 private ArrayList<View> mTranslateableViews;
Jorim Jaggibe565df2014-04-28 17:51:23 +0200101 private NotificationContentView mPublicLayout;
102 private NotificationContentView mPrivateLayout;
Selim Cinek1685e632014-04-08 02:27:49 +0200103 private int mMaxExpandHeight;
Selim Cinek8d490d42015-04-10 00:05:50 -0700104 private int mHeadsUpHeight;
Selim Cinek863834b2014-05-20 04:20:25 +0200105 private View mVetoButton;
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400106 private boolean mClearable;
Chris Wren78403d72014-07-28 10:23:24 +0100107 private ExpansionLogger mLogger;
108 private String mLoggingKey;
Mady Mellor4b80b102016-01-22 08:03:58 -0800109 private NotificationSettingsIconRow mSettingsIconRow;
Selim Cinek8d490d42015-04-10 00:05:50 -0700110 private NotificationGuts mGuts;
Selim Cinekda42d652015-12-04 15:51:16 -0800111 private NotificationData.Entry mEntry;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200112 private StatusBarNotification mStatusBarNotification;
Selim Cinek1a521f32014-11-03 17:39:29 +0100113 private boolean mIsHeadsUp;
Selim Cinek98713a42015-09-21 15:47:20 +0200114 private boolean mLastChronometerRunning = true;
Selim Cinekeef84282015-10-30 16:28:00 -0700115 private NotificationHeaderView mNotificationHeader;
Selim Cinek9c7712d2015-12-08 19:19:48 -0800116 private NotificationViewWrapper mNotificationHeaderWrapper;
Selim Cinekb5605e52015-02-20 18:21:41 +0100117 private ViewStub mChildrenContainerStub;
118 private NotificationGroupManager mGroupManager;
Selim Cinekb5605e52015-02-20 18:21:41 +0100119 private boolean mChildrenExpanded;
Selim Cinek263398f2015-10-21 17:40:23 -0700120 private boolean mIsSummaryWithChildren;
Selim Cinekb5605e52015-02-20 18:21:41 +0100121 private NotificationChildrenContainer mChildrenContainer;
Mady Mellor4b80b102016-01-22 08:03:58 -0800122 private ViewStub mSettingsIconRowStub;
Selim Cinekab29aeb2015-02-20 18:18:32 +0100123 private ViewStub mGutsStub;
Selim Cinekb5605e52015-02-20 18:21:41 +0100124 private boolean mIsSystemChildExpanded;
Selim Cinek684a4422015-04-15 16:18:39 -0700125 private boolean mIsPinned;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700126 private FalsingManager mFalsingManager;
Selim Cinek31aada42015-12-18 17:51:15 -0800127 private HeadsUpManager mHeadsUpManager;
Selim Cinekea4bef72015-12-02 15:51:10 -0800128 private NotificationHeaderUtil mHeaderUtil = new NotificationHeaderUtil(this);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200129
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700130 private boolean mJustClicked;
Selim Cinek5a175d92015-11-23 18:01:33 -0800131 private boolean mIconAnimationRunning;
Selim Cinek34d93b02015-10-22 12:30:38 -0700132 private boolean mShowNoBackground;
Selim Cinek388df6d2015-10-22 13:25:11 -0700133 private ExpandableNotificationRow mNotificationParent;
Selim Cinek570981d2015-12-01 11:37:01 -0800134 private OnExpandClickListener mOnExpandClickListener;
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800135 private OnClickListener mExpandClickListener = new OnClickListener() {
136 @Override
137 public void onClick(View v) {
Selim Cinek624c02db2015-12-14 21:00:02 -0800138 if (!mShowingPublic && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800139 mGroupManager.toggleGroupExpansion(mStatusBarNotification);
Selim Cinek31aada42015-12-18 17:51:15 -0800140 mOnExpandClickListener.onExpandClicked(mEntry,
Selim Cinek570981d2015-12-01 11:37:01 -0800141 mGroupManager.isGroupExpanded(mStatusBarNotification));
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800142 } else {
Selim Cinek31aada42015-12-18 17:51:15 -0800143 boolean nowExpanded;
144 if (isPinned()) {
145 nowExpanded = !mExpandedWhenPinned;
146 mExpandedWhenPinned = nowExpanded;
147 } else {
148 nowExpanded = !isExpanded();
149 setUserExpanded(nowExpanded);
150 }
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800151 notifyHeightChanged(true);
Selim Cinek31aada42015-12-18 17:51:15 -0800152 mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800153 }
154 }
155 };
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700156
Selim Cinek8d490d42015-04-10 00:05:50 -0700157 public NotificationContentView getPrivateLayout() {
158 return mPrivateLayout;
159 }
160
161 public NotificationContentView getPublicLayout() {
162 return mPublicLayout;
163 }
164
Selim Cinekcab4a602014-09-03 14:47:57 +0200165 public void setIconAnimationRunning(boolean running) {
166 setIconAnimationRunning(running, mPublicLayout);
167 setIconAnimationRunning(running, mPrivateLayout);
Selim Cinek5a175d92015-11-23 18:01:33 -0800168 setIconAnimationRunningForChild(running, mNotificationHeader);
169 if (mIsSummaryWithChildren) {
170 List<ExpandableNotificationRow> notificationChildren =
171 mChildrenContainer.getNotificationChildren();
172 for (int i = 0; i < notificationChildren.size(); i++) {
173 ExpandableNotificationRow child = notificationChildren.get(i);
174 child.setIconAnimationRunning(running);
175 }
176 }
177 mIconAnimationRunning = running;
Selim Cinekcab4a602014-09-03 14:47:57 +0200178 }
179
180 private void setIconAnimationRunning(boolean running, NotificationContentView layout) {
181 if (layout != null) {
182 View contractedChild = layout.getContractedChild();
183 View expandedChild = layout.getExpandedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -0700184 View headsUpChild = layout.getHeadsUpChild();
Selim Cinekcab4a602014-09-03 14:47:57 +0200185 setIconAnimationRunningForChild(running, contractedChild);
186 setIconAnimationRunningForChild(running, expandedChild);
Selim Cinek8d490d42015-04-10 00:05:50 -0700187 setIconAnimationRunningForChild(running, headsUpChild);
Selim Cinekcab4a602014-09-03 14:47:57 +0200188 }
189 }
190
191 private void setIconAnimationRunningForChild(boolean running, View child) {
192 if (child != null) {
193 ImageView icon = (ImageView) child.findViewById(com.android.internal.R.id.icon);
194 setIconRunning(icon, running);
195 ImageView rightIcon = (ImageView) child.findViewById(
196 com.android.internal.R.id.right_icon);
197 setIconRunning(rightIcon, running);
198 }
199 }
200
201 private void setIconRunning(ImageView imageView, boolean running) {
202 if (imageView != null) {
203 Drawable drawable = imageView.getDrawable();
204 if (drawable instanceof AnimationDrawable) {
205 AnimationDrawable animationDrawable = (AnimationDrawable) drawable;
206 if (running) {
207 animationDrawable.start();
208 } else {
209 animationDrawable.stop();
210 }
211 } else if (drawable instanceof AnimatedVectorDrawable) {
212 AnimatedVectorDrawable animationDrawable = (AnimatedVectorDrawable) drawable;
213 if (running) {
214 animationDrawable.start();
215 } else {
216 animationDrawable.stop();
217 }
218 }
219 }
220 }
221
Selim Cinekda42d652015-12-04 15:51:16 -0800222 public void onNotificationUpdated(NotificationData.Entry entry) {
223 mEntry = entry;
224 mStatusBarNotification = entry.notification;
Adrian Roosb88b1a12015-12-09 18:51:05 -0800225 mPrivateLayout.onNotificationUpdated(entry);
226 mPublicLayout.onNotificationUpdated(entry);
Selim Cinek757d8792016-01-28 16:21:08 -0800227 mShowingPublicInitialized = false;
228 updateClearability();
Selim Cinek8fc93c92015-11-23 17:48:07 -0800229 if (mIsSummaryWithChildren) {
230 recreateNotificationHeader();
Selim Cinekc897bd32016-03-18 17:32:31 -0700231 mChildrenContainer.onNotificationUpdated();
Selim Cinek8fc93c92015-11-23 17:48:07 -0800232 }
Selim Cinek5a175d92015-11-23 18:01:33 -0800233 if (mIconAnimationRunning) {
234 setIconAnimationRunning(true);
235 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800236 if (mNotificationParent != null) {
237 mNotificationParent.updateChildrenHeaderAppearance();
238 }
Selim Cinek263398f2015-10-21 17:40:23 -0700239 onChildrenCountChanged();
Selim Cinek624c02db2015-12-14 21:00:02 -0800240 // The public layouts expand button is always visible
241 mPublicLayout.updateExpandButtons(true);
Selim Cinekda42d652015-12-04 15:51:16 -0800242 updateLimits();
243 }
244
245 private void updateLimits() {
Selim Cineka1744872016-03-11 15:36:06 -0800246 updateLimitsForView(mPrivateLayout);
247 updateLimitsForView(mPublicLayout);
248 }
249
250 private void updateLimitsForView(NotificationContentView layout) {
251 boolean customView = layout.getContractedChild().getId()
Selim Cinekda42d652015-12-04 15:51:16 -0800252 != com.android.internal.R.id.status_bar_latest_event_content;
253 boolean beforeN = mEntry.targetSdk < Build.VERSION_CODES.N;
254 int minHeight = customView && beforeN && !mIsSummaryWithChildren ?
255 mNotificationMinHeightLegacy : mNotificationMinHeight;
Selim Cineka1744872016-03-11 15:36:06 -0800256 boolean headsUpCustom = layout.getHeadsUpChild() != null &&
257 layout.getHeadsUpChild().getId()
258 != com.android.internal.R.id.status_bar_latest_event_content;
Selim Cinek77019c72015-12-09 10:18:02 -0800259 int headsUpheight = headsUpCustom && beforeN ? mMaxHeadsUpHeightLegacy
260 : mMaxHeadsUpHeight;
Selim Cineka1744872016-03-11 15:36:06 -0800261 layout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200262 }
263
264 public StatusBarNotification getStatusBarNotification() {
265 return mStatusBarNotification;
266 }
267
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700268 public boolean isHeadsUp() {
269 return mIsHeadsUp;
270 }
271
Selim Cinek1a521f32014-11-03 17:39:29 +0100272 public void setHeadsUp(boolean isHeadsUp) {
Selim Cinekc80fdb12015-04-13 15:09:08 -0700273 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek1a521f32014-11-03 17:39:29 +0100274 mIsHeadsUp = isHeadsUp;
Selim Cinek8d490d42015-04-10 00:05:50 -0700275 mPrivateLayout.setHeadsUp(isHeadsUp);
Selim Cinekc80fdb12015-04-13 15:09:08 -0700276 if (intrinsicBefore != getIntrinsicHeight()) {
277 notifyHeightChanged(false /* needsAnimation */);
278 }
Selim Cinek1a521f32014-11-03 17:39:29 +0100279 }
280
Selim Cinekb5605e52015-02-20 18:21:41 +0100281 public void setGroupManager(NotificationGroupManager groupManager) {
282 mGroupManager = groupManager;
Selim Cinek83bc7832015-10-22 13:26:54 -0700283 mPrivateLayout.setGroupManager(groupManager);
Selim Cinekb5605e52015-02-20 18:21:41 +0100284 }
285
Adrian Roosb88b1a12015-12-09 18:51:05 -0800286 public void setRemoteInputController(RemoteInputController r) {
287 mPrivateLayout.setRemoteInputController(r);
288 }
289
Selim Cinekb5605e52015-02-20 18:21:41 +0100290 public void addChildNotification(ExpandableNotificationRow row) {
291 addChildNotification(row, -1);
292 }
293
294 /**
295 * Add a child notification to this view.
296 *
297 * @param row the row to add
298 * @param childIndex the index to add it at, if -1 it will be added at the end
299 */
300 public void addChildNotification(ExpandableNotificationRow row, int childIndex) {
301 if (mChildrenContainer == null) {
302 mChildrenContainerStub.inflate();
303 }
304 mChildrenContainer.addNotification(row, childIndex);
Selim Cinek263398f2015-10-21 17:40:23 -0700305 onChildrenCountChanged();
306 row.setIsChildInGroup(true, this);
Selim Cinekb5605e52015-02-20 18:21:41 +0100307 }
308
309 public void removeChildNotification(ExpandableNotificationRow row) {
310 if (mChildrenContainer != null) {
311 mChildrenContainer.removeNotification(row);
312 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800313 mHeaderUtil.restoreNotificationHeader(row);
Selim Cinek263398f2015-10-21 17:40:23 -0700314 onChildrenCountChanged();
315 row.setIsChildInGroup(false, null);
316 }
317
318 public boolean isChildInGroup() {
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700319 return mNotificationParent != null;
Selim Cinek263398f2015-10-21 17:40:23 -0700320 }
321
Selim Cinek388df6d2015-10-22 13:25:11 -0700322 public ExpandableNotificationRow getNotificationParent() {
323 return mNotificationParent;
324 }
325
Selim Cinek263398f2015-10-21 17:40:23 -0700326 /**
327 * @param isChildInGroup Is this notification now in a group
328 * @param parent the new parent notification
329 */
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700330 public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {;
331 boolean childInGroup = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
332 mNotificationParent = childInGroup ? parent : null;
333 mPrivateLayout.setIsChildInGroup(childInGroup);
334 updateNoBackgroundState();
Selim Cinek34d93b02015-10-22 12:30:38 -0700335 }
336
337 @Override
Selim Cinek72109472016-01-15 16:33:22 -0800338 public boolean onTouchEvent(MotionEvent event) {
339 if (event.getActionMasked() != MotionEvent.ACTION_DOWN
340 || !isChildInGroup() || isGroupExpanded()) {
341 return super.onTouchEvent(event);
342 } else {
343 return false;
344 }
345 }
346
347 @Override
Mady Mellorf0625802016-02-11 18:03:48 -0800348 protected boolean handleSlideBack() {
349 if (mSettingsIconRow != null && mSettingsIconRow.isVisible()) {
350 animateTranslateNotification(0 /* targetLeft */);
351 return true;
352 }
353 return false;
354 }
355
356 @Override
Selim Cinek34d93b02015-10-22 12:30:38 -0700357 protected boolean shouldHideBackground() {
358 return super.shouldHideBackground() || mShowNoBackground;
Selim Cinek263398f2015-10-21 17:40:23 -0700359 }
360
361 @Override
362 public boolean isSummaryWithChildren() {
363 return mIsSummaryWithChildren;
Selim Cinekb5605e52015-02-20 18:21:41 +0100364 }
365
366 @Override
367 public boolean areChildrenExpanded() {
368 return mChildrenExpanded;
369 }
370
371 public List<ExpandableNotificationRow> getNotificationChildren() {
372 return mChildrenContainer == null ? null : mChildrenContainer.getNotificationChildren();
373 }
374
Selim Cinekeef84282015-10-30 16:28:00 -0700375 public int getNumberOfNotificationChildren() {
376 if (mChildrenContainer == null) {
377 return 0;
378 }
379 return mChildrenContainer.getNotificationChildren().size();
380 }
381
Selim Cinekb5605e52015-02-20 18:21:41 +0100382 /**
383 * Apply the order given in the list to the children.
384 *
385 * @param childOrder the new list order
386 * @return whether the list order has changed
387 */
388 public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder) {
389 return mChildrenContainer != null && mChildrenContainer.applyChildOrder(childOrder);
390 }
391
392 public void getChildrenStates(StackScrollState resultState) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700393 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100394 StackViewState parentState = resultState.getViewStateForView(this);
395 mChildrenContainer.getState(resultState, parentState);
396 }
397 }
398
399 public void applyChildrenState(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700400 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100401 mChildrenContainer.applyState(state);
402 }
403 }
404
405 public void prepareExpansionChanged(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700406 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100407 mChildrenContainer.prepareExpansionChanged(state);
408 }
409 }
410
411 public void startChildAnimation(StackScrollState finalState,
Selim Cinek99695592016-01-12 17:51:35 -0800412 StackStateAnimator stateAnimator, long delay, long duration) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700413 if (mIsSummaryWithChildren) {
Selim Cinek99695592016-01-12 17:51:35 -0800414 mChildrenContainer.startAnimationToState(finalState, stateAnimator, delay,
Selim Cinekb5605e52015-02-20 18:21:41 +0100415 duration);
416 }
417 }
418
419 public ExpandableNotificationRow getViewAtPosition(float y) {
Selim Cinek43d30f02016-03-04 10:51:32 -0800420 if (!mIsSummaryWithChildren || !mChildrenExpanded) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100421 return this;
422 } else {
423 ExpandableNotificationRow view = mChildrenContainer.getViewAtPosition(y);
424 return view == null ? this : view;
425 }
426 }
427
Selim Cinekab29aeb2015-02-20 18:18:32 +0100428 public NotificationGuts getGuts() {
429 return mGuts;
430 }
431
Selim Cinek684a4422015-04-15 16:18:39 -0700432 /**
433 * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this
434 * the notification will be rendered on top of the screen.
435 *
436 * @param pinned whether it is pinned
437 */
438 public void setPinned(boolean pinned) {
439 mIsPinned = pinned;
Selim Cinek31aada42015-12-18 17:51:15 -0800440 if (pinned) {
441 setIconAnimationRunning(true);
442 mExpandedWhenPinned = false;
443 } else if (mExpandedWhenPinned) {
444 setUserExpanded(true);
445 }
Selim Cinek98713a42015-09-21 15:47:20 +0200446 setChronometerRunning(mLastChronometerRunning);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700447 }
448
Selim Cinek684a4422015-04-15 16:18:39 -0700449 public boolean isPinned() {
450 return mIsPinned;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700451 }
452
Selim Cinek31aada42015-12-18 17:51:15 -0800453 /**
454 * @param atLeastMinHeight should the value returned be at least the minimum height.
455 * Used to avoid cyclic calls
456 * @return the height of the heads up notification when pinned
457 */
458 public int getPinnedHeadsUpHeight(boolean atLeastMinHeight) {
Selim Cinek77019c72015-12-09 10:18:02 -0800459 if (mIsSummaryWithChildren) {
460 return mChildrenContainer.getIntrinsicHeight();
461 }
Selim Cinek31aada42015-12-18 17:51:15 -0800462 if(mExpandedWhenPinned) {
463 return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
464 } else if (atLeastMinHeight) {
465 return Math.max(getMinHeight(), mHeadsUpHeight);
466 } else {
467 return mHeadsUpHeight;
468 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700469 }
470
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700471 /**
472 * Mark whether this notification was just clicked, i.e. the user has just clicked this
473 * notification in this frame.
474 */
475 public void setJustClicked(boolean justClicked) {
476 mJustClicked = justClicked;
477 }
478
479 /**
480 * @return true if this notification has been clicked in this frame, false otherwise
481 */
482 public boolean wasJustClicked() {
483 return mJustClicked;
484 }
485
Selim Cinek98713a42015-09-21 15:47:20 +0200486 public void setChronometerRunning(boolean running) {
487 mLastChronometerRunning = running;
488 setChronometerRunning(running, mPrivateLayout);
489 setChronometerRunning(running, mPublicLayout);
490 if (mChildrenContainer != null) {
491 List<ExpandableNotificationRow> notificationChildren =
492 mChildrenContainer.getNotificationChildren();
493 for (int i = 0; i < notificationChildren.size(); i++) {
494 ExpandableNotificationRow child = notificationChildren.get(i);
495 child.setChronometerRunning(running);
496 }
497 }
498 }
499
500 private void setChronometerRunning(boolean running, NotificationContentView layout) {
501 if (layout != null) {
502 running = running || isPinned();
503 View contractedChild = layout.getContractedChild();
504 View expandedChild = layout.getExpandedChild();
505 View headsUpChild = layout.getHeadsUpChild();
506 setChronometerRunningForChild(running, contractedChild);
507 setChronometerRunningForChild(running, expandedChild);
508 setChronometerRunningForChild(running, headsUpChild);
509 }
510 }
511
512 private void setChronometerRunningForChild(boolean running, View child) {
513 if (child != null) {
514 View chronometer = child.findViewById(com.android.internal.R.id.chronometer);
515 if (chronometer instanceof Chronometer) {
516 ((Chronometer) chronometer).setStarted(running);
517 }
518 }
519 }
520
Selim Cinekea4bef72015-12-02 15:51:10 -0800521 public NotificationHeaderView getNotificationHeader() {
522 if (mNotificationHeader != null) {
523 return mNotificationHeader;
Selim Cinek8d6440d2015-10-22 13:00:05 -0700524 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800525 return mPrivateLayout.getNotificationHeader();
Selim Cinek8d6440d2015-10-22 13:00:05 -0700526 }
527
Selim Cinek34eda5e2016-02-18 17:10:43 -0800528 private NotificationHeaderView getVisibleNotificationHeader() {
529 if (mNotificationHeader != null) {
530 return mNotificationHeader;
531 }
532 return getShowingLayout().getVisibleNotificationHeader();
533 }
534
Selim Cinek570981d2015-12-01 11:37:01 -0800535 public void setOnExpandClickListener(OnExpandClickListener onExpandClickListener) {
536 mOnExpandClickListener = onExpandClickListener;
537 }
538
Selim Cinek31aada42015-12-18 17:51:15 -0800539 public void setHeadsUpManager(HeadsUpManager headsUpManager) {
540 mHeadsUpManager = headsUpManager;
541 }
542
Selim Cinek01af3342016-02-09 19:25:31 -0800543 public void reInflateViews() {
544 initDimens();
545 if (mIsSummaryWithChildren) {
546 removeView(mNotificationHeader);
547 mNotificationHeader = null;
548 recreateNotificationHeader();
549 if (mChildrenContainer != null) {
550 mChildrenContainer.reInflateViews();
551 }
552 }
553 if (mGuts != null) {
554 View oldGuts = mGuts;
555 int index = indexOfChild(oldGuts);
556 removeView(oldGuts);
557 mGuts = (NotificationGuts) LayoutInflater.from(mContext).inflate(
558 R.layout.notification_guts, this, false);
559 mGuts.setVisibility(oldGuts.getVisibility());
560 addView(mGuts, index);
561 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800562 if (mSettingsIconRow != null) {
563 View oldSettings = mSettingsIconRow;
564 int settingsIndex = indexOfChild(oldSettings);
565 removeView(oldSettings);
566 mSettingsIconRow = (NotificationSettingsIconRow) LayoutInflater.from(mContext).inflate(
567 R.layout.notification_settings_icon_row, this, false);
568 mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
569 mSettingsIconRow.setVisibility(oldSettings.getVisibility());
570 addView(mSettingsIconRow, settingsIndex);
571
572 }
Selim Cinekde33a4a2016-02-11 16:43:41 -0800573 mPrivateLayout.reInflateViews();
574 mPublicLayout.reInflateViews();
Selim Cinek01af3342016-02-09 19:25:31 -0800575 }
576
Selim Cinekc3179332016-03-04 14:44:56 -0800577 public void setContentBackground(int customBackgroundColor, boolean animate,
578 NotificationContentView notificationContentView) {
579 if (getShowingLayout() == notificationContentView) {
580 setTintColor(customBackgroundColor, animate);
581 }
582 }
583
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700584 public void closeRemoteInput() {
585 mPrivateLayout.closeRemoteInput();
586 mPublicLayout.closeRemoteInput();
587 }
588
Selim Cinekc897bd32016-03-18 17:32:31 -0700589 /**
590 * Set by how much the single line view should be indented.
591 */
592 public void setSingleLineWidthIndention(int indention) {
593 mPrivateLayout.setSingleLineWidthIndention(indention);
594 }
595
596 public int getNotificationColor() {
597 int color = getStatusBarNotification().getNotification().color;
598 if (color == Notification.COLOR_DEFAULT) {
599 return mContext.getColor(com.android.internal.R.color.notification_icon_default_color);
600 }
601 return color;
602 }
603
604 public HybridNotificationView getSingleLineView() {
605 return mPrivateLayout.getSingleLineView();
606 }
607
Selim Cinekf07d0622016-03-21 19:52:52 -0700608 public boolean isOnKeyguard() {
609 return mOnKeyguard;
610 }
611
Chris Wren78403d72014-07-28 10:23:24 +0100612 public interface ExpansionLogger {
613 public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
614 }
Selim Cinek1685e632014-04-08 02:27:49 +0200615
Chris Wren51c75102013-07-16 20:49:17 -0400616 public ExpandableNotificationRow(Context context, AttributeSet attrs) {
617 super(context, attrs);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700618 mFalsingManager = FalsingManager.getInstance(context);
Selim Cinek01af3342016-02-09 19:25:31 -0800619 initDimens();
620 }
621
622 private void initDimens() {
Selim Cinekf619ffc2016-02-17 14:53:05 -0800623 mNotificationMinHeightLegacy = getFontScaledHeight(R.dimen.notification_min_height_legacy);
624 mNotificationMinHeight = getFontScaledHeight(R.dimen.notification_min_height);
625 mNotificationMaxHeight = getFontScaledHeight(R.dimen.notification_max_height);
626 mMaxHeadsUpHeightLegacy = getFontScaledHeight(
Selim Cinek77019c72015-12-09 10:18:02 -0800627 R.dimen.notification_max_heads_up_height_legacy);
Selim Cinekf619ffc2016-02-17 14:53:05 -0800628 mMaxHeadsUpHeight = getFontScaledHeight(R.dimen.notification_max_heads_up_height);
629 }
630
631 /**
632 * @param dimenId the dimen to look up
633 * @return the font scaled dimen as if it were in sp but doesn't shrink sizes below dp
634 */
635 private int getFontScaledHeight(int dimenId) {
636 int dimensionPixelSize = getResources().getDimensionPixelSize(dimenId);
637 float factor = Math.max(1.0f, getResources().getDisplayMetrics().scaledDensity /
638 getResources().getDisplayMetrics().density);
639 return (int) (dimensionPixelSize * factor);
Chris Wren51c75102013-07-16 20:49:17 -0400640 }
641
Christoph Studera7fe6312014-06-27 19:32:44 +0200642 /**
643 * Resets this view so it can be re-used for an updated notification.
644 */
Christoph Studer22f2ee52014-07-29 22:57:21 +0200645 @Override
Christoph Studera7fe6312014-06-27 19:32:44 +0200646 public void reset() {
Christoph Studer22f2ee52014-07-29 22:57:21 +0200647 super.reset();
Chris Wren78403d72014-07-28 10:23:24 +0100648 final boolean wasExpanded = isExpanded();
Christoph Studera7fe6312014-06-27 19:32:44 +0200649 mExpandable = false;
650 mHasUserChangedExpansion = false;
651 mUserLocked = false;
652 mShowingPublic = false;
Jorim Jaggiae441282014-08-01 02:45:18 +0200653 mSensitive = false;
654 mShowingPublicInitialized = false;
Christoph Studera7fe6312014-06-27 19:32:44 +0200655 mIsSystemExpanded = false;
Selim Cinek83bc7832015-10-22 13:26:54 -0700656 mOnKeyguard = false;
Selim Cinek51d94912016-03-02 15:34:28 -0800657 mPublicLayout.reset();
658 mPrivateLayout.reset();
Selim Cinek31094df2014-08-14 19:28:15 +0200659 resetHeight();
Mady Mellor4b80b102016-01-22 08:03:58 -0800660 resetTranslation();
Selim Cinek31094df2014-08-14 19:28:15 +0200661 logExpansionEvent(false, wasExpanded);
662 }
663
664 public void resetHeight() {
Christoph Studera7fe6312014-06-27 19:32:44 +0200665 mMaxExpandHeight = 0;
Selim Cinek8d490d42015-04-10 00:05:50 -0700666 mHeadsUpHeight = 0;
Selim Cinek31094df2014-08-14 19:28:15 +0200667 onHeightReset();
Selim Cinek6e28a672014-09-05 14:43:28 +0200668 requestLayout();
Christoph Studera7fe6312014-06-27 19:32:44 +0200669 }
670
Jorim Jaggi251957d2014-04-09 04:24:09 +0200671 @Override
672 protected void onFinishInflate() {
673 super.onFinishInflate();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200674 mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800675 mPublicLayout.setContainingNotification(this);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200676 mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800677 mPrivateLayout.setExpandClickListener(mExpandClickListener);
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800678 mPrivateLayout.setContainingNotification(this);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800679 mPublicLayout.setExpandClickListener(mExpandClickListener);
Mady Mellor4b80b102016-01-22 08:03:58 -0800680 mSettingsIconRowStub = (ViewStub) findViewById(R.id.settings_icon_row_stub);
681 mSettingsIconRowStub.setOnInflateListener(new ViewStub.OnInflateListener() {
682 @Override
683 public void onInflate(ViewStub stub, View inflated) {
684 mSettingsIconRow = (NotificationSettingsIconRow) inflated;
685 mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
686 }
687 });
Selim Cinekab29aeb2015-02-20 18:18:32 +0100688 mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
689 mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200690 @Override
691 public void onInflate(ViewStub stub, View inflated) {
692 mGuts = (NotificationGuts) inflated;
693 mGuts.setClipTopAmount(getClipTopAmount());
694 mGuts.setActualHeight(getActualHeight());
Selim Cinekab29aeb2015-02-20 18:18:32 +0100695 mGutsStub = null;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200696 }
697 });
Selim Cinekb5605e52015-02-20 18:21:41 +0100698 mChildrenContainerStub = (ViewStub) findViewById(R.id.child_container_stub);
699 mChildrenContainerStub.setOnInflateListener(new ViewStub.OnInflateListener() {
700
701 @Override
702 public void onInflate(ViewStub stub, View inflated) {
703 mChildrenContainer = (NotificationChildrenContainer) inflated;
Selim Cinek388df6d2015-10-22 13:25:11 -0700704 mChildrenContainer.setNotificationParent(ExpandableNotificationRow.this);
Selim Cinekc897bd32016-03-18 17:32:31 -0700705 mChildrenContainer.onNotificationUpdated();
Mady Mellor4b80b102016-01-22 08:03:58 -0800706 mTranslateableViews.add(mChildrenContainer);
Selim Cinekb5605e52015-02-20 18:21:41 +0100707 }
708 });
Selim Cinek863834b2014-05-20 04:20:25 +0200709 mVetoButton = findViewById(R.id.veto);
Mady Mellor4b80b102016-01-22 08:03:58 -0800710
711 // Add the views that we translate to reveal the gear
712 mTranslateableViews = new ArrayList<View>();
713 for (int i = 0; i < getChildCount(); i++) {
714 mTranslateableViews.add(getChildAt(i));
715 }
716 // Remove views that don't translate
717 mTranslateableViews.remove(mVetoButton);
718 mTranslateableViews.remove(mSettingsIconRowStub);
719 mTranslateableViews.remove(mChildrenContainerStub);
720 mTranslateableViews.remove(mGutsStub);
721 }
722
Mady Mellor34958fa2016-02-23 09:52:17 -0800723 private void setTranslationForOutline(float translationX) {
Mady Mellor4b80b102016-01-22 08:03:58 -0800724 setOutlineRect(false, translationX, getTop(), getRight() + translationX, getBottom());
725 }
726
727 public void resetTranslation() {
728 if (mTranslateableViews != null) {
729 for (int i = 0; i < mTranslateableViews.size(); i++) {
730 mTranslateableViews.get(i).setTranslationX(0);
731 }
732 setTranslationForOutline(0);
733 }
734 if (mSettingsIconRow != null) {
735 mSettingsIconRow.resetState();
736 }
737 }
738
739 public void animateTranslateNotification(final float leftTarget) {
740 if (mTranslateAnim != null) {
741 mTranslateAnim.cancel();
742 }
Mady Mellor34958fa2016-02-23 09:52:17 -0800743 mTranslateAnim = (AnimatorSet) getTranslateViewAnimator(leftTarget,
744 null /* updateListener */);
745 if (mTranslateAnim != null) {
746 mTranslateAnim.start();
747 }
748 }
749
750 @Override
751 public void setTranslation(float translationX) {
752 if (areGutsExposed()) {
753 // Don't translate if guts are showing.
754 return;
755 }
756 // Translate the group of views
757 for (int i = 0; i < mTranslateableViews.size(); i++) {
758 if (mTranslateableViews.get(i) != null) {
759 mTranslateableViews.get(i).setTranslationX(translationX);
760 }
761 }
762 setTranslationForOutline(translationX);
763 if (mSettingsIconRow != null) {
764 mSettingsIconRow.updateSettingsIcons(translationX, getMeasuredWidth());
765 }
766 }
767
768 @Override
769 public float getTranslation() {
770 if (mTranslateableViews != null && mTranslateableViews.size() > 0) {
771 // All of the views in the list should have same translation, just use first one.
772 return mTranslateableViews.get(0).getTranslationX();
773 }
774 return 0;
775 }
776
777 public Animator getTranslateViewAnimator(final float leftTarget,
778 AnimatorUpdateListener listener) {
Mady Mellor723f1f92016-03-13 15:54:06 -0700779 if (mTranslateAnim != null) {
780 mTranslateAnim.cancel();
781 }
Mady Mellor34958fa2016-02-23 09:52:17 -0800782 if (areGutsExposed()) {
783 // No translation if guts are exposed.
784 return null;
785 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800786 AnimatorSet set = new AnimatorSet();
787 if (mTranslateableViews != null) {
788 for (int i = 0; i < mTranslateableViews.size(); i++) {
789 final View animView = mTranslateableViews.get(i);
790 final ObjectAnimator translateAnim = ObjectAnimator.ofFloat(
791 animView, "translationX", leftTarget);
792 if (i == 0) {
793 translateAnim.addUpdateListener(new AnimatorUpdateListener() {
794 @Override
795 public void onAnimationUpdate(ValueAnimator animation) {
796 setTranslationForOutline((float) animation.getAnimatedValue());
Mady Mellor34958fa2016-02-23 09:52:17 -0800797 if (mSettingsIconRow != null) {
798 mSettingsIconRow.updateSettingsIcons(
799 (float) animation.getAnimatedValue(), getMeasuredWidth());
800 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800801 }
802 });
Mady Mellor34958fa2016-02-23 09:52:17 -0800803 if (listener != null) {
804 translateAnim.addUpdateListener(listener);
805 }
Mady Mellor723f1f92016-03-13 15:54:06 -0700806 translateAnim.addListener(new AnimatorListenerAdapter() {
807 boolean cancelled = false;
808
809 @Override
810 public void onAnimationCancel(Animator anim) {
811 cancelled = true;
Mady Mellor4b80b102016-01-22 08:03:58 -0800812 }
Mady Mellor723f1f92016-03-13 15:54:06 -0700813
814 @Override
815 public void onAnimationEnd(Animator anim) {
816 if (!cancelled && mSettingsIconRow != null && leftTarget == 0) {
817 mSettingsIconRow.resetState();
818 mTranslateAnim = null;
819 }
820 }
821 });
822 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800823 set.play(translateAnim);
824 }
825 }
Mady Mellor723f1f92016-03-13 15:54:06 -0700826 mTranslateAnim = set;
Mady Mellor34958fa2016-02-23 09:52:17 -0800827 return set;
Mady Mellor4b80b102016-01-22 08:03:58 -0800828 }
829
830 public float getSpaceForGear() {
831 if (mSettingsIconRow != null) {
832 return mSettingsIconRow.getSpaceForGear();
833 }
834 return 0;
835 }
836
837 public NotificationSettingsIconRow getSettingsRow() {
838 if (mSettingsIconRow == null) {
839 mSettingsIconRowStub.inflate();
840 }
841 return mSettingsIconRow;
842 }
843
Selim Cinekab29aeb2015-02-20 18:18:32 +0100844 public void inflateGuts() {
845 if (mGuts == null) {
846 mGutsStub.inflate();
847 }
848 }
849
Selim Cinekda42d652015-12-04 15:51:16 -0800850 private void updateChildrenVisibility() {
Selim Cinekd84a5932015-12-15 11:45:36 -0800851 mPrivateLayout.setVisibility(!mShowingPublic && !mIsSummaryWithChildren ? VISIBLE
852 : INVISIBLE);
Selim Cinekef5127e2015-12-21 16:55:58 -0800853 if (mChildrenContainer != null) {
854 mChildrenContainer.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
855 : INVISIBLE);
Selim Cinekb5605e52015-02-20 18:21:41 +0100856 }
Selim Cinekef5127e2015-12-21 16:55:58 -0800857 if (mNotificationHeader != null) {
858 mNotificationHeader.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
859 : INVISIBLE);
860 }
Selim Cinekda42d652015-12-04 15:51:16 -0800861 // The limits might have changed if the view suddenly became a group or vice versa
862 updateLimits();
Selim Cinekb5605e52015-02-20 18:21:41 +0100863 }
864
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200865 @Override
Alan Viverettea54956a2015-01-07 16:05:02 -0800866 public boolean onRequestSendAccessibilityEventInternal(View child, AccessibilityEvent event) {
867 if (super.onRequestSendAccessibilityEventInternal(child, event)) {
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200868 // Add a record for the entire layout since its content is somehow small.
869 // The event comes from a leaf view that is interacted with.
870 AccessibilityEvent record = AccessibilityEvent.obtain();
871 onInitializeAccessibilityEvent(record);
872 dispatchPopulateAccessibilityEvent(record);
873 event.appendRecord(record);
874 return true;
875 }
876 return false;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200877 }
Chris Wren51c75102013-07-16 20:49:17 -0400878
John Spurlocke15452b2014-08-21 09:44:39 -0400879 @Override
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100880 public void setDark(boolean dark, boolean fade, long delay) {
881 super.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400882 final NotificationContentView showing = getShowingLayout();
883 if (showing != null) {
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100884 showing.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400885 }
Selim Cinek9c7712d2015-12-08 19:19:48 -0800886 if (mIsSummaryWithChildren) {
Selim Cinekc897bd32016-03-18 17:32:31 -0700887 mChildrenContainer.setDark(dark, fade, delay);
Selim Cinek9c7712d2015-12-08 19:19:48 -0800888 mNotificationHeaderWrapper.setDark(dark, fade, delay);
889 }
John Spurlocke15452b2014-08-21 09:44:39 -0400890 }
891
Chris Wren51c75102013-07-16 20:49:17 -0400892 public boolean isExpandable() {
Selim Cinek388df6d2015-10-22 13:25:11 -0700893 if (mIsSummaryWithChildren && !mShowingPublic) {
894 return !mChildrenExpanded;
895 }
Chris Wren51c75102013-07-16 20:49:17 -0400896 return mExpandable;
897 }
898
899 public void setExpandable(boolean expandable) {
900 mExpandable = expandable;
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800901 mPrivateLayout.updateExpandButtons(isExpandable());
Chris Wren51c75102013-07-16 20:49:17 -0400902 }
903
Selim Cinek4ffd6362015-12-29 15:12:23 +0100904 @Override
905 public void setClipToActualHeight(boolean clipToActualHeight) {
Selim Cinek084c16b2016-01-22 17:48:22 -0800906 super.setClipToActualHeight(clipToActualHeight || isUserLocked());
907 getShowingLayout().setClipToActualHeight(clipToActualHeight || isUserLocked());
Selim Cinek4ffd6362015-12-29 15:12:23 +0100908 }
909
Selim Cinek1685e632014-04-08 02:27:49 +0200910 /**
911 * @return whether the user has changed the expansion state
912 */
913 public boolean hasUserChangedExpansion() {
914 return mHasUserChangedExpansion;
915 }
916
Chris Wren51c75102013-07-16 20:49:17 -0400917 public boolean isUserExpanded() {
918 return mUserExpanded;
919 }
920
Selim Cinek1685e632014-04-08 02:27:49 +0200921 /**
922 * Set this notification to be expanded by the user
923 *
924 * @param userExpanded whether the user wants this notification to be expanded
925 */
Chris Wren51c75102013-07-16 20:49:17 -0400926 public void setUserExpanded(boolean userExpanded) {
Selim Cinek388df6d2015-10-22 13:25:11 -0700927 setUserExpanded(userExpanded, false /* allowChildExpansion */);
928 }
929
930 /**
931 * Set this notification to be expanded by the user
932 *
933 * @param userExpanded whether the user wants this notification to be expanded
934 * @param allowChildExpansion whether a call to this method allows expanding children
935 */
936 public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700937 mFalsingManager.setNotificationExpanded();
Selim Cinek388df6d2015-10-22 13:25:11 -0700938 if (mIsSummaryWithChildren && !mShowingPublic && allowChildExpansion) {
939 mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
940 return;
941 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200942 if (userExpanded && !mExpandable) return;
Chris Wren78403d72014-07-28 10:23:24 +0100943 final boolean wasExpanded = isExpanded();
Selim Cinek1685e632014-04-08 02:27:49 +0200944 mHasUserChangedExpansion = true;
Chris Wren51c75102013-07-16 20:49:17 -0400945 mUserExpanded = userExpanded;
Chris Wren78403d72014-07-28 10:23:24 +0100946 logExpansionEvent(true, wasExpanded);
Chris Wren51c75102013-07-16 20:49:17 -0400947 }
948
Selim Cinekccd14fb2014-08-12 18:53:24 +0200949 public void resetUserExpansion() {
950 mHasUserChangedExpansion = false;
951 mUserExpanded = false;
952 }
953
Chris Wren51c75102013-07-16 20:49:17 -0400954 public boolean isUserLocked() {
955 return mUserLocked;
956 }
957
958 public void setUserLocked(boolean userLocked) {
959 mUserLocked = userLocked;
Selim Cinek8f2f6a62016-02-23 19:56:31 -0800960 mPrivateLayout.setUserExpanding(userLocked);
Selim Cinek42357e02016-02-24 18:48:01 -0800961 if (mIsSummaryWithChildren) {
962 mChildrenContainer.setUserLocked(userLocked);
963 }
Chris Wren51c75102013-07-16 20:49:17 -0400964 }
965
Selim Cinek1685e632014-04-08 02:27:49 +0200966 /**
967 * @return has the system set this notification to be expanded
968 */
969 public boolean isSystemExpanded() {
970 return mIsSystemExpanded;
971 }
972
973 /**
974 * Set this notification to be expanded by the system.
975 *
976 * @param expand whether the system wants this notification to be expanded.
977 */
978 public void setSystemExpanded(boolean expand) {
Selim Cinek31094df2014-08-14 19:28:15 +0200979 if (expand != mIsSystemExpanded) {
980 final boolean wasExpanded = isExpanded();
981 mIsSystemExpanded = expand;
Selim Cinekb5605e52015-02-20 18:21:41 +0100982 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200983 logExpansionEvent(false, wasExpanded);
Selim Cinekc897bd32016-03-18 17:32:31 -0700984 if (mChildrenContainer != null) {
985 mChildrenContainer.updateGroupOverflow();
986 }
Selim Cinek31094df2014-08-14 19:28:15 +0200987 }
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200988 }
989
990 /**
Selim Cinek83bc7832015-10-22 13:26:54 -0700991 * @param onKeyguard whether to prevent notification expansion
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200992 */
Selim Cinek83bc7832015-10-22 13:26:54 -0700993 public void setOnKeyguard(boolean onKeyguard) {
994 if (onKeyguard != mOnKeyguard) {
Selim Cinek31094df2014-08-14 19:28:15 +0200995 final boolean wasExpanded = isExpanded();
Selim Cinek83bc7832015-10-22 13:26:54 -0700996 mOnKeyguard = onKeyguard;
Selim Cinek31094df2014-08-14 19:28:15 +0200997 logExpansionEvent(false, wasExpanded);
998 if (wasExpanded != isExpanded()) {
Selim Cinekc897bd32016-03-18 17:32:31 -0700999 if (mIsSummaryWithChildren) {
1000 mChildrenContainer.updateGroupOverflow();
1001 }
Mady Mellor4b80b102016-01-22 08:03:58 -08001002 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +02001003 }
1004 }
Selim Cinek1685e632014-04-08 02:27:49 +02001005 }
1006
1007 /**
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001008 * @return Can the underlying notification be cleared?
1009 */
1010 public boolean isClearable() {
Selim Cineka37774f2014-11-11 19:16:18 +01001011 return mStatusBarNotification != null && mStatusBarNotification.isClearable();
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001012 }
1013
Jorim Jaggi9cbadd32014-05-01 20:18:31 +02001014 @Override
1015 public int getIntrinsicHeight() {
Jorim Jaggibe565df2014-04-28 17:51:23 +02001016 if (isUserLocked()) {
1017 return getActualHeight();
1018 }
Selim Cinekd84a5932015-12-15 11:45:36 -08001019 if (mGuts != null && mGuts.areGutsExposed()) {
1020 return mGuts.getHeight();
1021 } else if ((isChildInGroup() && !isGroupExpanded())) {
1022 return mPrivateLayout.getMinHeight();
1023 } else if (mSensitive && mHideSensitiveForIntrinsicHeight) {
1024 return getMinHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -07001025 } else if (mIsSummaryWithChildren && !mOnKeyguard) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001026 return mChildrenContainer.getIntrinsicHeight();
Selim Cinek60122be2015-04-15 18:16:50 -07001027 } else if (mIsHeadsUp) {
Selim Cinek31aada42015-12-18 17:51:15 -08001028 if (isPinned()) {
1029 return getPinnedHeadsUpHeight(true /* atLeastMinHeight */);
1030 } else if (isExpanded()) {
Selim Cinekd84a5932015-12-15 11:45:36 -08001031 return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -07001032 } else {
Selim Cinekd84a5932015-12-15 11:45:36 -08001033 return Math.max(getMinHeight(), mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -07001034 }
Selim Cinek31aada42015-12-18 17:51:15 -08001035 } else if (isExpanded()) {
Selim Cinek83bc7832015-10-22 13:26:54 -07001036 return getMaxExpandHeight();
Selim Cinekd84a5932015-12-15 11:45:36 -08001037 } else {
1038 return getMinHeight();
Selim Cinek1685e632014-04-08 02:27:49 +02001039 }
Selim Cinekb5605e52015-02-20 18:21:41 +01001040 }
Selim Cinek1685e632014-04-08 02:27:49 +02001041
Selim Cinekeef84282015-10-30 16:28:00 -07001042 private boolean isGroupExpanded() {
1043 return mGroupManager.isGroupExpanded(mStatusBarNotification);
Selim Cinekb5605e52015-02-20 18:21:41 +01001044 }
1045
Selim Cinekeef84282015-10-30 16:28:00 -07001046 /**
1047 * @return whether this view has a header on the top of the content
1048 */
1049 private boolean hasNotificationHeader() {
1050 return mIsSummaryWithChildren;
Selim Cinek1685e632014-04-08 02:27:49 +02001051 }
1052
Selim Cinek263398f2015-10-21 17:40:23 -07001053 private void onChildrenCountChanged() {
Selim Cinek8fc93c92015-11-23 17:48:07 -08001054 mIsSummaryWithChildren = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS
Selim Cinek2a739342016-03-17 10:28:55 -07001055 && mChildrenContainer != null && mChildrenContainer.getChildCount() > 0;
Selim Cinek8fc93c92015-11-23 17:48:07 -08001056 if (mIsSummaryWithChildren) {
Selim Cinek8fc93c92015-11-23 17:48:07 -08001057 if (mNotificationHeader == null) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001058 recreateNotificationHeader();
1059 }
Selim Cinek263398f2015-10-21 17:40:23 -07001060 }
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001061 mPrivateLayout.updateExpandButtons(isExpandable());
Selim Cinekea4bef72015-12-02 15:51:10 -08001062 updateChildrenHeaderAppearance();
Selim Cinekda42d652015-12-04 15:51:16 -08001063 updateChildrenVisibility();
Selim Cinek263398f2015-10-21 17:40:23 -07001064 }
1065
Selim Cinek1685e632014-04-08 02:27:49 +02001066 /**
1067 * Check whether the view state is currently expanded. This is given by the system in {@link
1068 * #setSystemExpanded(boolean)} and can be overridden by user expansion or
1069 * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
1070 * view can differ from this state, if layout params are modified from outside.
1071 *
1072 * @return whether the view state is currently expanded.
1073 */
Selim Cinek83bc7832015-10-22 13:26:54 -07001074 public boolean isExpanded() {
Selim Cineke81b82b2016-03-04 11:22:28 -08001075 return isExpanded(false /* allowOnKeyguard */);
1076 }
1077
1078 public boolean isExpanded(boolean allowOnKeyguard) {
1079 return (!mOnKeyguard || allowOnKeyguard)
Selim Cinekb5605e52015-02-20 18:21:41 +01001080 && (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded())
1081 || isUserExpanded());
1082 }
1083
1084 private boolean isSystemChildExpanded() {
1085 return mIsSystemChildExpanded;
1086 }
1087
1088 public void setSystemChildExpanded(boolean expanded) {
1089 mIsSystemChildExpanded = expanded;
Selim Cinek1685e632014-04-08 02:27:49 +02001090 }
1091
1092 @Override
1093 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
1094 super.onLayout(changed, left, top, right, bottom);
Selim Cinek8d490d42015-04-10 00:05:50 -07001095 updateMaxHeights();
Selim Cinek1685e632014-04-08 02:27:49 +02001096 }
1097
Selim Cinek8d490d42015-04-10 00:05:50 -07001098 private void updateMaxHeights() {
Selim Cinekd2319fb2014-09-01 19:41:54 +02001099 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek8d490d42015-04-10 00:05:50 -07001100 View expandedChild = mPrivateLayout.getExpandedChild();
1101 if (expandedChild == null) {
1102 expandedChild = mPrivateLayout.getContractedChild();
1103 }
1104 mMaxExpandHeight = expandedChild.getHeight();
1105 View headsUpChild = mPrivateLayout.getHeadsUpChild();
Selim Cinek1f3f5442015-04-10 17:54:46 -07001106 if (headsUpChild == null) {
1107 headsUpChild = mPrivateLayout.getContractedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -07001108 }
Selim Cinek1f3f5442015-04-10 17:54:46 -07001109 mHeadsUpHeight = headsUpChild.getHeight();
Selim Cinekd2319fb2014-09-01 19:41:54 +02001110 if (intrinsicBefore != getIntrinsicHeight()) {
Selim Cinekb5605e52015-02-20 18:21:41 +01001111 notifyHeightChanged(false /* needsAnimation */);
Selim Cinekd2319fb2014-09-01 19:41:54 +02001112 }
1113 }
1114
Selim Cinekfa0a2d32016-01-14 13:02:21 -08001115 @Override
1116 public void notifyHeightChanged(boolean needsAnimation) {
1117 super.notifyHeightChanged(needsAnimation);
1118 getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked());
1119 }
1120
Selim Cinek3c76d502016-02-19 15:16:33 -08001121 public void setSensitive(boolean sensitive, boolean hideSensitive) {
Jorim Jaggiae441282014-08-01 02:45:18 +02001122 mSensitive = sensitive;
Selim Cinek3c76d502016-02-19 15:16:33 -08001123 mSensitiveHiddenInGeneral = hideSensitive;
Jorim Jaggiae441282014-08-01 02:45:18 +02001124 }
1125
1126 public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
Selim Cinek60122be2015-04-15 18:16:50 -07001127 mHideSensitiveForIntrinsicHeight = hideSensitive;
Selim Cineka52f6a12016-02-29 15:35:58 -08001128 if (mIsSummaryWithChildren) {
1129 List<ExpandableNotificationRow> notificationChildren =
1130 mChildrenContainer.getNotificationChildren();
1131 for (int i = 0; i < notificationChildren.size(); i++) {
1132 ExpandableNotificationRow child = notificationChildren.get(i);
1133 child.setHideSensitiveForIntrinsicHeight(hideSensitive);
1134 }
1135 }
Jorim Jaggiae441282014-08-01 02:45:18 +02001136 }
1137
1138 public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
1139 long duration) {
1140 boolean oldShowingPublic = mShowingPublic;
1141 mShowingPublic = mSensitive && hideSensitive;
1142 if (mShowingPublicInitialized && mShowingPublic == oldShowingPublic) {
1143 return;
1144 }
Dan Sandlera5e0f412014-01-23 15:11:54 -05001145
1146 // bail out if no public version
Selim Cinek1685e632014-04-08 02:27:49 +02001147 if (mPublicLayout.getChildCount() == 0) return;
Dan Sandlera5e0f412014-01-23 15:11:54 -05001148
Jorim Jaggiae441282014-08-01 02:45:18 +02001149 if (!animated) {
1150 mPublicLayout.animate().cancel();
1151 mPrivateLayout.animate().cancel();
1152 mPublicLayout.setAlpha(1f);
1153 mPrivateLayout.setAlpha(1f);
1154 mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
Selim Cinekd84a5932015-12-15 11:45:36 -08001155 updateChildrenVisibility();
Jorim Jaggiae441282014-08-01 02:45:18 +02001156 } else {
1157 animateShowingPublic(delay, duration);
1158 }
Selim Cinekc3179332016-03-04 14:44:56 -08001159 NotificationContentView showingLayout = getShowingLayout();
1160 showingLayout.updateBackgroundColor(animated);
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001161 mPrivateLayout.updateExpandButtons(isExpandable());
Selim Cinek757d8792016-01-28 16:21:08 -08001162 updateClearability();
Jorim Jaggiae441282014-08-01 02:45:18 +02001163 mShowingPublicInitialized = true;
1164 }
1165
1166 private void animateShowingPublic(long delay, long duration) {
Selim Cinekd84a5932015-12-15 11:45:36 -08001167 View[] privateViews = mIsSummaryWithChildren ?
1168 new View[] {mChildrenContainer, mNotificationHeader}
1169 : new View[] {mPrivateLayout};
1170 View[] publicViews = new View[] {mPublicLayout};
1171 View[] hiddenChildren = mShowingPublic ? privateViews : publicViews;
1172 View[] shownChildren = mShowingPublic ? publicViews : privateViews;
1173 for (final View hiddenView : hiddenChildren) {
1174 hiddenView.setVisibility(View.VISIBLE);
1175 hiddenView.animate().cancel();
1176 hiddenView.animate()
1177 .alpha(0f)
1178 .setStartDelay(delay)
1179 .setDuration(duration)
1180 .withEndAction(new Runnable() {
1181 @Override
1182 public void run() {
1183 hiddenView.setVisibility(View.INVISIBLE);
1184 }
1185 });
1186 }
1187 for (View showView : shownChildren) {
1188 showView.setVisibility(View.VISIBLE);
1189 showView.setAlpha(0f);
1190 showView.animate().cancel();
1191 showView.animate()
1192 .alpha(1f)
1193 .setStartDelay(delay)
1194 .setDuration(duration);
1195 }
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001196 }
1197
Selim Cinek3776fe02016-02-04 13:32:43 -08001198 public boolean mustStayOnScreen() {
1199 return mIsHeadsUp;
1200 }
1201
Selim Cinek757d8792016-01-28 16:21:08 -08001202 private void updateClearability() {
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001203 // public versions cannot be dismissed
Selim Cinek3c76d502016-02-19 15:16:33 -08001204 mVetoButton.setVisibility(isClearable() && (!mShowingPublic
1205 || !mSensitiveHiddenInGeneral) ? View.VISIBLE : View.GONE);
Dan Sandlera5e0f412014-01-23 15:11:54 -05001206 }
Jorim Jaggi251957d2014-04-09 04:24:09 +02001207
Selim Cinekb5605e52015-02-20 18:21:41 +01001208 public void setChildrenExpanded(boolean expanded, boolean animate) {
1209 mChildrenExpanded = expanded;
Selim Cinek7b836392015-12-04 20:02:59 -08001210 if (mNotificationHeader != null) {
1211 mNotificationHeader.setExpanded(expanded);
1212 }
Selim Cinek83bc7832015-10-22 13:26:54 -07001213 if (mChildrenContainer != null) {
1214 mChildrenContainer.setChildrenExpanded(expanded);
1215 }
Selim Cinekb5605e52015-02-20 18:21:41 +01001216 }
1217
Selim Cinekb5605e52015-02-20 18:21:41 +01001218 public static void applyTint(View v, int color) {
1219 int alpha;
1220 if (color != 0) {
1221 alpha = COLORED_DIVIDER_ALPHA;
1222 } else {
1223 color = 0xff000000;
1224 alpha = DEFAULT_DIVIDER_ALPHA;
1225 }
1226 if (v.getBackground() instanceof ColorDrawable) {
1227 ColorDrawable background = (ColorDrawable) v.getBackground();
1228 background.mutate();
1229 background.setColor(color);
1230 background.setAlpha(alpha);
1231 }
1232 }
1233
Selim Cinek1685e632014-04-08 02:27:49 +02001234 public int getMaxExpandHeight() {
Selim Cinekb5605e52015-02-20 18:21:41 +01001235 return mMaxExpandHeight;
Chris Wren51c75102013-07-16 20:49:17 -04001236 }
Jorim Jaggi584a7aa2014-04-10 23:26:13 +02001237
Mady Mellor34958fa2016-02-23 09:52:17 -08001238 public boolean areGutsExposed() {
1239 return (mGuts != null && mGuts.areGutsExposed());
1240 }
1241
Jorim Jaggibe565df2014-04-28 17:51:23 +02001242 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001243 public boolean isContentExpandable() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001244 NotificationContentView showingLayout = getShowingLayout();
1245 return showingLayout.isContentExpandable();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001246 }
1247
1248 @Override
Selim Cinek560e64d2015-06-09 19:58:11 -07001249 protected View getContentView() {
1250 return getShowingLayout();
1251 }
1252
1253 @Override
Jorim Jaggid552d9d2014-05-07 19:41:13 +02001254 public void setActualHeight(int height, boolean notifyListeners) {
Selim Cinekb5605e52015-02-20 18:21:41 +01001255 super.setActualHeight(height, notifyListeners);
Mady Mellorb53bc272016-02-11 18:28:23 -08001256 if (mGuts != null && mGuts.areGutsExposed()) {
1257 mGuts.setActualHeight(height);
1258 return;
1259 }
Selim Cinekeef84282015-10-30 16:28:00 -07001260 int contentHeight = Math.max(getMinHeight(), height);
Selim Cinekb5605e52015-02-20 18:21:41 +01001261 mPrivateLayout.setContentHeight(contentHeight);
1262 mPublicLayout.setContentHeight(contentHeight);
Selim Cinek42357e02016-02-24 18:48:01 -08001263 if (mIsSummaryWithChildren) {
1264 mChildrenContainer.setActualHeight(height);
1265 }
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001266 if (mGuts != null) {
1267 mGuts.setActualHeight(height);
1268 }
Jorim Jaggibe565df2014-04-28 17:51:23 +02001269 }
1270
1271 @Override
Selim Cinekb5605e52015-02-20 18:21:41 +01001272 public int getMaxContentHeight() {
Selim Cinek83bc7832015-10-22 13:26:54 -07001273 if (mIsSummaryWithChildren && !mShowingPublic) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001274 return mChildrenContainer.getMaxContentHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -07001275 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001276 NotificationContentView showingLayout = getShowingLayout();
1277 return showingLayout.getMaxHeight();
Jorim Jaggibe565df2014-04-28 17:51:23 +02001278 }
1279
1280 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001281 public int getMinHeight() {
Selim Cinek31aada42015-12-18 17:51:15 -08001282 if (mIsHeadsUp && mHeadsUpManager.isTrackingHeadsUp()) {
1283 return getPinnedHeadsUpHeight(false /* atLeastMinHeight */);
1284 } else if (mIsSummaryWithChildren && !isGroupExpanded() && !mShowingPublic) {
Selim Cinekb55386d2015-12-16 17:26:49 -08001285 return mChildrenContainer.getMinHeight();
Selim Cinek31aada42015-12-18 17:51:15 -08001286 } else if (mIsHeadsUp) {
1287 return mHeadsUpHeight;
Selim Cinekb55386d2015-12-16 17:26:49 -08001288 }
Selim Cinek816c8e42015-11-19 12:00:45 -08001289 NotificationContentView showingLayout = getShowingLayout();
1290 return showingLayout.getMinHeight();
1291 }
1292
1293 @Override
1294 public int getMinExpandHeight() {
Selim Cinek2c584612016-02-29 16:14:25 -08001295 if (mIsSummaryWithChildren && !mShowingPublic) {
Selim Cinekf07d0622016-03-21 19:52:52 -07001296 return mChildrenContainer.getMinExpandHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -07001297 }
Selim Cinek816c8e42015-11-19 12:00:45 -08001298 return getMinHeight();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001299 }
1300
1301 @Override
Jorim Jaggibe565df2014-04-28 17:51:23 +02001302 public void setClipTopAmount(int clipTopAmount) {
1303 super.setClipTopAmount(clipTopAmount);
1304 mPrivateLayout.setClipTopAmount(clipTopAmount);
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001305 mPublicLayout.setClipTopAmount(clipTopAmount);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001306 if (mGuts != null) {
1307 mGuts.setClipTopAmount(clipTopAmount);
1308 }
Jorim Jaggibe565df2014-04-28 17:51:23 +02001309 }
1310
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001311 private void recreateNotificationHeader() {
1312 final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
1313 getStatusBarNotification().getNotification());
1314 final RemoteViews header = builder.makeNotificationHeader();
1315 if (mNotificationHeader == null) {
1316 mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
1317 final View expandButton = mNotificationHeader.findViewById(
1318 com.android.internal.R.id.expand_button);
1319 expandButton.setVisibility(VISIBLE);
1320 mNotificationHeader.setOnClickListener(mExpandClickListener);
Selim Cinek9c7712d2015-12-08 19:19:48 -08001321 mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
1322 mNotificationHeader);
Selim Cinekb5a83612015-12-11 14:14:39 -08001323 addView(mNotificationHeader, indexOfChild(mChildrenContainer) + 1);
Mady Mellor4b80b102016-01-22 08:03:58 -08001324 mTranslateableViews.add(mNotificationHeader);
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001325 } else {
1326 header.reapply(getContext(), mNotificationHeader);
Selim Cinek4ffd6362015-12-29 15:12:23 +01001327 mNotificationHeaderWrapper.notifyContentUpdated(mEntry.notification);
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001328 }
Selim Cinekea4bef72015-12-02 15:51:10 -08001329 updateChildrenHeaderAppearance();
Selim Cinek343e6e22014-04-11 21:23:30 +02001330 }
Selim Cinek7d447722014-06-10 15:51:59 +02001331
Selim Cinekea4bef72015-12-02 15:51:10 -08001332 public void updateChildrenHeaderAppearance() {
1333 if (mIsSummaryWithChildren) {
1334 mHeaderUtil.updateChildrenHeaderAppearance();
1335 }
1336 }
1337
Selim Cinek31094df2014-08-14 19:28:15 +02001338 public boolean isMaxExpandHeightInitialized() {
1339 return mMaxExpandHeight != 0;
Selim Cinek7d447722014-06-10 15:51:59 +02001340 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001341
Selim Cinek42357e02016-02-24 18:48:01 -08001342 public NotificationContentView getShowingLayout() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001343 return mShowingPublic ? mPublicLayout : mPrivateLayout;
1344 }
Chris Wren78403d72014-07-28 10:23:24 +01001345
Jorim Jaggi59ec3042015-06-05 15:18:43 -07001346 @Override
1347 public void setShowingLegacyBackground(boolean showing) {
1348 super.setShowingLegacyBackground(showing);
1349 mPrivateLayout.setShowingLegacyBackground(showing);
1350 mPublicLayout.setShowingLegacyBackground(showing);
1351 }
1352
Selim Cineka6c6bfb2015-10-29 16:27:08 -07001353 @Override
1354 protected void updateBackgroundTint() {
1355 super.updateBackgroundTint();
1356 updateNoBackgroundState();
1357 if (mIsSummaryWithChildren) {
1358 List<ExpandableNotificationRow> notificationChildren =
1359 mChildrenContainer.getNotificationChildren();
1360 for (int i = 0; i < notificationChildren.size(); i++) {
1361 ExpandableNotificationRow child = notificationChildren.get(i);
1362 child.updateNoBackgroundState();
1363 }
1364 }
1365 }
1366
1367 private void updateNoBackgroundState() {
1368 mShowNoBackground = isChildInGroup() && hasSameBgColor(mNotificationParent);
1369 updateBackground();
1370 }
1371
Chris Wren78403d72014-07-28 10:23:24 +01001372 public void setExpansionLogger(ExpansionLogger logger, String key) {
1373 mLogger = logger;
1374 mLoggingKey = key;
1375 }
1376
Selim Cinek6183d122016-01-14 18:48:41 -08001377 @Override
Selim Cinek42357e02016-02-24 18:48:01 -08001378 public float getIncreasedPaddingAmount() {
1379 if (mIsSummaryWithChildren) {
1380 if (isGroupExpanded()) {
1381 return 1.0f;
1382 } else if (isUserLocked()) {
Selim Cinekf07d0622016-03-21 19:52:52 -07001383 return mChildrenContainer.getGroupExpandFraction();
Selim Cinek42357e02016-02-24 18:48:01 -08001384 }
1385 }
1386 return 0.0f;
Selim Cinek61633a82016-01-25 15:54:10 -08001387 }
1388
1389 @Override
Selim Cinek6183d122016-01-14 18:48:41 -08001390 protected boolean disallowSingleClick(MotionEvent event) {
1391 float x = event.getX();
1392 float y = event.getY();
Selim Cinek34eda5e2016-02-18 17:10:43 -08001393 NotificationHeaderView header = getVisibleNotificationHeader();
Selim Cinek6183d122016-01-14 18:48:41 -08001394 if (header != null) {
Mady Mellora8833512016-03-09 09:50:18 -08001395 return header.isInTouchRect(x - getTranslation(), y);
Selim Cinek6183d122016-01-14 18:48:41 -08001396 }
1397 return super.disallowSingleClick(event);
1398 }
1399
Chris Wren78403d72014-07-28 10:23:24 +01001400 private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
1401 final boolean nowExpanded = isExpanded();
1402 if (wasExpanded != nowExpanded && mLogger != null) {
1403 mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
1404 }
1405 }
Selim Cinek570981d2015-12-01 11:37:01 -08001406
1407 public interface OnExpandClickListener {
Selim Cinek31aada42015-12-18 17:51:15 -08001408 void onExpandClicked(NotificationData.Entry clickedEntry, boolean nowExpanded);
Selim Cinek570981d2015-12-01 11:37:01 -08001409 }
Chris Wren51c75102013-07-16 20:49:17 -04001410}