blob: de292d66fc5dad8c19a3ac6fe4ad45810798c086 [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 Cinek0ffbda62016-01-01 20:29:12 +010046import com.android.systemui.statusbar.notification.NotificationViewWrapper;
Selim Cinekb5605e52015-02-20 18:21:41 +010047import com.android.systemui.statusbar.phone.NotificationGroupManager;
Selim Cinek31aada42015-12-18 17:51:15 -080048import com.android.systemui.statusbar.policy.HeadsUpManager;
Selim Cinekb5605e52015-02-20 18:21:41 +010049import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
50import com.android.systemui.statusbar.stack.StackScrollState;
51import com.android.systemui.statusbar.stack.StackStateAnimator;
52import com.android.systemui.statusbar.stack.StackViewState;
53
Mady Mellor4b80b102016-01-22 08:03:58 -080054import java.util.ArrayList;
Selim Cinekb5605e52015-02-20 18:21:41 +010055import java.util.List;
Dan Sandlera5e0f412014-01-23 15:11:54 -050056
Jorim Jaggi4222d9a2014-04-23 16:13:15 +020057public class ExpandableNotificationRow extends ActivatableNotificationView {
Selim Cinekb5605e52015-02-20 18:21:41 +010058
59 private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
60 private static final int COLORED_DIVIDER_ALPHA = 0x7B;
Selim Cinek01af3342016-02-09 19:25:31 -080061 private int mNotificationMinHeightLegacy;
62 private int mMaxHeadsUpHeightLegacy;
63 private int mMaxHeadsUpHeight;
64 private int mNotificationMinHeight;
65 private int mNotificationMaxHeight;
Chris Wren51c75102013-07-16 20:49:17 -040066
Selim Cinek1685e632014-04-08 02:27:49 +020067 /** Does this row contain layouts that can adapt to row expansion */
Chris Wren51c75102013-07-16 20:49:17 -040068 private boolean mExpandable;
Selim Cinek1685e632014-04-08 02:27:49 +020069 /** Has the user actively changed the expansion state of this row */
70 private boolean mHasUserChangedExpansion;
71 /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */
Chris Wren51c75102013-07-16 20:49:17 -040072 private boolean mUserExpanded;
Selim Cinek31aada42015-12-18 17:51:15 -080073
74 /**
75 * Has this notification been expanded while it was pinned
76 */
77 private boolean mExpandedWhenPinned;
Selim Cinek1685e632014-04-08 02:27:49 +020078 /** Is the user touching this row */
Chris Wren51c75102013-07-16 20:49:17 -040079 private boolean mUserLocked;
Selim Cinek1685e632014-04-08 02:27:49 +020080 /** Are we showing the "public" version */
Dan Sandlera5e0f412014-01-23 15:11:54 -050081 private boolean mShowingPublic;
Jorim Jaggiae441282014-08-01 02:45:18 +020082 private boolean mSensitive;
Selim Cinek3c76d502016-02-19 15:16:33 -080083 private boolean mSensitiveHiddenInGeneral;
Jorim Jaggiae441282014-08-01 02:45:18 +020084 private boolean mShowingPublicInitialized;
Selim Cinek60122be2015-04-15 18:16:50 -070085 private boolean mHideSensitiveForIntrinsicHeight;
Chris Wren51c75102013-07-16 20:49:17 -040086
Selim Cinek1685e632014-04-08 02:27:49 +020087 /**
88 * Is this notification expanded by the system. The expansion state can be overridden by the
89 * user expansion.
90 */
91 private boolean mIsSystemExpanded;
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020092
93 /**
Selim Cinek83bc7832015-10-22 13:26:54 -070094 * Whether the notification is on the keyguard and the expansion is disabled.
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020095 */
Selim Cinek83bc7832015-10-22 13:26:54 -070096 private boolean mOnKeyguard;
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020097
Mady Mellor4b80b102016-01-22 08:03:58 -080098 private AnimatorSet mTranslateAnim;
99 private ArrayList<View> mTranslateableViews;
Jorim Jaggibe565df2014-04-28 17:51:23 +0200100 private NotificationContentView mPublicLayout;
101 private NotificationContentView mPrivateLayout;
Selim Cinek1685e632014-04-08 02:27:49 +0200102 private int mMaxExpandHeight;
Selim Cinek8d490d42015-04-10 00:05:50 -0700103 private int mHeadsUpHeight;
Selim Cinek863834b2014-05-20 04:20:25 +0200104 private View mVetoButton;
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400105 private boolean mClearable;
Chris Wren78403d72014-07-28 10:23:24 +0100106 private ExpansionLogger mLogger;
107 private String mLoggingKey;
Mady Mellor4b80b102016-01-22 08:03:58 -0800108 private NotificationSettingsIconRow mSettingsIconRow;
Selim Cinek8d490d42015-04-10 00:05:50 -0700109 private NotificationGuts mGuts;
Selim Cinekda42d652015-12-04 15:51:16 -0800110 private NotificationData.Entry mEntry;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200111 private StatusBarNotification mStatusBarNotification;
Selim Cinek1a521f32014-11-03 17:39:29 +0100112 private boolean mIsHeadsUp;
Selim Cinek98713a42015-09-21 15:47:20 +0200113 private boolean mLastChronometerRunning = true;
Selim Cinekeef84282015-10-30 16:28:00 -0700114 private NotificationHeaderView mNotificationHeader;
Selim Cinek9c7712d2015-12-08 19:19:48 -0800115 private NotificationViewWrapper mNotificationHeaderWrapper;
Selim Cinekb5605e52015-02-20 18:21:41 +0100116 private ViewStub mChildrenContainerStub;
117 private NotificationGroupManager mGroupManager;
Selim Cinekb5605e52015-02-20 18:21:41 +0100118 private boolean mChildrenExpanded;
Selim Cinek263398f2015-10-21 17:40:23 -0700119 private boolean mIsSummaryWithChildren;
Selim Cinekb5605e52015-02-20 18:21:41 +0100120 private NotificationChildrenContainer mChildrenContainer;
Mady Mellor4b80b102016-01-22 08:03:58 -0800121 private ViewStub mSettingsIconRowStub;
Selim Cinekab29aeb2015-02-20 18:18:32 +0100122 private ViewStub mGutsStub;
Selim Cinekb5605e52015-02-20 18:21:41 +0100123 private boolean mIsSystemChildExpanded;
Selim Cinek684a4422015-04-15 16:18:39 -0700124 private boolean mIsPinned;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700125 private FalsingManager mFalsingManager;
Selim Cinek31aada42015-12-18 17:51:15 -0800126 private HeadsUpManager mHeadsUpManager;
Selim Cinekea4bef72015-12-02 15:51:10 -0800127 private NotificationHeaderUtil mHeaderUtil = new NotificationHeaderUtil(this);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200128
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700129 private boolean mJustClicked;
Selim Cinek5a175d92015-11-23 18:01:33 -0800130 private boolean mIconAnimationRunning;
Selim Cinek34d93b02015-10-22 12:30:38 -0700131 private boolean mShowNoBackground;
Selim Cinek388df6d2015-10-22 13:25:11 -0700132 private ExpandableNotificationRow mNotificationParent;
Selim Cinek570981d2015-12-01 11:37:01 -0800133 private OnExpandClickListener mOnExpandClickListener;
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800134 private OnClickListener mExpandClickListener = new OnClickListener() {
135 @Override
136 public void onClick(View v) {
Selim Cinek624c02db2015-12-14 21:00:02 -0800137 if (!mShowingPublic && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800138 mGroupManager.toggleGroupExpansion(mStatusBarNotification);
Selim Cinek31aada42015-12-18 17:51:15 -0800139 mOnExpandClickListener.onExpandClicked(mEntry,
Selim Cinek570981d2015-12-01 11:37:01 -0800140 mGroupManager.isGroupExpanded(mStatusBarNotification));
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800141 } else {
Selim Cinek31aada42015-12-18 17:51:15 -0800142 boolean nowExpanded;
143 if (isPinned()) {
144 nowExpanded = !mExpandedWhenPinned;
145 mExpandedWhenPinned = nowExpanded;
146 } else {
147 nowExpanded = !isExpanded();
148 setUserExpanded(nowExpanded);
149 }
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800150 notifyHeightChanged(true);
Selim Cinek31aada42015-12-18 17:51:15 -0800151 mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800152 }
153 }
154 };
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700155
Selim Cinek8d490d42015-04-10 00:05:50 -0700156 public NotificationContentView getPrivateLayout() {
157 return mPrivateLayout;
158 }
159
160 public NotificationContentView getPublicLayout() {
161 return mPublicLayout;
162 }
163
Selim Cinekcab4a602014-09-03 14:47:57 +0200164 public void setIconAnimationRunning(boolean running) {
165 setIconAnimationRunning(running, mPublicLayout);
166 setIconAnimationRunning(running, mPrivateLayout);
Selim Cinek5a175d92015-11-23 18:01:33 -0800167 setIconAnimationRunningForChild(running, mNotificationHeader);
168 if (mIsSummaryWithChildren) {
169 List<ExpandableNotificationRow> notificationChildren =
170 mChildrenContainer.getNotificationChildren();
171 for (int i = 0; i < notificationChildren.size(); i++) {
172 ExpandableNotificationRow child = notificationChildren.get(i);
173 child.setIconAnimationRunning(running);
174 }
175 }
176 mIconAnimationRunning = running;
Selim Cinekcab4a602014-09-03 14:47:57 +0200177 }
178
179 private void setIconAnimationRunning(boolean running, NotificationContentView layout) {
180 if (layout != null) {
181 View contractedChild = layout.getContractedChild();
182 View expandedChild = layout.getExpandedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -0700183 View headsUpChild = layout.getHeadsUpChild();
Selim Cinekcab4a602014-09-03 14:47:57 +0200184 setIconAnimationRunningForChild(running, contractedChild);
185 setIconAnimationRunningForChild(running, expandedChild);
Selim Cinek8d490d42015-04-10 00:05:50 -0700186 setIconAnimationRunningForChild(running, headsUpChild);
Selim Cinekcab4a602014-09-03 14:47:57 +0200187 }
188 }
189
190 private void setIconAnimationRunningForChild(boolean running, View child) {
191 if (child != null) {
192 ImageView icon = (ImageView) child.findViewById(com.android.internal.R.id.icon);
193 setIconRunning(icon, running);
194 ImageView rightIcon = (ImageView) child.findViewById(
195 com.android.internal.R.id.right_icon);
196 setIconRunning(rightIcon, running);
197 }
198 }
199
200 private void setIconRunning(ImageView imageView, boolean running) {
201 if (imageView != null) {
202 Drawable drawable = imageView.getDrawable();
203 if (drawable instanceof AnimationDrawable) {
204 AnimationDrawable animationDrawable = (AnimationDrawable) drawable;
205 if (running) {
206 animationDrawable.start();
207 } else {
208 animationDrawable.stop();
209 }
210 } else if (drawable instanceof AnimatedVectorDrawable) {
211 AnimatedVectorDrawable animationDrawable = (AnimatedVectorDrawable) drawable;
212 if (running) {
213 animationDrawable.start();
214 } else {
215 animationDrawable.stop();
216 }
217 }
218 }
219 }
220
Selim Cinekda42d652015-12-04 15:51:16 -0800221 public void onNotificationUpdated(NotificationData.Entry entry) {
222 mEntry = entry;
223 mStatusBarNotification = entry.notification;
Adrian Roosb88b1a12015-12-09 18:51:05 -0800224 mPrivateLayout.onNotificationUpdated(entry);
225 mPublicLayout.onNotificationUpdated(entry);
Selim Cinek757d8792016-01-28 16:21:08 -0800226 mShowingPublicInitialized = false;
227 updateClearability();
Selim Cinek8fc93c92015-11-23 17:48:07 -0800228 if (mIsSummaryWithChildren) {
229 recreateNotificationHeader();
230 }
Selim Cinek5a175d92015-11-23 18:01:33 -0800231 if (mIconAnimationRunning) {
232 setIconAnimationRunning(true);
233 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800234 if (mNotificationParent != null) {
235 mNotificationParent.updateChildrenHeaderAppearance();
236 }
Selim Cinek263398f2015-10-21 17:40:23 -0700237 onChildrenCountChanged();
Selim Cinek624c02db2015-12-14 21:00:02 -0800238 // The public layouts expand button is always visible
239 mPublicLayout.updateExpandButtons(true);
Selim Cinekda42d652015-12-04 15:51:16 -0800240 updateLimits();
241 }
242
243 private void updateLimits() {
Selim Cineka1744872016-03-11 15:36:06 -0800244 updateLimitsForView(mPrivateLayout);
245 updateLimitsForView(mPublicLayout);
246 }
247
248 private void updateLimitsForView(NotificationContentView layout) {
249 boolean customView = layout.getContractedChild().getId()
Selim Cinekda42d652015-12-04 15:51:16 -0800250 != com.android.internal.R.id.status_bar_latest_event_content;
251 boolean beforeN = mEntry.targetSdk < Build.VERSION_CODES.N;
252 int minHeight = customView && beforeN && !mIsSummaryWithChildren ?
253 mNotificationMinHeightLegacy : mNotificationMinHeight;
Selim Cineka1744872016-03-11 15:36:06 -0800254 boolean headsUpCustom = layout.getHeadsUpChild() != null &&
255 layout.getHeadsUpChild().getId()
256 != com.android.internal.R.id.status_bar_latest_event_content;
Selim Cinek77019c72015-12-09 10:18:02 -0800257 int headsUpheight = headsUpCustom && beforeN ? mMaxHeadsUpHeightLegacy
258 : mMaxHeadsUpHeight;
Selim Cineka1744872016-03-11 15:36:06 -0800259 layout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200260 }
261
262 public StatusBarNotification getStatusBarNotification() {
263 return mStatusBarNotification;
264 }
265
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700266 public boolean isHeadsUp() {
267 return mIsHeadsUp;
268 }
269
Selim Cinek1a521f32014-11-03 17:39:29 +0100270 public void setHeadsUp(boolean isHeadsUp) {
Selim Cinekc80fdb12015-04-13 15:09:08 -0700271 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek1a521f32014-11-03 17:39:29 +0100272 mIsHeadsUp = isHeadsUp;
Selim Cinek8d490d42015-04-10 00:05:50 -0700273 mPrivateLayout.setHeadsUp(isHeadsUp);
Selim Cinekc80fdb12015-04-13 15:09:08 -0700274 if (intrinsicBefore != getIntrinsicHeight()) {
275 notifyHeightChanged(false /* needsAnimation */);
276 }
Selim Cinek1a521f32014-11-03 17:39:29 +0100277 }
278
Selim Cinekb5605e52015-02-20 18:21:41 +0100279 public void setGroupManager(NotificationGroupManager groupManager) {
280 mGroupManager = groupManager;
Selim Cinek83bc7832015-10-22 13:26:54 -0700281 mPrivateLayout.setGroupManager(groupManager);
Selim Cinekb5605e52015-02-20 18:21:41 +0100282 }
283
Adrian Roosb88b1a12015-12-09 18:51:05 -0800284 public void setRemoteInputController(RemoteInputController r) {
285 mPrivateLayout.setRemoteInputController(r);
286 }
287
Selim Cinekb5605e52015-02-20 18:21:41 +0100288 public void addChildNotification(ExpandableNotificationRow row) {
289 addChildNotification(row, -1);
290 }
291
292 /**
293 * Add a child notification to this view.
294 *
295 * @param row the row to add
296 * @param childIndex the index to add it at, if -1 it will be added at the end
297 */
298 public void addChildNotification(ExpandableNotificationRow row, int childIndex) {
299 if (mChildrenContainer == null) {
300 mChildrenContainerStub.inflate();
301 }
302 mChildrenContainer.addNotification(row, childIndex);
Selim Cinek263398f2015-10-21 17:40:23 -0700303 onChildrenCountChanged();
304 row.setIsChildInGroup(true, this);
Selim Cinekb5605e52015-02-20 18:21:41 +0100305 }
306
307 public void removeChildNotification(ExpandableNotificationRow row) {
308 if (mChildrenContainer != null) {
309 mChildrenContainer.removeNotification(row);
310 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800311 mHeaderUtil.restoreNotificationHeader(row);
Selim Cinek263398f2015-10-21 17:40:23 -0700312 onChildrenCountChanged();
313 row.setIsChildInGroup(false, null);
314 }
315
316 public boolean isChildInGroup() {
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700317 return mNotificationParent != null;
Selim Cinek263398f2015-10-21 17:40:23 -0700318 }
319
Selim Cinek388df6d2015-10-22 13:25:11 -0700320 public ExpandableNotificationRow getNotificationParent() {
321 return mNotificationParent;
322 }
323
Selim Cinek263398f2015-10-21 17:40:23 -0700324 /**
325 * @param isChildInGroup Is this notification now in a group
326 * @param parent the new parent notification
327 */
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700328 public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {;
329 boolean childInGroup = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
330 mNotificationParent = childInGroup ? parent : null;
331 mPrivateLayout.setIsChildInGroup(childInGroup);
332 updateNoBackgroundState();
Selim Cinek34d93b02015-10-22 12:30:38 -0700333 }
334
335 @Override
Selim Cinek72109472016-01-15 16:33:22 -0800336 public boolean onTouchEvent(MotionEvent event) {
337 if (event.getActionMasked() != MotionEvent.ACTION_DOWN
338 || !isChildInGroup() || isGroupExpanded()) {
339 return super.onTouchEvent(event);
340 } else {
341 return false;
342 }
343 }
344
345 @Override
Mady Mellorf0625802016-02-11 18:03:48 -0800346 protected boolean handleSlideBack() {
347 if (mSettingsIconRow != null && mSettingsIconRow.isVisible()) {
348 animateTranslateNotification(0 /* targetLeft */);
349 return true;
350 }
351 return false;
352 }
353
354 @Override
Selim Cinek34d93b02015-10-22 12:30:38 -0700355 protected boolean shouldHideBackground() {
356 return super.shouldHideBackground() || mShowNoBackground;
Selim Cinek263398f2015-10-21 17:40:23 -0700357 }
358
359 @Override
360 public boolean isSummaryWithChildren() {
361 return mIsSummaryWithChildren;
Selim Cinekb5605e52015-02-20 18:21:41 +0100362 }
363
364 @Override
365 public boolean areChildrenExpanded() {
366 return mChildrenExpanded;
367 }
368
369 public List<ExpandableNotificationRow> getNotificationChildren() {
370 return mChildrenContainer == null ? null : mChildrenContainer.getNotificationChildren();
371 }
372
Selim Cinekeef84282015-10-30 16:28:00 -0700373 public int getNumberOfNotificationChildren() {
374 if (mChildrenContainer == null) {
375 return 0;
376 }
377 return mChildrenContainer.getNotificationChildren().size();
378 }
379
Selim Cinekb5605e52015-02-20 18:21:41 +0100380 /**
381 * Apply the order given in the list to the children.
382 *
383 * @param childOrder the new list order
384 * @return whether the list order has changed
385 */
386 public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder) {
387 return mChildrenContainer != null && mChildrenContainer.applyChildOrder(childOrder);
388 }
389
390 public void getChildrenStates(StackScrollState resultState) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700391 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100392 StackViewState parentState = resultState.getViewStateForView(this);
393 mChildrenContainer.getState(resultState, parentState);
394 }
395 }
396
397 public void applyChildrenState(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700398 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100399 mChildrenContainer.applyState(state);
400 }
401 }
402
403 public void prepareExpansionChanged(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700404 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100405 mChildrenContainer.prepareExpansionChanged(state);
406 }
407 }
408
409 public void startChildAnimation(StackScrollState finalState,
Selim Cinek99695592016-01-12 17:51:35 -0800410 StackStateAnimator stateAnimator, long delay, long duration) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700411 if (mIsSummaryWithChildren) {
Selim Cinek99695592016-01-12 17:51:35 -0800412 mChildrenContainer.startAnimationToState(finalState, stateAnimator, delay,
Selim Cinekb5605e52015-02-20 18:21:41 +0100413 duration);
414 }
415 }
416
417 public ExpandableNotificationRow getViewAtPosition(float y) {
Selim Cinek43d30f02016-03-04 10:51:32 -0800418 if (!mIsSummaryWithChildren || !mChildrenExpanded) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100419 return this;
420 } else {
421 ExpandableNotificationRow view = mChildrenContainer.getViewAtPosition(y);
422 return view == null ? this : view;
423 }
424 }
425
Selim Cinekab29aeb2015-02-20 18:18:32 +0100426 public NotificationGuts getGuts() {
427 return mGuts;
428 }
429
Selim Cinek684a4422015-04-15 16:18:39 -0700430 /**
431 * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this
432 * the notification will be rendered on top of the screen.
433 *
434 * @param pinned whether it is pinned
435 */
436 public void setPinned(boolean pinned) {
437 mIsPinned = pinned;
Selim Cinek31aada42015-12-18 17:51:15 -0800438 if (pinned) {
439 setIconAnimationRunning(true);
440 mExpandedWhenPinned = false;
441 } else if (mExpandedWhenPinned) {
442 setUserExpanded(true);
443 }
Selim Cinek98713a42015-09-21 15:47:20 +0200444 setChronometerRunning(mLastChronometerRunning);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700445 }
446
Selim Cinek684a4422015-04-15 16:18:39 -0700447 public boolean isPinned() {
448 return mIsPinned;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700449 }
450
Selim Cinek31aada42015-12-18 17:51:15 -0800451 /**
452 * @param atLeastMinHeight should the value returned be at least the minimum height.
453 * Used to avoid cyclic calls
454 * @return the height of the heads up notification when pinned
455 */
456 public int getPinnedHeadsUpHeight(boolean atLeastMinHeight) {
Selim Cinek77019c72015-12-09 10:18:02 -0800457 if (mIsSummaryWithChildren) {
458 return mChildrenContainer.getIntrinsicHeight();
459 }
Selim Cinek31aada42015-12-18 17:51:15 -0800460 if(mExpandedWhenPinned) {
461 return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
462 } else if (atLeastMinHeight) {
463 return Math.max(getMinHeight(), mHeadsUpHeight);
464 } else {
465 return mHeadsUpHeight;
466 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700467 }
468
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700469 /**
470 * Mark whether this notification was just clicked, i.e. the user has just clicked this
471 * notification in this frame.
472 */
473 public void setJustClicked(boolean justClicked) {
474 mJustClicked = justClicked;
475 }
476
477 /**
478 * @return true if this notification has been clicked in this frame, false otherwise
479 */
480 public boolean wasJustClicked() {
481 return mJustClicked;
482 }
483
Selim Cinek98713a42015-09-21 15:47:20 +0200484 public void setChronometerRunning(boolean running) {
485 mLastChronometerRunning = running;
486 setChronometerRunning(running, mPrivateLayout);
487 setChronometerRunning(running, mPublicLayout);
488 if (mChildrenContainer != null) {
489 List<ExpandableNotificationRow> notificationChildren =
490 mChildrenContainer.getNotificationChildren();
491 for (int i = 0; i < notificationChildren.size(); i++) {
492 ExpandableNotificationRow child = notificationChildren.get(i);
493 child.setChronometerRunning(running);
494 }
495 }
496 }
497
498 private void setChronometerRunning(boolean running, NotificationContentView layout) {
499 if (layout != null) {
500 running = running || isPinned();
501 View contractedChild = layout.getContractedChild();
502 View expandedChild = layout.getExpandedChild();
503 View headsUpChild = layout.getHeadsUpChild();
504 setChronometerRunningForChild(running, contractedChild);
505 setChronometerRunningForChild(running, expandedChild);
506 setChronometerRunningForChild(running, headsUpChild);
507 }
508 }
509
510 private void setChronometerRunningForChild(boolean running, View child) {
511 if (child != null) {
512 View chronometer = child.findViewById(com.android.internal.R.id.chronometer);
513 if (chronometer instanceof Chronometer) {
514 ((Chronometer) chronometer).setStarted(running);
515 }
516 }
517 }
518
Selim Cinekea4bef72015-12-02 15:51:10 -0800519 public NotificationHeaderView getNotificationHeader() {
520 if (mNotificationHeader != null) {
521 return mNotificationHeader;
Selim Cinek8d6440d2015-10-22 13:00:05 -0700522 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800523 return mPrivateLayout.getNotificationHeader();
Selim Cinek8d6440d2015-10-22 13:00:05 -0700524 }
525
Selim Cinek34eda5e2016-02-18 17:10:43 -0800526 private NotificationHeaderView getVisibleNotificationHeader() {
527 if (mNotificationHeader != null) {
528 return mNotificationHeader;
529 }
530 return getShowingLayout().getVisibleNotificationHeader();
531 }
532
Selim Cinek570981d2015-12-01 11:37:01 -0800533 public void setOnExpandClickListener(OnExpandClickListener onExpandClickListener) {
534 mOnExpandClickListener = onExpandClickListener;
535 }
536
Selim Cinek31aada42015-12-18 17:51:15 -0800537 public void setHeadsUpManager(HeadsUpManager headsUpManager) {
538 mHeadsUpManager = headsUpManager;
539 }
540
Selim Cinek01af3342016-02-09 19:25:31 -0800541 public void reInflateViews() {
542 initDimens();
543 if (mIsSummaryWithChildren) {
544 removeView(mNotificationHeader);
545 mNotificationHeader = null;
546 recreateNotificationHeader();
547 if (mChildrenContainer != null) {
548 mChildrenContainer.reInflateViews();
549 }
550 }
551 if (mGuts != null) {
552 View oldGuts = mGuts;
553 int index = indexOfChild(oldGuts);
554 removeView(oldGuts);
555 mGuts = (NotificationGuts) LayoutInflater.from(mContext).inflate(
556 R.layout.notification_guts, this, false);
557 mGuts.setVisibility(oldGuts.getVisibility());
558 addView(mGuts, index);
559 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800560 if (mSettingsIconRow != null) {
561 View oldSettings = mSettingsIconRow;
562 int settingsIndex = indexOfChild(oldSettings);
563 removeView(oldSettings);
564 mSettingsIconRow = (NotificationSettingsIconRow) LayoutInflater.from(mContext).inflate(
565 R.layout.notification_settings_icon_row, this, false);
566 mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
567 mSettingsIconRow.setVisibility(oldSettings.getVisibility());
568 addView(mSettingsIconRow, settingsIndex);
569
570 }
Selim Cinekde33a4a2016-02-11 16:43:41 -0800571 mPrivateLayout.reInflateViews();
572 mPublicLayout.reInflateViews();
Selim Cinek01af3342016-02-09 19:25:31 -0800573 }
574
Selim Cinekc3179332016-03-04 14:44:56 -0800575 public void setContentBackground(int customBackgroundColor, boolean animate,
576 NotificationContentView notificationContentView) {
577 if (getShowingLayout() == notificationContentView) {
578 setTintColor(customBackgroundColor, animate);
579 }
580 }
581
Adrian Roos0bd8a4b2016-03-14 16:21:44 -0700582 public void closeRemoteInput() {
583 mPrivateLayout.closeRemoteInput();
584 mPublicLayout.closeRemoteInput();
585 }
586
Chris Wren78403d72014-07-28 10:23:24 +0100587 public interface ExpansionLogger {
588 public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
589 }
Selim Cinek1685e632014-04-08 02:27:49 +0200590
Chris Wren51c75102013-07-16 20:49:17 -0400591 public ExpandableNotificationRow(Context context, AttributeSet attrs) {
592 super(context, attrs);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700593 mFalsingManager = FalsingManager.getInstance(context);
Selim Cinek01af3342016-02-09 19:25:31 -0800594 initDimens();
595 }
596
597 private void initDimens() {
Selim Cinekf619ffc2016-02-17 14:53:05 -0800598 mNotificationMinHeightLegacy = getFontScaledHeight(R.dimen.notification_min_height_legacy);
599 mNotificationMinHeight = getFontScaledHeight(R.dimen.notification_min_height);
600 mNotificationMaxHeight = getFontScaledHeight(R.dimen.notification_max_height);
601 mMaxHeadsUpHeightLegacy = getFontScaledHeight(
Selim Cinek77019c72015-12-09 10:18:02 -0800602 R.dimen.notification_max_heads_up_height_legacy);
Selim Cinekf619ffc2016-02-17 14:53:05 -0800603 mMaxHeadsUpHeight = getFontScaledHeight(R.dimen.notification_max_heads_up_height);
604 }
605
606 /**
607 * @param dimenId the dimen to look up
608 * @return the font scaled dimen as if it were in sp but doesn't shrink sizes below dp
609 */
610 private int getFontScaledHeight(int dimenId) {
611 int dimensionPixelSize = getResources().getDimensionPixelSize(dimenId);
612 float factor = Math.max(1.0f, getResources().getDisplayMetrics().scaledDensity /
613 getResources().getDisplayMetrics().density);
614 return (int) (dimensionPixelSize * factor);
Chris Wren51c75102013-07-16 20:49:17 -0400615 }
616
Christoph Studera7fe6312014-06-27 19:32:44 +0200617 /**
618 * Resets this view so it can be re-used for an updated notification.
619 */
Christoph Studer22f2ee52014-07-29 22:57:21 +0200620 @Override
Christoph Studera7fe6312014-06-27 19:32:44 +0200621 public void reset() {
Christoph Studer22f2ee52014-07-29 22:57:21 +0200622 super.reset();
Chris Wren78403d72014-07-28 10:23:24 +0100623 final boolean wasExpanded = isExpanded();
Christoph Studera7fe6312014-06-27 19:32:44 +0200624 mExpandable = false;
625 mHasUserChangedExpansion = false;
626 mUserLocked = false;
627 mShowingPublic = false;
Jorim Jaggiae441282014-08-01 02:45:18 +0200628 mSensitive = false;
629 mShowingPublicInitialized = false;
Christoph Studera7fe6312014-06-27 19:32:44 +0200630 mIsSystemExpanded = false;
Selim Cinek83bc7832015-10-22 13:26:54 -0700631 mOnKeyguard = false;
Selim Cinek51d94912016-03-02 15:34:28 -0800632 mPublicLayout.reset();
633 mPrivateLayout.reset();
Selim Cinek31094df2014-08-14 19:28:15 +0200634 resetHeight();
Mady Mellor4b80b102016-01-22 08:03:58 -0800635 resetTranslation();
Selim Cinek31094df2014-08-14 19:28:15 +0200636 logExpansionEvent(false, wasExpanded);
637 }
638
639 public void resetHeight() {
Christoph Studera7fe6312014-06-27 19:32:44 +0200640 mMaxExpandHeight = 0;
Selim Cinek8d490d42015-04-10 00:05:50 -0700641 mHeadsUpHeight = 0;
Selim Cinek31094df2014-08-14 19:28:15 +0200642 onHeightReset();
Selim Cinek6e28a672014-09-05 14:43:28 +0200643 requestLayout();
Christoph Studera7fe6312014-06-27 19:32:44 +0200644 }
645
Jorim Jaggi251957d2014-04-09 04:24:09 +0200646 @Override
647 protected void onFinishInflate() {
648 super.onFinishInflate();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200649 mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800650 mPublicLayout.setContainingNotification(this);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200651 mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800652 mPrivateLayout.setExpandClickListener(mExpandClickListener);
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800653 mPrivateLayout.setContainingNotification(this);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800654 mPublicLayout.setExpandClickListener(mExpandClickListener);
Mady Mellor4b80b102016-01-22 08:03:58 -0800655 mSettingsIconRowStub = (ViewStub) findViewById(R.id.settings_icon_row_stub);
656 mSettingsIconRowStub.setOnInflateListener(new ViewStub.OnInflateListener() {
657 @Override
658 public void onInflate(ViewStub stub, View inflated) {
659 mSettingsIconRow = (NotificationSettingsIconRow) inflated;
660 mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
661 }
662 });
Selim Cinekab29aeb2015-02-20 18:18:32 +0100663 mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
664 mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200665 @Override
666 public void onInflate(ViewStub stub, View inflated) {
667 mGuts = (NotificationGuts) inflated;
668 mGuts.setClipTopAmount(getClipTopAmount());
669 mGuts.setActualHeight(getActualHeight());
Selim Cinekab29aeb2015-02-20 18:18:32 +0100670 mGutsStub = null;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200671 }
672 });
Selim Cinekb5605e52015-02-20 18:21:41 +0100673 mChildrenContainerStub = (ViewStub) findViewById(R.id.child_container_stub);
674 mChildrenContainerStub.setOnInflateListener(new ViewStub.OnInflateListener() {
675
676 @Override
677 public void onInflate(ViewStub stub, View inflated) {
678 mChildrenContainer = (NotificationChildrenContainer) inflated;
Selim Cinek388df6d2015-10-22 13:25:11 -0700679 mChildrenContainer.setNotificationParent(ExpandableNotificationRow.this);
Mady Mellor4b80b102016-01-22 08:03:58 -0800680 mTranslateableViews.add(mChildrenContainer);
Selim Cinekb5605e52015-02-20 18:21:41 +0100681 }
682 });
Selim Cinek863834b2014-05-20 04:20:25 +0200683 mVetoButton = findViewById(R.id.veto);
Mady Mellor4b80b102016-01-22 08:03:58 -0800684
685 // Add the views that we translate to reveal the gear
686 mTranslateableViews = new ArrayList<View>();
687 for (int i = 0; i < getChildCount(); i++) {
688 mTranslateableViews.add(getChildAt(i));
689 }
690 // Remove views that don't translate
691 mTranslateableViews.remove(mVetoButton);
692 mTranslateableViews.remove(mSettingsIconRowStub);
693 mTranslateableViews.remove(mChildrenContainerStub);
694 mTranslateableViews.remove(mGutsStub);
695 }
696
Mady Mellor34958fa2016-02-23 09:52:17 -0800697 private void setTranslationForOutline(float translationX) {
Mady Mellor4b80b102016-01-22 08:03:58 -0800698 setOutlineRect(false, translationX, getTop(), getRight() + translationX, getBottom());
699 }
700
701 public void resetTranslation() {
702 if (mTranslateableViews != null) {
703 for (int i = 0; i < mTranslateableViews.size(); i++) {
704 mTranslateableViews.get(i).setTranslationX(0);
705 }
706 setTranslationForOutline(0);
707 }
708 if (mSettingsIconRow != null) {
709 mSettingsIconRow.resetState();
710 }
711 }
712
713 public void animateTranslateNotification(final float leftTarget) {
714 if (mTranslateAnim != null) {
715 mTranslateAnim.cancel();
716 }
Mady Mellor34958fa2016-02-23 09:52:17 -0800717 mTranslateAnim = (AnimatorSet) getTranslateViewAnimator(leftTarget,
718 null /* updateListener */);
719 if (mTranslateAnim != null) {
720 mTranslateAnim.start();
721 }
722 }
723
724 @Override
725 public void setTranslation(float translationX) {
726 if (areGutsExposed()) {
727 // Don't translate if guts are showing.
728 return;
729 }
730 // Translate the group of views
731 for (int i = 0; i < mTranslateableViews.size(); i++) {
732 if (mTranslateableViews.get(i) != null) {
733 mTranslateableViews.get(i).setTranslationX(translationX);
734 }
735 }
736 setTranslationForOutline(translationX);
737 if (mSettingsIconRow != null) {
738 mSettingsIconRow.updateSettingsIcons(translationX, getMeasuredWidth());
739 }
740 }
741
742 @Override
743 public float getTranslation() {
744 if (mTranslateableViews != null && mTranslateableViews.size() > 0) {
745 // All of the views in the list should have same translation, just use first one.
746 return mTranslateableViews.get(0).getTranslationX();
747 }
748 return 0;
749 }
750
751 public Animator getTranslateViewAnimator(final float leftTarget,
752 AnimatorUpdateListener listener) {
753 if (areGutsExposed()) {
754 // No translation if guts are exposed.
755 return null;
756 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800757 AnimatorSet set = new AnimatorSet();
758 if (mTranslateableViews != null) {
759 for (int i = 0; i < mTranslateableViews.size(); i++) {
760 final View animView = mTranslateableViews.get(i);
761 final ObjectAnimator translateAnim = ObjectAnimator.ofFloat(
762 animView, "translationX", leftTarget);
763 if (i == 0) {
764 translateAnim.addUpdateListener(new AnimatorUpdateListener() {
765 @Override
766 public void onAnimationUpdate(ValueAnimator animation) {
767 setTranslationForOutline((float) animation.getAnimatedValue());
Mady Mellor34958fa2016-02-23 09:52:17 -0800768 if (mSettingsIconRow != null) {
769 mSettingsIconRow.updateSettingsIcons(
770 (float) animation.getAnimatedValue(), getMeasuredWidth());
771 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800772 }
773 });
Mady Mellor34958fa2016-02-23 09:52:17 -0800774 if (listener != null) {
775 translateAnim.addUpdateListener(listener);
776 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800777 }
778 translateAnim.addListener(new AnimatorListenerAdapter() {
779 @Override
780 public void onAnimationEnd(Animator anim) {
781 if (mSettingsIconRow != null && leftTarget == 0) {
782 mSettingsIconRow.resetState();
783 }
784 mTranslateAnim = null;
785 }
786 });
787 set.play(translateAnim);
788 }
789 }
Mady Mellor34958fa2016-02-23 09:52:17 -0800790 return set;
Mady Mellor4b80b102016-01-22 08:03:58 -0800791 }
792
793 public float getSpaceForGear() {
794 if (mSettingsIconRow != null) {
795 return mSettingsIconRow.getSpaceForGear();
796 }
797 return 0;
798 }
799
800 public NotificationSettingsIconRow getSettingsRow() {
801 if (mSettingsIconRow == null) {
802 mSettingsIconRowStub.inflate();
803 }
804 return mSettingsIconRow;
805 }
806
Selim Cinekab29aeb2015-02-20 18:18:32 +0100807 public void inflateGuts() {
808 if (mGuts == null) {
809 mGutsStub.inflate();
810 }
811 }
812
Selim Cinekda42d652015-12-04 15:51:16 -0800813 private void updateChildrenVisibility() {
Selim Cinekd84a5932015-12-15 11:45:36 -0800814 mPrivateLayout.setVisibility(!mShowingPublic && !mIsSummaryWithChildren ? VISIBLE
815 : INVISIBLE);
Selim Cinekef5127e2015-12-21 16:55:58 -0800816 if (mChildrenContainer != null) {
817 mChildrenContainer.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
818 : INVISIBLE);
Selim Cinekb5605e52015-02-20 18:21:41 +0100819 }
Selim Cinekef5127e2015-12-21 16:55:58 -0800820 if (mNotificationHeader != null) {
821 mNotificationHeader.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
822 : INVISIBLE);
823 }
Selim Cinekda42d652015-12-04 15:51:16 -0800824 // The limits might have changed if the view suddenly became a group or vice versa
825 updateLimits();
Selim Cinekb5605e52015-02-20 18:21:41 +0100826 }
827
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200828 @Override
Alan Viverettea54956a2015-01-07 16:05:02 -0800829 public boolean onRequestSendAccessibilityEventInternal(View child, AccessibilityEvent event) {
830 if (super.onRequestSendAccessibilityEventInternal(child, event)) {
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200831 // Add a record for the entire layout since its content is somehow small.
832 // The event comes from a leaf view that is interacted with.
833 AccessibilityEvent record = AccessibilityEvent.obtain();
834 onInitializeAccessibilityEvent(record);
835 dispatchPopulateAccessibilityEvent(record);
836 event.appendRecord(record);
837 return true;
838 }
839 return false;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200840 }
Chris Wren51c75102013-07-16 20:49:17 -0400841
John Spurlocke15452b2014-08-21 09:44:39 -0400842 @Override
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100843 public void setDark(boolean dark, boolean fade, long delay) {
844 super.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400845 final NotificationContentView showing = getShowingLayout();
846 if (showing != null) {
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100847 showing.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400848 }
Selim Cinek9c7712d2015-12-08 19:19:48 -0800849 if (mIsSummaryWithChildren) {
850 mChildrenContainer.setDark(dark, fade, delay);
851 mNotificationHeaderWrapper.setDark(dark, fade, delay);
852 }
John Spurlocke15452b2014-08-21 09:44:39 -0400853 }
854
Chris Wren51c75102013-07-16 20:49:17 -0400855 public boolean isExpandable() {
Selim Cinek388df6d2015-10-22 13:25:11 -0700856 if (mIsSummaryWithChildren && !mShowingPublic) {
857 return !mChildrenExpanded;
858 }
Chris Wren51c75102013-07-16 20:49:17 -0400859 return mExpandable;
860 }
861
862 public void setExpandable(boolean expandable) {
863 mExpandable = expandable;
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800864 mPrivateLayout.updateExpandButtons(isExpandable());
Chris Wren51c75102013-07-16 20:49:17 -0400865 }
866
Selim Cinek4ffd6362015-12-29 15:12:23 +0100867 @Override
868 public void setClipToActualHeight(boolean clipToActualHeight) {
Selim Cinek084c16b2016-01-22 17:48:22 -0800869 super.setClipToActualHeight(clipToActualHeight || isUserLocked());
870 getShowingLayout().setClipToActualHeight(clipToActualHeight || isUserLocked());
Selim Cinek4ffd6362015-12-29 15:12:23 +0100871 }
872
Selim Cinek1685e632014-04-08 02:27:49 +0200873 /**
874 * @return whether the user has changed the expansion state
875 */
876 public boolean hasUserChangedExpansion() {
877 return mHasUserChangedExpansion;
878 }
879
Chris Wren51c75102013-07-16 20:49:17 -0400880 public boolean isUserExpanded() {
881 return mUserExpanded;
882 }
883
Selim Cinek1685e632014-04-08 02:27:49 +0200884 /**
885 * Set this notification to be expanded by the user
886 *
887 * @param userExpanded whether the user wants this notification to be expanded
888 */
Chris Wren51c75102013-07-16 20:49:17 -0400889 public void setUserExpanded(boolean userExpanded) {
Selim Cinek388df6d2015-10-22 13:25:11 -0700890 setUserExpanded(userExpanded, false /* allowChildExpansion */);
891 }
892
893 /**
894 * Set this notification to be expanded by the user
895 *
896 * @param userExpanded whether the user wants this notification to be expanded
897 * @param allowChildExpansion whether a call to this method allows expanding children
898 */
899 public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700900 mFalsingManager.setNotificationExpanded();
Selim Cinek388df6d2015-10-22 13:25:11 -0700901 if (mIsSummaryWithChildren && !mShowingPublic && allowChildExpansion) {
902 mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
903 return;
904 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200905 if (userExpanded && !mExpandable) return;
Chris Wren78403d72014-07-28 10:23:24 +0100906 final boolean wasExpanded = isExpanded();
Selim Cinek1685e632014-04-08 02:27:49 +0200907 mHasUserChangedExpansion = true;
Chris Wren51c75102013-07-16 20:49:17 -0400908 mUserExpanded = userExpanded;
Chris Wren78403d72014-07-28 10:23:24 +0100909 logExpansionEvent(true, wasExpanded);
Chris Wren51c75102013-07-16 20:49:17 -0400910 }
911
Selim Cinekccd14fb2014-08-12 18:53:24 +0200912 public void resetUserExpansion() {
913 mHasUserChangedExpansion = false;
914 mUserExpanded = false;
915 }
916
Chris Wren51c75102013-07-16 20:49:17 -0400917 public boolean isUserLocked() {
918 return mUserLocked;
919 }
920
921 public void setUserLocked(boolean userLocked) {
922 mUserLocked = userLocked;
Selim Cinek8f2f6a62016-02-23 19:56:31 -0800923 mPrivateLayout.setUserExpanding(userLocked);
Selim Cinek42357e02016-02-24 18:48:01 -0800924 if (mIsSummaryWithChildren) {
925 mChildrenContainer.setUserLocked(userLocked);
926 }
Chris Wren51c75102013-07-16 20:49:17 -0400927 }
928
Selim Cinek1685e632014-04-08 02:27:49 +0200929 /**
930 * @return has the system set this notification to be expanded
931 */
932 public boolean isSystemExpanded() {
933 return mIsSystemExpanded;
934 }
935
936 /**
937 * Set this notification to be expanded by the system.
938 *
939 * @param expand whether the system wants this notification to be expanded.
940 */
941 public void setSystemExpanded(boolean expand) {
Selim Cinek31094df2014-08-14 19:28:15 +0200942 if (expand != mIsSystemExpanded) {
943 final boolean wasExpanded = isExpanded();
944 mIsSystemExpanded = expand;
Selim Cinekb5605e52015-02-20 18:21:41 +0100945 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200946 logExpansionEvent(false, wasExpanded);
Selim Cinek83bc7832015-10-22 13:26:54 -0700947 if (mChildrenContainer != null) {
948 mChildrenContainer.updateGroupOverflow();
949 }
Selim Cinek31094df2014-08-14 19:28:15 +0200950 }
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200951 }
952
953 /**
Selim Cinek83bc7832015-10-22 13:26:54 -0700954 * @param onKeyguard whether to prevent notification expansion
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200955 */
Selim Cinek83bc7832015-10-22 13:26:54 -0700956 public void setOnKeyguard(boolean onKeyguard) {
957 if (onKeyguard != mOnKeyguard) {
Selim Cinek31094df2014-08-14 19:28:15 +0200958 final boolean wasExpanded = isExpanded();
Selim Cinek83bc7832015-10-22 13:26:54 -0700959 mOnKeyguard = onKeyguard;
Selim Cinek31094df2014-08-14 19:28:15 +0200960 logExpansionEvent(false, wasExpanded);
961 if (wasExpanded != isExpanded()) {
Selim Cinek2108fe02015-12-10 12:56:13 -0800962 if (mIsSummaryWithChildren) {
963 mChildrenContainer.updateGroupOverflow();
964 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800965 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200966 }
967 }
Selim Cinek1685e632014-04-08 02:27:49 +0200968 }
969
970 /**
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400971 * @return Can the underlying notification be cleared?
972 */
973 public boolean isClearable() {
Selim Cineka37774f2014-11-11 19:16:18 +0100974 return mStatusBarNotification != null && mStatusBarNotification.isClearable();
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400975 }
976
Jorim Jaggi9cbadd32014-05-01 20:18:31 +0200977 @Override
978 public int getIntrinsicHeight() {
Jorim Jaggibe565df2014-04-28 17:51:23 +0200979 if (isUserLocked()) {
980 return getActualHeight();
981 }
Selim Cinekd84a5932015-12-15 11:45:36 -0800982 if (mGuts != null && mGuts.areGutsExposed()) {
983 return mGuts.getHeight();
984 } else if ((isChildInGroup() && !isGroupExpanded())) {
985 return mPrivateLayout.getMinHeight();
986 } else if (mSensitive && mHideSensitiveForIntrinsicHeight) {
987 return getMinHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -0700988 } else if (mIsSummaryWithChildren && !mOnKeyguard) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800989 return mChildrenContainer.getIntrinsicHeight();
Selim Cinek60122be2015-04-15 18:16:50 -0700990 } else if (mIsHeadsUp) {
Selim Cinek31aada42015-12-18 17:51:15 -0800991 if (isPinned()) {
992 return getPinnedHeadsUpHeight(true /* atLeastMinHeight */);
993 } else if (isExpanded()) {
Selim Cinekd84a5932015-12-15 11:45:36 -0800994 return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -0700995 } else {
Selim Cinekd84a5932015-12-15 11:45:36 -0800996 return Math.max(getMinHeight(), mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -0700997 }
Selim Cinek31aada42015-12-18 17:51:15 -0800998 } else if (isExpanded()) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700999 return getMaxExpandHeight();
Selim Cinekd84a5932015-12-15 11:45:36 -08001000 } else {
1001 return getMinHeight();
Selim Cinek1685e632014-04-08 02:27:49 +02001002 }
Selim Cinekb5605e52015-02-20 18:21:41 +01001003 }
Selim Cinek1685e632014-04-08 02:27:49 +02001004
Selim Cinekeef84282015-10-30 16:28:00 -07001005 private boolean isGroupExpanded() {
1006 return mGroupManager.isGroupExpanded(mStatusBarNotification);
Selim Cinekb5605e52015-02-20 18:21:41 +01001007 }
1008
Selim Cinekeef84282015-10-30 16:28:00 -07001009 /**
1010 * @return whether this view has a header on the top of the content
1011 */
1012 private boolean hasNotificationHeader() {
1013 return mIsSummaryWithChildren;
Selim Cinek1685e632014-04-08 02:27:49 +02001014 }
1015
Selim Cinek263398f2015-10-21 17:40:23 -07001016 private void onChildrenCountChanged() {
Selim Cinek8fc93c92015-11-23 17:48:07 -08001017 mIsSummaryWithChildren = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS
Selim Cinek263398f2015-10-21 17:40:23 -07001018 && mGroupManager.hasGroupChildren(mStatusBarNotification);
Selim Cinek8fc93c92015-11-23 17:48:07 -08001019 if (mIsSummaryWithChildren) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001020 if (mChildrenContainer == null) {
1021 mChildrenContainerStub.inflate();
1022 }
Selim Cinek8fc93c92015-11-23 17:48:07 -08001023 if (mNotificationHeader == null) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001024 recreateNotificationHeader();
1025 }
Selim Cinek263398f2015-10-21 17:40:23 -07001026 }
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001027 mPrivateLayout.updateExpandButtons(isExpandable());
Selim Cinekea4bef72015-12-02 15:51:10 -08001028 updateChildrenHeaderAppearance();
Selim Cinekda42d652015-12-04 15:51:16 -08001029 updateChildrenVisibility();
Selim Cinek263398f2015-10-21 17:40:23 -07001030 }
1031
Selim Cinek1685e632014-04-08 02:27:49 +02001032 /**
1033 * Check whether the view state is currently expanded. This is given by the system in {@link
1034 * #setSystemExpanded(boolean)} and can be overridden by user expansion or
1035 * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
1036 * view can differ from this state, if layout params are modified from outside.
1037 *
1038 * @return whether the view state is currently expanded.
1039 */
Selim Cinek83bc7832015-10-22 13:26:54 -07001040 public boolean isExpanded() {
Selim Cineke81b82b2016-03-04 11:22:28 -08001041 return isExpanded(false /* allowOnKeyguard */);
1042 }
1043
1044 public boolean isExpanded(boolean allowOnKeyguard) {
1045 return (!mOnKeyguard || allowOnKeyguard)
Selim Cinekb5605e52015-02-20 18:21:41 +01001046 && (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded())
1047 || isUserExpanded());
1048 }
1049
1050 private boolean isSystemChildExpanded() {
1051 return mIsSystemChildExpanded;
1052 }
1053
1054 public void setSystemChildExpanded(boolean expanded) {
1055 mIsSystemChildExpanded = expanded;
Selim Cinek1685e632014-04-08 02:27:49 +02001056 }
1057
1058 @Override
1059 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
1060 super.onLayout(changed, left, top, right, bottom);
Selim Cinek8d490d42015-04-10 00:05:50 -07001061 updateMaxHeights();
Selim Cinek1685e632014-04-08 02:27:49 +02001062 }
1063
Selim Cinek8d490d42015-04-10 00:05:50 -07001064 private void updateMaxHeights() {
Selim Cinekd2319fb2014-09-01 19:41:54 +02001065 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek8d490d42015-04-10 00:05:50 -07001066 View expandedChild = mPrivateLayout.getExpandedChild();
1067 if (expandedChild == null) {
1068 expandedChild = mPrivateLayout.getContractedChild();
1069 }
1070 mMaxExpandHeight = expandedChild.getHeight();
1071 View headsUpChild = mPrivateLayout.getHeadsUpChild();
Selim Cinek1f3f5442015-04-10 17:54:46 -07001072 if (headsUpChild == null) {
1073 headsUpChild = mPrivateLayout.getContractedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -07001074 }
Selim Cinek1f3f5442015-04-10 17:54:46 -07001075 mHeadsUpHeight = headsUpChild.getHeight();
Selim Cinekd2319fb2014-09-01 19:41:54 +02001076 if (intrinsicBefore != getIntrinsicHeight()) {
Selim Cinekb5605e52015-02-20 18:21:41 +01001077 notifyHeightChanged(false /* needsAnimation */);
Selim Cinekd2319fb2014-09-01 19:41:54 +02001078 }
1079 }
1080
Selim Cinekfa0a2d32016-01-14 13:02:21 -08001081 @Override
1082 public void notifyHeightChanged(boolean needsAnimation) {
1083 super.notifyHeightChanged(needsAnimation);
1084 getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked());
1085 }
1086
Selim Cinek3c76d502016-02-19 15:16:33 -08001087 public void setSensitive(boolean sensitive, boolean hideSensitive) {
Jorim Jaggiae441282014-08-01 02:45:18 +02001088 mSensitive = sensitive;
Selim Cinek3c76d502016-02-19 15:16:33 -08001089 mSensitiveHiddenInGeneral = hideSensitive;
Jorim Jaggiae441282014-08-01 02:45:18 +02001090 }
1091
1092 public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
Selim Cinek60122be2015-04-15 18:16:50 -07001093 mHideSensitiveForIntrinsicHeight = hideSensitive;
Selim Cineka52f6a12016-02-29 15:35:58 -08001094 if (mIsSummaryWithChildren) {
1095 List<ExpandableNotificationRow> notificationChildren =
1096 mChildrenContainer.getNotificationChildren();
1097 for (int i = 0; i < notificationChildren.size(); i++) {
1098 ExpandableNotificationRow child = notificationChildren.get(i);
1099 child.setHideSensitiveForIntrinsicHeight(hideSensitive);
1100 }
1101 }
Jorim Jaggiae441282014-08-01 02:45:18 +02001102 }
1103
1104 public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
1105 long duration) {
1106 boolean oldShowingPublic = mShowingPublic;
1107 mShowingPublic = mSensitive && hideSensitive;
1108 if (mShowingPublicInitialized && mShowingPublic == oldShowingPublic) {
1109 return;
1110 }
Dan Sandlera5e0f412014-01-23 15:11:54 -05001111
1112 // bail out if no public version
Selim Cinek1685e632014-04-08 02:27:49 +02001113 if (mPublicLayout.getChildCount() == 0) return;
Dan Sandlera5e0f412014-01-23 15:11:54 -05001114
Jorim Jaggiae441282014-08-01 02:45:18 +02001115 if (!animated) {
1116 mPublicLayout.animate().cancel();
1117 mPrivateLayout.animate().cancel();
1118 mPublicLayout.setAlpha(1f);
1119 mPrivateLayout.setAlpha(1f);
1120 mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
Selim Cinekd84a5932015-12-15 11:45:36 -08001121 updateChildrenVisibility();
Jorim Jaggiae441282014-08-01 02:45:18 +02001122 } else {
1123 animateShowingPublic(delay, duration);
1124 }
Selim Cinekc3179332016-03-04 14:44:56 -08001125 NotificationContentView showingLayout = getShowingLayout();
1126 showingLayout.updateBackgroundColor(animated);
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001127 mPrivateLayout.updateExpandButtons(isExpandable());
Selim Cinek757d8792016-01-28 16:21:08 -08001128 updateClearability();
Jorim Jaggiae441282014-08-01 02:45:18 +02001129 mShowingPublicInitialized = true;
1130 }
1131
1132 private void animateShowingPublic(long delay, long duration) {
Selim Cinekd84a5932015-12-15 11:45:36 -08001133 View[] privateViews = mIsSummaryWithChildren ?
1134 new View[] {mChildrenContainer, mNotificationHeader}
1135 : new View[] {mPrivateLayout};
1136 View[] publicViews = new View[] {mPublicLayout};
1137 View[] hiddenChildren = mShowingPublic ? privateViews : publicViews;
1138 View[] shownChildren = mShowingPublic ? publicViews : privateViews;
1139 for (final View hiddenView : hiddenChildren) {
1140 hiddenView.setVisibility(View.VISIBLE);
1141 hiddenView.animate().cancel();
1142 hiddenView.animate()
1143 .alpha(0f)
1144 .setStartDelay(delay)
1145 .setDuration(duration)
1146 .withEndAction(new Runnable() {
1147 @Override
1148 public void run() {
1149 hiddenView.setVisibility(View.INVISIBLE);
1150 }
1151 });
1152 }
1153 for (View showView : shownChildren) {
1154 showView.setVisibility(View.VISIBLE);
1155 showView.setAlpha(0f);
1156 showView.animate().cancel();
1157 showView.animate()
1158 .alpha(1f)
1159 .setStartDelay(delay)
1160 .setDuration(duration);
1161 }
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001162 }
1163
Selim Cinek3776fe02016-02-04 13:32:43 -08001164 public boolean mustStayOnScreen() {
1165 return mIsHeadsUp;
1166 }
1167
Selim Cinek757d8792016-01-28 16:21:08 -08001168 private void updateClearability() {
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001169 // public versions cannot be dismissed
Selim Cinek3c76d502016-02-19 15:16:33 -08001170 mVetoButton.setVisibility(isClearable() && (!mShowingPublic
1171 || !mSensitiveHiddenInGeneral) ? View.VISIBLE : View.GONE);
Dan Sandlera5e0f412014-01-23 15:11:54 -05001172 }
Jorim Jaggi251957d2014-04-09 04:24:09 +02001173
Selim Cinekb5605e52015-02-20 18:21:41 +01001174 public void setChildrenExpanded(boolean expanded, boolean animate) {
1175 mChildrenExpanded = expanded;
Selim Cinek7b836392015-12-04 20:02:59 -08001176 if (mNotificationHeader != null) {
1177 mNotificationHeader.setExpanded(expanded);
1178 }
Selim Cinek83bc7832015-10-22 13:26:54 -07001179 if (mChildrenContainer != null) {
1180 mChildrenContainer.setChildrenExpanded(expanded);
1181 }
Selim Cinekb5605e52015-02-20 18:21:41 +01001182 }
1183
Selim Cinekb5605e52015-02-20 18:21:41 +01001184 public static void applyTint(View v, int color) {
1185 int alpha;
1186 if (color != 0) {
1187 alpha = COLORED_DIVIDER_ALPHA;
1188 } else {
1189 color = 0xff000000;
1190 alpha = DEFAULT_DIVIDER_ALPHA;
1191 }
1192 if (v.getBackground() instanceof ColorDrawable) {
1193 ColorDrawable background = (ColorDrawable) v.getBackground();
1194 background.mutate();
1195 background.setColor(color);
1196 background.setAlpha(alpha);
1197 }
1198 }
1199
Selim Cinek1685e632014-04-08 02:27:49 +02001200 public int getMaxExpandHeight() {
Selim Cinekb5605e52015-02-20 18:21:41 +01001201 return mMaxExpandHeight;
Chris Wren51c75102013-07-16 20:49:17 -04001202 }
Jorim Jaggi584a7aa2014-04-10 23:26:13 +02001203
Mady Mellor34958fa2016-02-23 09:52:17 -08001204 public boolean areGutsExposed() {
1205 return (mGuts != null && mGuts.areGutsExposed());
1206 }
1207
Jorim Jaggibe565df2014-04-28 17:51:23 +02001208 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001209 public boolean isContentExpandable() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001210 NotificationContentView showingLayout = getShowingLayout();
1211 return showingLayout.isContentExpandable();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001212 }
1213
1214 @Override
Selim Cinek560e64d2015-06-09 19:58:11 -07001215 protected View getContentView() {
1216 return getShowingLayout();
1217 }
1218
1219 @Override
Jorim Jaggid552d9d2014-05-07 19:41:13 +02001220 public void setActualHeight(int height, boolean notifyListeners) {
Selim Cinekb5605e52015-02-20 18:21:41 +01001221 super.setActualHeight(height, notifyListeners);
Mady Mellorb53bc272016-02-11 18:28:23 -08001222 if (mGuts != null && mGuts.areGutsExposed()) {
1223 mGuts.setActualHeight(height);
1224 return;
1225 }
Selim Cinekeef84282015-10-30 16:28:00 -07001226 int contentHeight = Math.max(getMinHeight(), height);
Selim Cinekb5605e52015-02-20 18:21:41 +01001227 mPrivateLayout.setContentHeight(contentHeight);
1228 mPublicLayout.setContentHeight(contentHeight);
Selim Cinek42357e02016-02-24 18:48:01 -08001229 if (mIsSummaryWithChildren) {
1230 mChildrenContainer.setActualHeight(height);
1231 }
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001232 if (mGuts != null) {
1233 mGuts.setActualHeight(height);
1234 }
Jorim Jaggibe565df2014-04-28 17:51:23 +02001235 }
1236
1237 @Override
Selim Cinekb5605e52015-02-20 18:21:41 +01001238 public int getMaxContentHeight() {
Selim Cinek83bc7832015-10-22 13:26:54 -07001239 if (mIsSummaryWithChildren && !mShowingPublic) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001240 return mChildrenContainer.getMaxContentHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -07001241 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001242 NotificationContentView showingLayout = getShowingLayout();
1243 return showingLayout.getMaxHeight();
Jorim Jaggibe565df2014-04-28 17:51:23 +02001244 }
1245
1246 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001247 public int getMinHeight() {
Selim Cinek31aada42015-12-18 17:51:15 -08001248 if (mIsHeadsUp && mHeadsUpManager.isTrackingHeadsUp()) {
1249 return getPinnedHeadsUpHeight(false /* atLeastMinHeight */);
1250 } else if (mIsSummaryWithChildren && !isGroupExpanded() && !mShowingPublic) {
Selim Cinekb55386d2015-12-16 17:26:49 -08001251 return mChildrenContainer.getMinHeight();
Selim Cinek31aada42015-12-18 17:51:15 -08001252 } else if (mIsHeadsUp) {
1253 return mHeadsUpHeight;
Selim Cinekb55386d2015-12-16 17:26:49 -08001254 }
Selim Cinek816c8e42015-11-19 12:00:45 -08001255 NotificationContentView showingLayout = getShowingLayout();
1256 return showingLayout.getMinHeight();
1257 }
1258
1259 @Override
1260 public int getMinExpandHeight() {
Selim Cinek2c584612016-02-29 16:14:25 -08001261 if (mIsSummaryWithChildren && !mShowingPublic) {
1262 return mChildrenContainer.getMinExpandHeight(mOnKeyguard);
Selim Cinek83bc7832015-10-22 13:26:54 -07001263 }
Selim Cinek816c8e42015-11-19 12:00:45 -08001264 return getMinHeight();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001265 }
1266
1267 @Override
Jorim Jaggibe565df2014-04-28 17:51:23 +02001268 public void setClipTopAmount(int clipTopAmount) {
1269 super.setClipTopAmount(clipTopAmount);
1270 mPrivateLayout.setClipTopAmount(clipTopAmount);
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001271 mPublicLayout.setClipTopAmount(clipTopAmount);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001272 if (mGuts != null) {
1273 mGuts.setClipTopAmount(clipTopAmount);
1274 }
Jorim Jaggibe565df2014-04-28 17:51:23 +02001275 }
1276
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001277 private void recreateNotificationHeader() {
1278 final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
1279 getStatusBarNotification().getNotification());
1280 final RemoteViews header = builder.makeNotificationHeader();
1281 if (mNotificationHeader == null) {
1282 mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
1283 final View expandButton = mNotificationHeader.findViewById(
1284 com.android.internal.R.id.expand_button);
1285 expandButton.setVisibility(VISIBLE);
1286 mNotificationHeader.setOnClickListener(mExpandClickListener);
Selim Cinek9c7712d2015-12-08 19:19:48 -08001287 mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
1288 mNotificationHeader);
Selim Cinekb5a83612015-12-11 14:14:39 -08001289 addView(mNotificationHeader, indexOfChild(mChildrenContainer) + 1);
Mady Mellor4b80b102016-01-22 08:03:58 -08001290 mTranslateableViews.add(mNotificationHeader);
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001291 } else {
1292 header.reapply(getContext(), mNotificationHeader);
Selim Cinek4ffd6362015-12-29 15:12:23 +01001293 mNotificationHeaderWrapper.notifyContentUpdated(mEntry.notification);
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001294 }
Selim Cinekea4bef72015-12-02 15:51:10 -08001295 updateChildrenHeaderAppearance();
Selim Cinek343e6e22014-04-11 21:23:30 +02001296 }
Selim Cinek7d447722014-06-10 15:51:59 +02001297
Selim Cinekea4bef72015-12-02 15:51:10 -08001298 public void updateChildrenHeaderAppearance() {
1299 if (mIsSummaryWithChildren) {
1300 mHeaderUtil.updateChildrenHeaderAppearance();
1301 }
1302 }
1303
Selim Cinek31094df2014-08-14 19:28:15 +02001304 public boolean isMaxExpandHeightInitialized() {
1305 return mMaxExpandHeight != 0;
Selim Cinek7d447722014-06-10 15:51:59 +02001306 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001307
Selim Cinek42357e02016-02-24 18:48:01 -08001308 public NotificationContentView getShowingLayout() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001309 return mShowingPublic ? mPublicLayout : mPrivateLayout;
1310 }
Chris Wren78403d72014-07-28 10:23:24 +01001311
Jorim Jaggi59ec3042015-06-05 15:18:43 -07001312 @Override
1313 public void setShowingLegacyBackground(boolean showing) {
1314 super.setShowingLegacyBackground(showing);
1315 mPrivateLayout.setShowingLegacyBackground(showing);
1316 mPublicLayout.setShowingLegacyBackground(showing);
1317 }
1318
Selim Cineka6c6bfb2015-10-29 16:27:08 -07001319 @Override
1320 protected void updateBackgroundTint() {
1321 super.updateBackgroundTint();
1322 updateNoBackgroundState();
1323 if (mIsSummaryWithChildren) {
1324 List<ExpandableNotificationRow> notificationChildren =
1325 mChildrenContainer.getNotificationChildren();
1326 for (int i = 0; i < notificationChildren.size(); i++) {
1327 ExpandableNotificationRow child = notificationChildren.get(i);
1328 child.updateNoBackgroundState();
1329 }
1330 }
1331 }
1332
1333 private void updateNoBackgroundState() {
1334 mShowNoBackground = isChildInGroup() && hasSameBgColor(mNotificationParent);
1335 updateBackground();
1336 }
1337
Chris Wren78403d72014-07-28 10:23:24 +01001338 public void setExpansionLogger(ExpansionLogger logger, String key) {
1339 mLogger = logger;
1340 mLoggingKey = key;
1341 }
1342
Selim Cinek6183d122016-01-14 18:48:41 -08001343 @Override
Selim Cinek42357e02016-02-24 18:48:01 -08001344 public float getIncreasedPaddingAmount() {
1345 if (mIsSummaryWithChildren) {
1346 if (isGroupExpanded()) {
1347 return 1.0f;
1348 } else if (isUserLocked()) {
1349 return mChildrenContainer.getChildExpandFraction();
1350 }
1351 }
1352 return 0.0f;
Selim Cinek61633a82016-01-25 15:54:10 -08001353 }
1354
1355 @Override
Selim Cinek6183d122016-01-14 18:48:41 -08001356 protected boolean disallowSingleClick(MotionEvent event) {
1357 float x = event.getX();
1358 float y = event.getY();
Selim Cinek34eda5e2016-02-18 17:10:43 -08001359 NotificationHeaderView header = getVisibleNotificationHeader();
Selim Cinek6183d122016-01-14 18:48:41 -08001360 if (header != null) {
Mady Mellora8833512016-03-09 09:50:18 -08001361 return header.isInTouchRect(x - getTranslation(), y);
Selim Cinek6183d122016-01-14 18:48:41 -08001362 }
1363 return super.disallowSingleClick(event);
1364 }
1365
Chris Wren78403d72014-07-28 10:23:24 +01001366 private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
1367 final boolean nowExpanded = isExpanded();
1368 if (wasExpanded != nowExpanded && mLogger != null) {
1369 mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
1370 }
1371 }
Selim Cinek570981d2015-12-01 11:37:01 -08001372
1373 public interface OnExpandClickListener {
Selim Cinek31aada42015-12-18 17:51:15 -08001374 void onExpandClicked(NotificationData.Entry clickedEntry, boolean nowExpanded);
Selim Cinek570981d2015-12-01 11:37:01 -08001375 }
Chris Wren51c75102013-07-16 20:49:17 -04001376}