blob: 40446321cc5cd15861587c776f88fb472f70b2cf [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;
Mady Mellor3fd273e2016-03-15 21:08:14 -0700112 private String mAppName;
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();
231 }
Selim Cinek5a175d92015-11-23 18:01:33 -0800232 if (mIconAnimationRunning) {
233 setIconAnimationRunning(true);
234 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800235 if (mNotificationParent != null) {
236 mNotificationParent.updateChildrenHeaderAppearance();
237 }
Selim Cinek263398f2015-10-21 17:40:23 -0700238 onChildrenCountChanged();
Selim Cinek624c02db2015-12-14 21:00:02 -0800239 // The public layouts expand button is always visible
240 mPublicLayout.updateExpandButtons(true);
Selim Cinekda42d652015-12-04 15:51:16 -0800241 updateLimits();
242 }
243
244 private void updateLimits() {
Selim Cineka1744872016-03-11 15:36:06 -0800245 updateLimitsForView(mPrivateLayout);
246 updateLimitsForView(mPublicLayout);
247 }
248
249 private void updateLimitsForView(NotificationContentView layout) {
250 boolean customView = layout.getContractedChild().getId()
Selim Cinekda42d652015-12-04 15:51:16 -0800251 != com.android.internal.R.id.status_bar_latest_event_content;
252 boolean beforeN = mEntry.targetSdk < Build.VERSION_CODES.N;
253 int minHeight = customView && beforeN && !mIsSummaryWithChildren ?
254 mNotificationMinHeightLegacy : mNotificationMinHeight;
Selim Cineka1744872016-03-11 15:36:06 -0800255 boolean headsUpCustom = layout.getHeadsUpChild() != null &&
256 layout.getHeadsUpChild().getId()
257 != com.android.internal.R.id.status_bar_latest_event_content;
Selim Cinek77019c72015-12-09 10:18:02 -0800258 int headsUpheight = headsUpCustom && beforeN ? mMaxHeadsUpHeightLegacy
259 : mMaxHeadsUpHeight;
Selim Cineka1744872016-03-11 15:36:06 -0800260 layout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200261 }
262
263 public StatusBarNotification getStatusBarNotification() {
264 return mStatusBarNotification;
265 }
266
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700267 public boolean isHeadsUp() {
268 return mIsHeadsUp;
269 }
270
Selim Cinek1a521f32014-11-03 17:39:29 +0100271 public void setHeadsUp(boolean isHeadsUp) {
Selim Cinekc80fdb12015-04-13 15:09:08 -0700272 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek1a521f32014-11-03 17:39:29 +0100273 mIsHeadsUp = isHeadsUp;
Selim Cinek8d490d42015-04-10 00:05:50 -0700274 mPrivateLayout.setHeadsUp(isHeadsUp);
Selim Cinekc80fdb12015-04-13 15:09:08 -0700275 if (intrinsicBefore != getIntrinsicHeight()) {
276 notifyHeightChanged(false /* needsAnimation */);
277 }
Selim Cinek1a521f32014-11-03 17:39:29 +0100278 }
279
Selim Cinekb5605e52015-02-20 18:21:41 +0100280 public void setGroupManager(NotificationGroupManager groupManager) {
281 mGroupManager = groupManager;
Selim Cinek83bc7832015-10-22 13:26:54 -0700282 mPrivateLayout.setGroupManager(groupManager);
Selim Cinekb5605e52015-02-20 18:21:41 +0100283 }
284
Adrian Roosb88b1a12015-12-09 18:51:05 -0800285 public void setRemoteInputController(RemoteInputController r) {
286 mPrivateLayout.setRemoteInputController(r);
287 }
288
Mady Mellor3fd273e2016-03-15 21:08:14 -0700289 public void setAppName(String appName) {
290 mAppName = appName;
291 if (mSettingsIconRow != null) {
292 mSettingsIconRow.setAppName(mAppName);
293 }
294 }
295
Selim Cinekb5605e52015-02-20 18:21:41 +0100296 public void addChildNotification(ExpandableNotificationRow row) {
297 addChildNotification(row, -1);
298 }
299
300 /**
301 * Add a child notification to this view.
302 *
303 * @param row the row to add
304 * @param childIndex the index to add it at, if -1 it will be added at the end
305 */
306 public void addChildNotification(ExpandableNotificationRow row, int childIndex) {
307 if (mChildrenContainer == null) {
308 mChildrenContainerStub.inflate();
309 }
310 mChildrenContainer.addNotification(row, childIndex);
Selim Cinek263398f2015-10-21 17:40:23 -0700311 onChildrenCountChanged();
312 row.setIsChildInGroup(true, this);
Selim Cinekb5605e52015-02-20 18:21:41 +0100313 }
314
315 public void removeChildNotification(ExpandableNotificationRow row) {
316 if (mChildrenContainer != null) {
317 mChildrenContainer.removeNotification(row);
318 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800319 mHeaderUtil.restoreNotificationHeader(row);
Selim Cinek263398f2015-10-21 17:40:23 -0700320 onChildrenCountChanged();
321 row.setIsChildInGroup(false, null);
322 }
323
324 public boolean isChildInGroup() {
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700325 return mNotificationParent != null;
Selim Cinek263398f2015-10-21 17:40:23 -0700326 }
327
Selim Cinek388df6d2015-10-22 13:25:11 -0700328 public ExpandableNotificationRow getNotificationParent() {
329 return mNotificationParent;
330 }
331
Selim Cinek263398f2015-10-21 17:40:23 -0700332 /**
333 * @param isChildInGroup Is this notification now in a group
334 * @param parent the new parent notification
335 */
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700336 public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {;
337 boolean childInGroup = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
338 mNotificationParent = childInGroup ? parent : null;
339 mPrivateLayout.setIsChildInGroup(childInGroup);
340 updateNoBackgroundState();
Selim Cinek34d93b02015-10-22 12:30:38 -0700341 }
342
343 @Override
Selim Cinek72109472016-01-15 16:33:22 -0800344 public boolean onTouchEvent(MotionEvent event) {
345 if (event.getActionMasked() != MotionEvent.ACTION_DOWN
346 || !isChildInGroup() || isGroupExpanded()) {
347 return super.onTouchEvent(event);
348 } else {
349 return false;
350 }
351 }
352
353 @Override
Mady Mellorf0625802016-02-11 18:03:48 -0800354 protected boolean handleSlideBack() {
355 if (mSettingsIconRow != null && mSettingsIconRow.isVisible()) {
356 animateTranslateNotification(0 /* targetLeft */);
357 return true;
358 }
359 return false;
360 }
361
362 @Override
Selim Cinek34d93b02015-10-22 12:30:38 -0700363 protected boolean shouldHideBackground() {
364 return super.shouldHideBackground() || mShowNoBackground;
Selim Cinek263398f2015-10-21 17:40:23 -0700365 }
366
367 @Override
368 public boolean isSummaryWithChildren() {
369 return mIsSummaryWithChildren;
Selim Cinekb5605e52015-02-20 18:21:41 +0100370 }
371
372 @Override
373 public boolean areChildrenExpanded() {
374 return mChildrenExpanded;
375 }
376
377 public List<ExpandableNotificationRow> getNotificationChildren() {
378 return mChildrenContainer == null ? null : mChildrenContainer.getNotificationChildren();
379 }
380
Selim Cinekeef84282015-10-30 16:28:00 -0700381 public int getNumberOfNotificationChildren() {
382 if (mChildrenContainer == null) {
383 return 0;
384 }
385 return mChildrenContainer.getNotificationChildren().size();
386 }
387
Selim Cinekb5605e52015-02-20 18:21:41 +0100388 /**
389 * Apply the order given in the list to the children.
390 *
391 * @param childOrder the new list order
392 * @return whether the list order has changed
393 */
394 public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder) {
395 return mChildrenContainer != null && mChildrenContainer.applyChildOrder(childOrder);
396 }
397
398 public void getChildrenStates(StackScrollState resultState) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700399 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100400 StackViewState parentState = resultState.getViewStateForView(this);
401 mChildrenContainer.getState(resultState, parentState);
402 }
403 }
404
405 public void applyChildrenState(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700406 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100407 mChildrenContainer.applyState(state);
408 }
409 }
410
411 public void prepareExpansionChanged(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700412 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100413 mChildrenContainer.prepareExpansionChanged(state);
414 }
415 }
416
417 public void startChildAnimation(StackScrollState finalState,
Selim Cinek99695592016-01-12 17:51:35 -0800418 StackStateAnimator stateAnimator, long delay, long duration) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700419 if (mIsSummaryWithChildren) {
Selim Cinek99695592016-01-12 17:51:35 -0800420 mChildrenContainer.startAnimationToState(finalState, stateAnimator, delay,
Selim Cinekb5605e52015-02-20 18:21:41 +0100421 duration);
422 }
423 }
424
425 public ExpandableNotificationRow getViewAtPosition(float y) {
Selim Cinek43d30f02016-03-04 10:51:32 -0800426 if (!mIsSummaryWithChildren || !mChildrenExpanded) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100427 return this;
428 } else {
429 ExpandableNotificationRow view = mChildrenContainer.getViewAtPosition(y);
430 return view == null ? this : view;
431 }
432 }
433
Selim Cinekab29aeb2015-02-20 18:18:32 +0100434 public NotificationGuts getGuts() {
435 return mGuts;
436 }
437
Selim Cinek684a4422015-04-15 16:18:39 -0700438 /**
439 * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this
440 * the notification will be rendered on top of the screen.
441 *
442 * @param pinned whether it is pinned
443 */
444 public void setPinned(boolean pinned) {
445 mIsPinned = pinned;
Selim Cinek31aada42015-12-18 17:51:15 -0800446 if (pinned) {
447 setIconAnimationRunning(true);
448 mExpandedWhenPinned = false;
449 } else if (mExpandedWhenPinned) {
450 setUserExpanded(true);
451 }
Selim Cinek98713a42015-09-21 15:47:20 +0200452 setChronometerRunning(mLastChronometerRunning);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700453 }
454
Selim Cinek684a4422015-04-15 16:18:39 -0700455 public boolean isPinned() {
456 return mIsPinned;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700457 }
458
Selim Cinek31aada42015-12-18 17:51:15 -0800459 /**
460 * @param atLeastMinHeight should the value returned be at least the minimum height.
461 * Used to avoid cyclic calls
462 * @return the height of the heads up notification when pinned
463 */
464 public int getPinnedHeadsUpHeight(boolean atLeastMinHeight) {
Selim Cinek77019c72015-12-09 10:18:02 -0800465 if (mIsSummaryWithChildren) {
466 return mChildrenContainer.getIntrinsicHeight();
467 }
Selim Cinek31aada42015-12-18 17:51:15 -0800468 if(mExpandedWhenPinned) {
469 return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
470 } else if (atLeastMinHeight) {
471 return Math.max(getMinHeight(), mHeadsUpHeight);
472 } else {
473 return mHeadsUpHeight;
474 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700475 }
476
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700477 /**
478 * Mark whether this notification was just clicked, i.e. the user has just clicked this
479 * notification in this frame.
480 */
481 public void setJustClicked(boolean justClicked) {
482 mJustClicked = justClicked;
483 }
484
485 /**
486 * @return true if this notification has been clicked in this frame, false otherwise
487 */
488 public boolean wasJustClicked() {
489 return mJustClicked;
490 }
491
Selim Cinek98713a42015-09-21 15:47:20 +0200492 public void setChronometerRunning(boolean running) {
493 mLastChronometerRunning = running;
494 setChronometerRunning(running, mPrivateLayout);
495 setChronometerRunning(running, mPublicLayout);
496 if (mChildrenContainer != null) {
497 List<ExpandableNotificationRow> notificationChildren =
498 mChildrenContainer.getNotificationChildren();
499 for (int i = 0; i < notificationChildren.size(); i++) {
500 ExpandableNotificationRow child = notificationChildren.get(i);
501 child.setChronometerRunning(running);
502 }
503 }
504 }
505
506 private void setChronometerRunning(boolean running, NotificationContentView layout) {
507 if (layout != null) {
508 running = running || isPinned();
509 View contractedChild = layout.getContractedChild();
510 View expandedChild = layout.getExpandedChild();
511 View headsUpChild = layout.getHeadsUpChild();
512 setChronometerRunningForChild(running, contractedChild);
513 setChronometerRunningForChild(running, expandedChild);
514 setChronometerRunningForChild(running, headsUpChild);
515 }
516 }
517
518 private void setChronometerRunningForChild(boolean running, View child) {
519 if (child != null) {
520 View chronometer = child.findViewById(com.android.internal.R.id.chronometer);
521 if (chronometer instanceof Chronometer) {
522 ((Chronometer) chronometer).setStarted(running);
523 }
524 }
525 }
526
Selim Cinekea4bef72015-12-02 15:51:10 -0800527 public NotificationHeaderView getNotificationHeader() {
528 if (mNotificationHeader != null) {
529 return mNotificationHeader;
Selim Cinek8d6440d2015-10-22 13:00:05 -0700530 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800531 return mPrivateLayout.getNotificationHeader();
Selim Cinek8d6440d2015-10-22 13:00:05 -0700532 }
533
Selim Cinek34eda5e2016-02-18 17:10:43 -0800534 private NotificationHeaderView getVisibleNotificationHeader() {
535 if (mNotificationHeader != null) {
536 return mNotificationHeader;
537 }
538 return getShowingLayout().getVisibleNotificationHeader();
539 }
540
Selim Cinek570981d2015-12-01 11:37:01 -0800541 public void setOnExpandClickListener(OnExpandClickListener onExpandClickListener) {
542 mOnExpandClickListener = onExpandClickListener;
543 }
544
Selim Cinek31aada42015-12-18 17:51:15 -0800545 public void setHeadsUpManager(HeadsUpManager headsUpManager) {
546 mHeadsUpManager = headsUpManager;
547 }
548
Selim Cinek01af3342016-02-09 19:25:31 -0800549 public void reInflateViews() {
550 initDimens();
551 if (mIsSummaryWithChildren) {
552 removeView(mNotificationHeader);
553 mNotificationHeader = null;
554 recreateNotificationHeader();
555 if (mChildrenContainer != null) {
556 mChildrenContainer.reInflateViews();
557 }
558 }
559 if (mGuts != null) {
560 View oldGuts = mGuts;
561 int index = indexOfChild(oldGuts);
562 removeView(oldGuts);
563 mGuts = (NotificationGuts) LayoutInflater.from(mContext).inflate(
564 R.layout.notification_guts, this, false);
565 mGuts.setVisibility(oldGuts.getVisibility());
566 addView(mGuts, index);
567 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800568 if (mSettingsIconRow != null) {
569 View oldSettings = mSettingsIconRow;
570 int settingsIndex = indexOfChild(oldSettings);
571 removeView(oldSettings);
572 mSettingsIconRow = (NotificationSettingsIconRow) LayoutInflater.from(mContext).inflate(
573 R.layout.notification_settings_icon_row, this, false);
574 mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
Mady Mellor3fd273e2016-03-15 21:08:14 -0700575 mSettingsIconRow.setAppName(mAppName);
Mady Mellor4b80b102016-01-22 08:03:58 -0800576 mSettingsIconRow.setVisibility(oldSettings.getVisibility());
577 addView(mSettingsIconRow, settingsIndex);
578
579 }
Selim Cinekde33a4a2016-02-11 16:43:41 -0800580 mPrivateLayout.reInflateViews();
581 mPublicLayout.reInflateViews();
Selim Cinek01af3342016-02-09 19:25:31 -0800582 }
583
Selim Cinekc3179332016-03-04 14:44:56 -0800584 public void setContentBackground(int customBackgroundColor, boolean animate,
585 NotificationContentView notificationContentView) {
586 if (getShowingLayout() == notificationContentView) {
587 setTintColor(customBackgroundColor, animate);
588 }
589 }
590
Chris Wren78403d72014-07-28 10:23:24 +0100591 public interface ExpansionLogger {
592 public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
593 }
Selim Cinek1685e632014-04-08 02:27:49 +0200594
Chris Wren51c75102013-07-16 20:49:17 -0400595 public ExpandableNotificationRow(Context context, AttributeSet attrs) {
596 super(context, attrs);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700597 mFalsingManager = FalsingManager.getInstance(context);
Selim Cinek01af3342016-02-09 19:25:31 -0800598 initDimens();
599 }
600
601 private void initDimens() {
Selim Cinekf619ffc2016-02-17 14:53:05 -0800602 mNotificationMinHeightLegacy = getFontScaledHeight(R.dimen.notification_min_height_legacy);
603 mNotificationMinHeight = getFontScaledHeight(R.dimen.notification_min_height);
604 mNotificationMaxHeight = getFontScaledHeight(R.dimen.notification_max_height);
605 mMaxHeadsUpHeightLegacy = getFontScaledHeight(
Selim Cinek77019c72015-12-09 10:18:02 -0800606 R.dimen.notification_max_heads_up_height_legacy);
Selim Cinekf619ffc2016-02-17 14:53:05 -0800607 mMaxHeadsUpHeight = getFontScaledHeight(R.dimen.notification_max_heads_up_height);
608 }
609
610 /**
611 * @param dimenId the dimen to look up
612 * @return the font scaled dimen as if it were in sp but doesn't shrink sizes below dp
613 */
614 private int getFontScaledHeight(int dimenId) {
615 int dimensionPixelSize = getResources().getDimensionPixelSize(dimenId);
616 float factor = Math.max(1.0f, getResources().getDisplayMetrics().scaledDensity /
617 getResources().getDisplayMetrics().density);
618 return (int) (dimensionPixelSize * factor);
Chris Wren51c75102013-07-16 20:49:17 -0400619 }
620
Christoph Studera7fe6312014-06-27 19:32:44 +0200621 /**
622 * Resets this view so it can be re-used for an updated notification.
623 */
Christoph Studer22f2ee52014-07-29 22:57:21 +0200624 @Override
Christoph Studera7fe6312014-06-27 19:32:44 +0200625 public void reset() {
Christoph Studer22f2ee52014-07-29 22:57:21 +0200626 super.reset();
Chris Wren78403d72014-07-28 10:23:24 +0100627 final boolean wasExpanded = isExpanded();
Christoph Studera7fe6312014-06-27 19:32:44 +0200628 mExpandable = false;
629 mHasUserChangedExpansion = false;
630 mUserLocked = false;
631 mShowingPublic = false;
Jorim Jaggiae441282014-08-01 02:45:18 +0200632 mSensitive = false;
633 mShowingPublicInitialized = false;
Christoph Studera7fe6312014-06-27 19:32:44 +0200634 mIsSystemExpanded = false;
Selim Cinek83bc7832015-10-22 13:26:54 -0700635 mOnKeyguard = false;
Selim Cinek51d94912016-03-02 15:34:28 -0800636 mPublicLayout.reset();
637 mPrivateLayout.reset();
Selim Cinek31094df2014-08-14 19:28:15 +0200638 resetHeight();
Mady Mellor4b80b102016-01-22 08:03:58 -0800639 resetTranslation();
Selim Cinek31094df2014-08-14 19:28:15 +0200640 logExpansionEvent(false, wasExpanded);
641 }
642
643 public void resetHeight() {
Christoph Studera7fe6312014-06-27 19:32:44 +0200644 mMaxExpandHeight = 0;
Selim Cinek8d490d42015-04-10 00:05:50 -0700645 mHeadsUpHeight = 0;
Selim Cinek31094df2014-08-14 19:28:15 +0200646 onHeightReset();
Selim Cinek6e28a672014-09-05 14:43:28 +0200647 requestLayout();
Christoph Studera7fe6312014-06-27 19:32:44 +0200648 }
649
Jorim Jaggi251957d2014-04-09 04:24:09 +0200650 @Override
651 protected void onFinishInflate() {
652 super.onFinishInflate();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200653 mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800654 mPublicLayout.setContainingNotification(this);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200655 mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800656 mPrivateLayout.setExpandClickListener(mExpandClickListener);
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800657 mPrivateLayout.setContainingNotification(this);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800658 mPublicLayout.setExpandClickListener(mExpandClickListener);
Mady Mellor4b80b102016-01-22 08:03:58 -0800659 mSettingsIconRowStub = (ViewStub) findViewById(R.id.settings_icon_row_stub);
660 mSettingsIconRowStub.setOnInflateListener(new ViewStub.OnInflateListener() {
661 @Override
662 public void onInflate(ViewStub stub, View inflated) {
663 mSettingsIconRow = (NotificationSettingsIconRow) inflated;
664 mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
Mady Mellor3fd273e2016-03-15 21:08:14 -0700665 mSettingsIconRow.setAppName(mAppName);
Mady Mellor4b80b102016-01-22 08:03:58 -0800666 }
667 });
Selim Cinekab29aeb2015-02-20 18:18:32 +0100668 mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
669 mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200670 @Override
671 public void onInflate(ViewStub stub, View inflated) {
672 mGuts = (NotificationGuts) inflated;
673 mGuts.setClipTopAmount(getClipTopAmount());
674 mGuts.setActualHeight(getActualHeight());
Selim Cinekab29aeb2015-02-20 18:18:32 +0100675 mGutsStub = null;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200676 }
677 });
Selim Cinekb5605e52015-02-20 18:21:41 +0100678 mChildrenContainerStub = (ViewStub) findViewById(R.id.child_container_stub);
679 mChildrenContainerStub.setOnInflateListener(new ViewStub.OnInflateListener() {
680
681 @Override
682 public void onInflate(ViewStub stub, View inflated) {
683 mChildrenContainer = (NotificationChildrenContainer) inflated;
Selim Cinek388df6d2015-10-22 13:25:11 -0700684 mChildrenContainer.setNotificationParent(ExpandableNotificationRow.this);
Mady Mellor4b80b102016-01-22 08:03:58 -0800685 mTranslateableViews.add(mChildrenContainer);
Selim Cinekb5605e52015-02-20 18:21:41 +0100686 }
687 });
Selim Cinek863834b2014-05-20 04:20:25 +0200688 mVetoButton = findViewById(R.id.veto);
Mady Mellor4b80b102016-01-22 08:03:58 -0800689
690 // Add the views that we translate to reveal the gear
691 mTranslateableViews = new ArrayList<View>();
692 for (int i = 0; i < getChildCount(); i++) {
693 mTranslateableViews.add(getChildAt(i));
694 }
695 // Remove views that don't translate
696 mTranslateableViews.remove(mVetoButton);
697 mTranslateableViews.remove(mSettingsIconRowStub);
698 mTranslateableViews.remove(mChildrenContainerStub);
699 mTranslateableViews.remove(mGutsStub);
700 }
701
Mady Mellor34958fa2016-02-23 09:52:17 -0800702 private void setTranslationForOutline(float translationX) {
Mady Mellor4b80b102016-01-22 08:03:58 -0800703 setOutlineRect(false, translationX, getTop(), getRight() + translationX, getBottom());
704 }
705
706 public void resetTranslation() {
707 if (mTranslateableViews != null) {
708 for (int i = 0; i < mTranslateableViews.size(); i++) {
709 mTranslateableViews.get(i).setTranslationX(0);
710 }
711 setTranslationForOutline(0);
712 }
713 if (mSettingsIconRow != null) {
714 mSettingsIconRow.resetState();
715 }
716 }
717
718 public void animateTranslateNotification(final float leftTarget) {
719 if (mTranslateAnim != null) {
720 mTranslateAnim.cancel();
721 }
Mady Mellor34958fa2016-02-23 09:52:17 -0800722 mTranslateAnim = (AnimatorSet) getTranslateViewAnimator(leftTarget,
723 null /* updateListener */);
724 if (mTranslateAnim != null) {
725 mTranslateAnim.start();
726 }
727 }
728
729 @Override
730 public void setTranslation(float translationX) {
731 if (areGutsExposed()) {
732 // Don't translate if guts are showing.
733 return;
734 }
735 // Translate the group of views
736 for (int i = 0; i < mTranslateableViews.size(); i++) {
737 if (mTranslateableViews.get(i) != null) {
738 mTranslateableViews.get(i).setTranslationX(translationX);
739 }
740 }
741 setTranslationForOutline(translationX);
742 if (mSettingsIconRow != null) {
743 mSettingsIconRow.updateSettingsIcons(translationX, getMeasuredWidth());
744 }
745 }
746
747 @Override
748 public float getTranslation() {
749 if (mTranslateableViews != null && mTranslateableViews.size() > 0) {
750 // All of the views in the list should have same translation, just use first one.
751 return mTranslateableViews.get(0).getTranslationX();
752 }
753 return 0;
754 }
755
756 public Animator getTranslateViewAnimator(final float leftTarget,
757 AnimatorUpdateListener listener) {
758 if (areGutsExposed()) {
759 // No translation if guts are exposed.
760 return null;
761 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800762 AnimatorSet set = new AnimatorSet();
763 if (mTranslateableViews != null) {
764 for (int i = 0; i < mTranslateableViews.size(); i++) {
765 final View animView = mTranslateableViews.get(i);
766 final ObjectAnimator translateAnim = ObjectAnimator.ofFloat(
767 animView, "translationX", leftTarget);
768 if (i == 0) {
769 translateAnim.addUpdateListener(new AnimatorUpdateListener() {
770 @Override
771 public void onAnimationUpdate(ValueAnimator animation) {
772 setTranslationForOutline((float) animation.getAnimatedValue());
Mady Mellor34958fa2016-02-23 09:52:17 -0800773 if (mSettingsIconRow != null) {
774 mSettingsIconRow.updateSettingsIcons(
775 (float) animation.getAnimatedValue(), getMeasuredWidth());
776 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800777 }
778 });
Mady Mellor34958fa2016-02-23 09:52:17 -0800779 if (listener != null) {
780 translateAnim.addUpdateListener(listener);
781 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800782 }
783 translateAnim.addListener(new AnimatorListenerAdapter() {
784 @Override
785 public void onAnimationEnd(Animator anim) {
786 if (mSettingsIconRow != null && leftTarget == 0) {
787 mSettingsIconRow.resetState();
788 }
789 mTranslateAnim = null;
790 }
791 });
792 set.play(translateAnim);
793 }
794 }
Mady Mellor34958fa2016-02-23 09:52:17 -0800795 return set;
Mady Mellor4b80b102016-01-22 08:03:58 -0800796 }
797
798 public float getSpaceForGear() {
799 if (mSettingsIconRow != null) {
800 return mSettingsIconRow.getSpaceForGear();
801 }
802 return 0;
803 }
804
805 public NotificationSettingsIconRow getSettingsRow() {
806 if (mSettingsIconRow == null) {
807 mSettingsIconRowStub.inflate();
808 }
809 return mSettingsIconRow;
810 }
811
Selim Cinekab29aeb2015-02-20 18:18:32 +0100812 public void inflateGuts() {
813 if (mGuts == null) {
814 mGutsStub.inflate();
815 }
816 }
817
Selim Cinekda42d652015-12-04 15:51:16 -0800818 private void updateChildrenVisibility() {
Selim Cinekd84a5932015-12-15 11:45:36 -0800819 mPrivateLayout.setVisibility(!mShowingPublic && !mIsSummaryWithChildren ? VISIBLE
820 : INVISIBLE);
Selim Cinekef5127e2015-12-21 16:55:58 -0800821 if (mChildrenContainer != null) {
822 mChildrenContainer.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
823 : INVISIBLE);
Selim Cinekb5605e52015-02-20 18:21:41 +0100824 }
Selim Cinekef5127e2015-12-21 16:55:58 -0800825 if (mNotificationHeader != null) {
826 mNotificationHeader.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
827 : INVISIBLE);
828 }
Selim Cinekda42d652015-12-04 15:51:16 -0800829 // The limits might have changed if the view suddenly became a group or vice versa
830 updateLimits();
Selim Cinekb5605e52015-02-20 18:21:41 +0100831 }
832
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200833 @Override
Alan Viverettea54956a2015-01-07 16:05:02 -0800834 public boolean onRequestSendAccessibilityEventInternal(View child, AccessibilityEvent event) {
835 if (super.onRequestSendAccessibilityEventInternal(child, event)) {
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200836 // Add a record for the entire layout since its content is somehow small.
837 // The event comes from a leaf view that is interacted with.
838 AccessibilityEvent record = AccessibilityEvent.obtain();
839 onInitializeAccessibilityEvent(record);
840 dispatchPopulateAccessibilityEvent(record);
841 event.appendRecord(record);
842 return true;
843 }
844 return false;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200845 }
Chris Wren51c75102013-07-16 20:49:17 -0400846
John Spurlocke15452b2014-08-21 09:44:39 -0400847 @Override
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100848 public void setDark(boolean dark, boolean fade, long delay) {
849 super.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400850 final NotificationContentView showing = getShowingLayout();
851 if (showing != null) {
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100852 showing.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400853 }
Selim Cinek9c7712d2015-12-08 19:19:48 -0800854 if (mIsSummaryWithChildren) {
855 mChildrenContainer.setDark(dark, fade, delay);
856 mNotificationHeaderWrapper.setDark(dark, fade, delay);
857 }
John Spurlocke15452b2014-08-21 09:44:39 -0400858 }
859
Chris Wren51c75102013-07-16 20:49:17 -0400860 public boolean isExpandable() {
Selim Cinek388df6d2015-10-22 13:25:11 -0700861 if (mIsSummaryWithChildren && !mShowingPublic) {
862 return !mChildrenExpanded;
863 }
Chris Wren51c75102013-07-16 20:49:17 -0400864 return mExpandable;
865 }
866
867 public void setExpandable(boolean expandable) {
868 mExpandable = expandable;
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800869 mPrivateLayout.updateExpandButtons(isExpandable());
Chris Wren51c75102013-07-16 20:49:17 -0400870 }
871
Selim Cinek4ffd6362015-12-29 15:12:23 +0100872 @Override
873 public void setClipToActualHeight(boolean clipToActualHeight) {
Selim Cinek084c16b2016-01-22 17:48:22 -0800874 super.setClipToActualHeight(clipToActualHeight || isUserLocked());
875 getShowingLayout().setClipToActualHeight(clipToActualHeight || isUserLocked());
Selim Cinek4ffd6362015-12-29 15:12:23 +0100876 }
877
Selim Cinek1685e632014-04-08 02:27:49 +0200878 /**
879 * @return whether the user has changed the expansion state
880 */
881 public boolean hasUserChangedExpansion() {
882 return mHasUserChangedExpansion;
883 }
884
Chris Wren51c75102013-07-16 20:49:17 -0400885 public boolean isUserExpanded() {
886 return mUserExpanded;
887 }
888
Selim Cinek1685e632014-04-08 02:27:49 +0200889 /**
890 * Set this notification to be expanded by the user
891 *
892 * @param userExpanded whether the user wants this notification to be expanded
893 */
Chris Wren51c75102013-07-16 20:49:17 -0400894 public void setUserExpanded(boolean userExpanded) {
Selim Cinek388df6d2015-10-22 13:25:11 -0700895 setUserExpanded(userExpanded, false /* allowChildExpansion */);
896 }
897
898 /**
899 * Set this notification to be expanded by the user
900 *
901 * @param userExpanded whether the user wants this notification to be expanded
902 * @param allowChildExpansion whether a call to this method allows expanding children
903 */
904 public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700905 mFalsingManager.setNotificationExpanded();
Selim Cinek388df6d2015-10-22 13:25:11 -0700906 if (mIsSummaryWithChildren && !mShowingPublic && allowChildExpansion) {
907 mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
908 return;
909 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200910 if (userExpanded && !mExpandable) return;
Chris Wren78403d72014-07-28 10:23:24 +0100911 final boolean wasExpanded = isExpanded();
Selim Cinek1685e632014-04-08 02:27:49 +0200912 mHasUserChangedExpansion = true;
Chris Wren51c75102013-07-16 20:49:17 -0400913 mUserExpanded = userExpanded;
Chris Wren78403d72014-07-28 10:23:24 +0100914 logExpansionEvent(true, wasExpanded);
Chris Wren51c75102013-07-16 20:49:17 -0400915 }
916
Selim Cinekccd14fb2014-08-12 18:53:24 +0200917 public void resetUserExpansion() {
918 mHasUserChangedExpansion = false;
919 mUserExpanded = false;
920 }
921
Chris Wren51c75102013-07-16 20:49:17 -0400922 public boolean isUserLocked() {
923 return mUserLocked;
924 }
925
926 public void setUserLocked(boolean userLocked) {
927 mUserLocked = userLocked;
Selim Cinek8f2f6a62016-02-23 19:56:31 -0800928 mPrivateLayout.setUserExpanding(userLocked);
Selim Cinek42357e02016-02-24 18:48:01 -0800929 if (mIsSummaryWithChildren) {
930 mChildrenContainer.setUserLocked(userLocked);
931 }
Chris Wren51c75102013-07-16 20:49:17 -0400932 }
933
Selim Cinek1685e632014-04-08 02:27:49 +0200934 /**
935 * @return has the system set this notification to be expanded
936 */
937 public boolean isSystemExpanded() {
938 return mIsSystemExpanded;
939 }
940
941 /**
942 * Set this notification to be expanded by the system.
943 *
944 * @param expand whether the system wants this notification to be expanded.
945 */
946 public void setSystemExpanded(boolean expand) {
Selim Cinek31094df2014-08-14 19:28:15 +0200947 if (expand != mIsSystemExpanded) {
948 final boolean wasExpanded = isExpanded();
949 mIsSystemExpanded = expand;
Selim Cinekb5605e52015-02-20 18:21:41 +0100950 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200951 logExpansionEvent(false, wasExpanded);
Selim Cinek83bc7832015-10-22 13:26:54 -0700952 if (mChildrenContainer != null) {
953 mChildrenContainer.updateGroupOverflow();
954 }
Selim Cinek31094df2014-08-14 19:28:15 +0200955 }
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200956 }
957
958 /**
Selim Cinek83bc7832015-10-22 13:26:54 -0700959 * @param onKeyguard whether to prevent notification expansion
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200960 */
Selim Cinek83bc7832015-10-22 13:26:54 -0700961 public void setOnKeyguard(boolean onKeyguard) {
962 if (onKeyguard != mOnKeyguard) {
Selim Cinek31094df2014-08-14 19:28:15 +0200963 final boolean wasExpanded = isExpanded();
Selim Cinek83bc7832015-10-22 13:26:54 -0700964 mOnKeyguard = onKeyguard;
Selim Cinek31094df2014-08-14 19:28:15 +0200965 logExpansionEvent(false, wasExpanded);
966 if (wasExpanded != isExpanded()) {
Selim Cinek2108fe02015-12-10 12:56:13 -0800967 if (mIsSummaryWithChildren) {
968 mChildrenContainer.updateGroupOverflow();
969 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800970 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200971 }
972 }
Selim Cinek1685e632014-04-08 02:27:49 +0200973 }
974
975 /**
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400976 * @return Can the underlying notification be cleared?
977 */
978 public boolean isClearable() {
Selim Cineka37774f2014-11-11 19:16:18 +0100979 return mStatusBarNotification != null && mStatusBarNotification.isClearable();
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400980 }
981
Jorim Jaggi9cbadd32014-05-01 20:18:31 +0200982 @Override
983 public int getIntrinsicHeight() {
Jorim Jaggibe565df2014-04-28 17:51:23 +0200984 if (isUserLocked()) {
985 return getActualHeight();
986 }
Selim Cinekd84a5932015-12-15 11:45:36 -0800987 if (mGuts != null && mGuts.areGutsExposed()) {
988 return mGuts.getHeight();
989 } else if ((isChildInGroup() && !isGroupExpanded())) {
990 return mPrivateLayout.getMinHeight();
991 } else if (mSensitive && mHideSensitiveForIntrinsicHeight) {
992 return getMinHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -0700993 } else if (mIsSummaryWithChildren && !mOnKeyguard) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800994 return mChildrenContainer.getIntrinsicHeight();
Selim Cinek60122be2015-04-15 18:16:50 -0700995 } else if (mIsHeadsUp) {
Selim Cinek31aada42015-12-18 17:51:15 -0800996 if (isPinned()) {
997 return getPinnedHeadsUpHeight(true /* atLeastMinHeight */);
998 } else if (isExpanded()) {
Selim Cinekd84a5932015-12-15 11:45:36 -0800999 return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -07001000 } else {
Selim Cinekd84a5932015-12-15 11:45:36 -08001001 return Math.max(getMinHeight(), mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -07001002 }
Selim Cinek31aada42015-12-18 17:51:15 -08001003 } else if (isExpanded()) {
Selim Cinek83bc7832015-10-22 13:26:54 -07001004 return getMaxExpandHeight();
Selim Cinekd84a5932015-12-15 11:45:36 -08001005 } else {
1006 return getMinHeight();
Selim Cinek1685e632014-04-08 02:27:49 +02001007 }
Selim Cinekb5605e52015-02-20 18:21:41 +01001008 }
Selim Cinek1685e632014-04-08 02:27:49 +02001009
Selim Cinekeef84282015-10-30 16:28:00 -07001010 private boolean isGroupExpanded() {
1011 return mGroupManager.isGroupExpanded(mStatusBarNotification);
Selim Cinekb5605e52015-02-20 18:21:41 +01001012 }
1013
Selim Cinekeef84282015-10-30 16:28:00 -07001014 /**
1015 * @return whether this view has a header on the top of the content
1016 */
1017 private boolean hasNotificationHeader() {
1018 return mIsSummaryWithChildren;
Selim Cinek1685e632014-04-08 02:27:49 +02001019 }
1020
Selim Cinek263398f2015-10-21 17:40:23 -07001021 private void onChildrenCountChanged() {
Selim Cinek8fc93c92015-11-23 17:48:07 -08001022 mIsSummaryWithChildren = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS
Selim Cinek263398f2015-10-21 17:40:23 -07001023 && mGroupManager.hasGroupChildren(mStatusBarNotification);
Selim Cinek8fc93c92015-11-23 17:48:07 -08001024 if (mIsSummaryWithChildren) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001025 if (mChildrenContainer == null) {
1026 mChildrenContainerStub.inflate();
1027 }
Selim Cinek8fc93c92015-11-23 17:48:07 -08001028 if (mNotificationHeader == null) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001029 recreateNotificationHeader();
1030 }
Selim Cinek263398f2015-10-21 17:40:23 -07001031 }
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001032 mPrivateLayout.updateExpandButtons(isExpandable());
Selim Cinekea4bef72015-12-02 15:51:10 -08001033 updateChildrenHeaderAppearance();
Selim Cinekda42d652015-12-04 15:51:16 -08001034 updateChildrenVisibility();
Selim Cinek263398f2015-10-21 17:40:23 -07001035 }
1036
Selim Cinek1685e632014-04-08 02:27:49 +02001037 /**
1038 * Check whether the view state is currently expanded. This is given by the system in {@link
1039 * #setSystemExpanded(boolean)} and can be overridden by user expansion or
1040 * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
1041 * view can differ from this state, if layout params are modified from outside.
1042 *
1043 * @return whether the view state is currently expanded.
1044 */
Selim Cinek83bc7832015-10-22 13:26:54 -07001045 public boolean isExpanded() {
Selim Cineke81b82b2016-03-04 11:22:28 -08001046 return isExpanded(false /* allowOnKeyguard */);
1047 }
1048
1049 public boolean isExpanded(boolean allowOnKeyguard) {
1050 return (!mOnKeyguard || allowOnKeyguard)
Selim Cinekb5605e52015-02-20 18:21:41 +01001051 && (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded())
1052 || isUserExpanded());
1053 }
1054
1055 private boolean isSystemChildExpanded() {
1056 return mIsSystemChildExpanded;
1057 }
1058
1059 public void setSystemChildExpanded(boolean expanded) {
1060 mIsSystemChildExpanded = expanded;
Selim Cinek1685e632014-04-08 02:27:49 +02001061 }
1062
1063 @Override
1064 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
1065 super.onLayout(changed, left, top, right, bottom);
Selim Cinek8d490d42015-04-10 00:05:50 -07001066 updateMaxHeights();
Selim Cinek1685e632014-04-08 02:27:49 +02001067 }
1068
Selim Cinek8d490d42015-04-10 00:05:50 -07001069 private void updateMaxHeights() {
Selim Cinekd2319fb2014-09-01 19:41:54 +02001070 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek8d490d42015-04-10 00:05:50 -07001071 View expandedChild = mPrivateLayout.getExpandedChild();
1072 if (expandedChild == null) {
1073 expandedChild = mPrivateLayout.getContractedChild();
1074 }
1075 mMaxExpandHeight = expandedChild.getHeight();
1076 View headsUpChild = mPrivateLayout.getHeadsUpChild();
Selim Cinek1f3f5442015-04-10 17:54:46 -07001077 if (headsUpChild == null) {
1078 headsUpChild = mPrivateLayout.getContractedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -07001079 }
Selim Cinek1f3f5442015-04-10 17:54:46 -07001080 mHeadsUpHeight = headsUpChild.getHeight();
Selim Cinekd2319fb2014-09-01 19:41:54 +02001081 if (intrinsicBefore != getIntrinsicHeight()) {
Selim Cinekb5605e52015-02-20 18:21:41 +01001082 notifyHeightChanged(false /* needsAnimation */);
Selim Cinekd2319fb2014-09-01 19:41:54 +02001083 }
1084 }
1085
Selim Cinekfa0a2d32016-01-14 13:02:21 -08001086 @Override
1087 public void notifyHeightChanged(boolean needsAnimation) {
1088 super.notifyHeightChanged(needsAnimation);
1089 getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked());
1090 }
1091
Selim Cinek3c76d502016-02-19 15:16:33 -08001092 public void setSensitive(boolean sensitive, boolean hideSensitive) {
Jorim Jaggiae441282014-08-01 02:45:18 +02001093 mSensitive = sensitive;
Selim Cinek3c76d502016-02-19 15:16:33 -08001094 mSensitiveHiddenInGeneral = hideSensitive;
Jorim Jaggiae441282014-08-01 02:45:18 +02001095 }
1096
1097 public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
Selim Cinek60122be2015-04-15 18:16:50 -07001098 mHideSensitiveForIntrinsicHeight = hideSensitive;
Selim Cineka52f6a12016-02-29 15:35:58 -08001099 if (mIsSummaryWithChildren) {
1100 List<ExpandableNotificationRow> notificationChildren =
1101 mChildrenContainer.getNotificationChildren();
1102 for (int i = 0; i < notificationChildren.size(); i++) {
1103 ExpandableNotificationRow child = notificationChildren.get(i);
1104 child.setHideSensitiveForIntrinsicHeight(hideSensitive);
1105 }
1106 }
Jorim Jaggiae441282014-08-01 02:45:18 +02001107 }
1108
1109 public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
1110 long duration) {
1111 boolean oldShowingPublic = mShowingPublic;
1112 mShowingPublic = mSensitive && hideSensitive;
1113 if (mShowingPublicInitialized && mShowingPublic == oldShowingPublic) {
1114 return;
1115 }
Dan Sandlera5e0f412014-01-23 15:11:54 -05001116
1117 // bail out if no public version
Selim Cinek1685e632014-04-08 02:27:49 +02001118 if (mPublicLayout.getChildCount() == 0) return;
Dan Sandlera5e0f412014-01-23 15:11:54 -05001119
Jorim Jaggiae441282014-08-01 02:45:18 +02001120 if (!animated) {
1121 mPublicLayout.animate().cancel();
1122 mPrivateLayout.animate().cancel();
1123 mPublicLayout.setAlpha(1f);
1124 mPrivateLayout.setAlpha(1f);
1125 mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
Selim Cinekd84a5932015-12-15 11:45:36 -08001126 updateChildrenVisibility();
Jorim Jaggiae441282014-08-01 02:45:18 +02001127 } else {
1128 animateShowingPublic(delay, duration);
1129 }
Selim Cinekc3179332016-03-04 14:44:56 -08001130 NotificationContentView showingLayout = getShowingLayout();
1131 showingLayout.updateBackgroundColor(animated);
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001132 mPrivateLayout.updateExpandButtons(isExpandable());
Selim Cinek757d8792016-01-28 16:21:08 -08001133 updateClearability();
Jorim Jaggiae441282014-08-01 02:45:18 +02001134 mShowingPublicInitialized = true;
1135 }
1136
1137 private void animateShowingPublic(long delay, long duration) {
Selim Cinekd84a5932015-12-15 11:45:36 -08001138 View[] privateViews = mIsSummaryWithChildren ?
1139 new View[] {mChildrenContainer, mNotificationHeader}
1140 : new View[] {mPrivateLayout};
1141 View[] publicViews = new View[] {mPublicLayout};
1142 View[] hiddenChildren = mShowingPublic ? privateViews : publicViews;
1143 View[] shownChildren = mShowingPublic ? publicViews : privateViews;
1144 for (final View hiddenView : hiddenChildren) {
1145 hiddenView.setVisibility(View.VISIBLE);
1146 hiddenView.animate().cancel();
1147 hiddenView.animate()
1148 .alpha(0f)
1149 .setStartDelay(delay)
1150 .setDuration(duration)
1151 .withEndAction(new Runnable() {
1152 @Override
1153 public void run() {
1154 hiddenView.setVisibility(View.INVISIBLE);
1155 }
1156 });
1157 }
1158 for (View showView : shownChildren) {
1159 showView.setVisibility(View.VISIBLE);
1160 showView.setAlpha(0f);
1161 showView.animate().cancel();
1162 showView.animate()
1163 .alpha(1f)
1164 .setStartDelay(delay)
1165 .setDuration(duration);
1166 }
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001167 }
1168
Selim Cinek3776fe02016-02-04 13:32:43 -08001169 public boolean mustStayOnScreen() {
1170 return mIsHeadsUp;
1171 }
1172
Selim Cinek757d8792016-01-28 16:21:08 -08001173 private void updateClearability() {
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001174 // public versions cannot be dismissed
Selim Cinek3c76d502016-02-19 15:16:33 -08001175 mVetoButton.setVisibility(isClearable() && (!mShowingPublic
1176 || !mSensitiveHiddenInGeneral) ? View.VISIBLE : View.GONE);
Dan Sandlera5e0f412014-01-23 15:11:54 -05001177 }
Jorim Jaggi251957d2014-04-09 04:24:09 +02001178
Selim Cinekb5605e52015-02-20 18:21:41 +01001179 public void setChildrenExpanded(boolean expanded, boolean animate) {
1180 mChildrenExpanded = expanded;
Selim Cinek7b836392015-12-04 20:02:59 -08001181 if (mNotificationHeader != null) {
1182 mNotificationHeader.setExpanded(expanded);
1183 }
Selim Cinek83bc7832015-10-22 13:26:54 -07001184 if (mChildrenContainer != null) {
1185 mChildrenContainer.setChildrenExpanded(expanded);
1186 }
Selim Cinekb5605e52015-02-20 18:21:41 +01001187 }
1188
Selim Cinekb5605e52015-02-20 18:21:41 +01001189 public static void applyTint(View v, int color) {
1190 int alpha;
1191 if (color != 0) {
1192 alpha = COLORED_DIVIDER_ALPHA;
1193 } else {
1194 color = 0xff000000;
1195 alpha = DEFAULT_DIVIDER_ALPHA;
1196 }
1197 if (v.getBackground() instanceof ColorDrawable) {
1198 ColorDrawable background = (ColorDrawable) v.getBackground();
1199 background.mutate();
1200 background.setColor(color);
1201 background.setAlpha(alpha);
1202 }
1203 }
1204
Selim Cinek1685e632014-04-08 02:27:49 +02001205 public int getMaxExpandHeight() {
Selim Cinekb5605e52015-02-20 18:21:41 +01001206 return mMaxExpandHeight;
Chris Wren51c75102013-07-16 20:49:17 -04001207 }
Jorim Jaggi584a7aa2014-04-10 23:26:13 +02001208
Mady Mellor34958fa2016-02-23 09:52:17 -08001209 public boolean areGutsExposed() {
1210 return (mGuts != null && mGuts.areGutsExposed());
1211 }
1212
Jorim Jaggibe565df2014-04-28 17:51:23 +02001213 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001214 public boolean isContentExpandable() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001215 NotificationContentView showingLayout = getShowingLayout();
1216 return showingLayout.isContentExpandable();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001217 }
1218
1219 @Override
Selim Cinek560e64d2015-06-09 19:58:11 -07001220 protected View getContentView() {
1221 return getShowingLayout();
1222 }
1223
1224 @Override
Jorim Jaggid552d9d2014-05-07 19:41:13 +02001225 public void setActualHeight(int height, boolean notifyListeners) {
Selim Cinekb5605e52015-02-20 18:21:41 +01001226 super.setActualHeight(height, notifyListeners);
Mady Mellorb53bc272016-02-11 18:28:23 -08001227 if (mGuts != null && mGuts.areGutsExposed()) {
1228 mGuts.setActualHeight(height);
1229 return;
1230 }
Selim Cinekeef84282015-10-30 16:28:00 -07001231 int contentHeight = Math.max(getMinHeight(), height);
Selim Cinekb5605e52015-02-20 18:21:41 +01001232 mPrivateLayout.setContentHeight(contentHeight);
1233 mPublicLayout.setContentHeight(contentHeight);
Selim Cinek42357e02016-02-24 18:48:01 -08001234 if (mIsSummaryWithChildren) {
1235 mChildrenContainer.setActualHeight(height);
1236 }
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001237 if (mGuts != null) {
1238 mGuts.setActualHeight(height);
1239 }
Jorim Jaggibe565df2014-04-28 17:51:23 +02001240 }
1241
1242 @Override
Selim Cinekb5605e52015-02-20 18:21:41 +01001243 public int getMaxContentHeight() {
Selim Cinek83bc7832015-10-22 13:26:54 -07001244 if (mIsSummaryWithChildren && !mShowingPublic) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001245 return mChildrenContainer.getMaxContentHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -07001246 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001247 NotificationContentView showingLayout = getShowingLayout();
1248 return showingLayout.getMaxHeight();
Jorim Jaggibe565df2014-04-28 17:51:23 +02001249 }
1250
1251 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001252 public int getMinHeight() {
Selim Cinek31aada42015-12-18 17:51:15 -08001253 if (mIsHeadsUp && mHeadsUpManager.isTrackingHeadsUp()) {
1254 return getPinnedHeadsUpHeight(false /* atLeastMinHeight */);
1255 } else if (mIsSummaryWithChildren && !isGroupExpanded() && !mShowingPublic) {
Selim Cinekb55386d2015-12-16 17:26:49 -08001256 return mChildrenContainer.getMinHeight();
Selim Cinek31aada42015-12-18 17:51:15 -08001257 } else if (mIsHeadsUp) {
1258 return mHeadsUpHeight;
Selim Cinekb55386d2015-12-16 17:26:49 -08001259 }
Selim Cinek816c8e42015-11-19 12:00:45 -08001260 NotificationContentView showingLayout = getShowingLayout();
1261 return showingLayout.getMinHeight();
1262 }
1263
1264 @Override
1265 public int getMinExpandHeight() {
Selim Cinek2c584612016-02-29 16:14:25 -08001266 if (mIsSummaryWithChildren && !mShowingPublic) {
1267 return mChildrenContainer.getMinExpandHeight(mOnKeyguard);
Selim Cinek83bc7832015-10-22 13:26:54 -07001268 }
Selim Cinek816c8e42015-11-19 12:00:45 -08001269 return getMinHeight();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001270 }
1271
1272 @Override
Jorim Jaggibe565df2014-04-28 17:51:23 +02001273 public void setClipTopAmount(int clipTopAmount) {
1274 super.setClipTopAmount(clipTopAmount);
1275 mPrivateLayout.setClipTopAmount(clipTopAmount);
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001276 mPublicLayout.setClipTopAmount(clipTopAmount);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001277 if (mGuts != null) {
1278 mGuts.setClipTopAmount(clipTopAmount);
1279 }
Jorim Jaggibe565df2014-04-28 17:51:23 +02001280 }
1281
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001282 private void recreateNotificationHeader() {
1283 final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
1284 getStatusBarNotification().getNotification());
1285 final RemoteViews header = builder.makeNotificationHeader();
1286 if (mNotificationHeader == null) {
1287 mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
1288 final View expandButton = mNotificationHeader.findViewById(
1289 com.android.internal.R.id.expand_button);
1290 expandButton.setVisibility(VISIBLE);
1291 mNotificationHeader.setOnClickListener(mExpandClickListener);
Selim Cinek9c7712d2015-12-08 19:19:48 -08001292 mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
1293 mNotificationHeader);
Selim Cinekb5a83612015-12-11 14:14:39 -08001294 addView(mNotificationHeader, indexOfChild(mChildrenContainer) + 1);
Mady Mellor4b80b102016-01-22 08:03:58 -08001295 mTranslateableViews.add(mNotificationHeader);
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001296 } else {
1297 header.reapply(getContext(), mNotificationHeader);
Selim Cinek4ffd6362015-12-29 15:12:23 +01001298 mNotificationHeaderWrapper.notifyContentUpdated(mEntry.notification);
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001299 }
Selim Cinekea4bef72015-12-02 15:51:10 -08001300 updateChildrenHeaderAppearance();
Selim Cinek343e6e22014-04-11 21:23:30 +02001301 }
Selim Cinek7d447722014-06-10 15:51:59 +02001302
Selim Cinekea4bef72015-12-02 15:51:10 -08001303 public void updateChildrenHeaderAppearance() {
1304 if (mIsSummaryWithChildren) {
1305 mHeaderUtil.updateChildrenHeaderAppearance();
1306 }
1307 }
1308
Selim Cinek31094df2014-08-14 19:28:15 +02001309 public boolean isMaxExpandHeightInitialized() {
1310 return mMaxExpandHeight != 0;
Selim Cinek7d447722014-06-10 15:51:59 +02001311 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001312
Selim Cinek42357e02016-02-24 18:48:01 -08001313 public NotificationContentView getShowingLayout() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001314 return mShowingPublic ? mPublicLayout : mPrivateLayout;
1315 }
Chris Wren78403d72014-07-28 10:23:24 +01001316
Jorim Jaggi59ec3042015-06-05 15:18:43 -07001317 @Override
1318 public void setShowingLegacyBackground(boolean showing) {
1319 super.setShowingLegacyBackground(showing);
1320 mPrivateLayout.setShowingLegacyBackground(showing);
1321 mPublicLayout.setShowingLegacyBackground(showing);
1322 }
1323
Selim Cineka6c6bfb2015-10-29 16:27:08 -07001324 @Override
1325 protected void updateBackgroundTint() {
1326 super.updateBackgroundTint();
1327 updateNoBackgroundState();
1328 if (mIsSummaryWithChildren) {
1329 List<ExpandableNotificationRow> notificationChildren =
1330 mChildrenContainer.getNotificationChildren();
1331 for (int i = 0; i < notificationChildren.size(); i++) {
1332 ExpandableNotificationRow child = notificationChildren.get(i);
1333 child.updateNoBackgroundState();
1334 }
1335 }
1336 }
1337
1338 private void updateNoBackgroundState() {
1339 mShowNoBackground = isChildInGroup() && hasSameBgColor(mNotificationParent);
1340 updateBackground();
1341 }
1342
Chris Wren78403d72014-07-28 10:23:24 +01001343 public void setExpansionLogger(ExpansionLogger logger, String key) {
1344 mLogger = logger;
1345 mLoggingKey = key;
1346 }
1347
Selim Cinek6183d122016-01-14 18:48:41 -08001348 @Override
Selim Cinek42357e02016-02-24 18:48:01 -08001349 public float getIncreasedPaddingAmount() {
1350 if (mIsSummaryWithChildren) {
1351 if (isGroupExpanded()) {
1352 return 1.0f;
1353 } else if (isUserLocked()) {
1354 return mChildrenContainer.getChildExpandFraction();
1355 }
1356 }
1357 return 0.0f;
Selim Cinek61633a82016-01-25 15:54:10 -08001358 }
1359
1360 @Override
Selim Cinek6183d122016-01-14 18:48:41 -08001361 protected boolean disallowSingleClick(MotionEvent event) {
1362 float x = event.getX();
1363 float y = event.getY();
Selim Cinek34eda5e2016-02-18 17:10:43 -08001364 NotificationHeaderView header = getVisibleNotificationHeader();
Selim Cinek6183d122016-01-14 18:48:41 -08001365 if (header != null) {
Mady Mellora8833512016-03-09 09:50:18 -08001366 return header.isInTouchRect(x - getTranslation(), y);
Selim Cinek6183d122016-01-14 18:48:41 -08001367 }
1368 return super.disallowSingleClick(event);
1369 }
1370
Chris Wren78403d72014-07-28 10:23:24 +01001371 private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
1372 final boolean nowExpanded = isExpanded();
1373 if (wasExpanded != nowExpanded && mLogger != null) {
1374 mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
1375 }
1376 }
Selim Cinek570981d2015-12-01 11:37:01 -08001377
1378 public interface OnExpandClickListener {
Selim Cinek31aada42015-12-18 17:51:15 -08001379 void onExpandClicked(NotificationData.Entry clickedEntry, boolean nowExpanded);
Selim Cinek570981d2015-12-01 11:37:01 -08001380 }
Chris Wren51c75102013-07-16 20:49:17 -04001381}