blob: f446593e6cb46aa0b977744c4575d4cd19e3b6d8 [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;
Selim Cineka5e211b2014-08-11 17:35:48 +0200108 private boolean mWasReset;
Mady Mellor4b80b102016-01-22 08:03:58 -0800109 private NotificationSettingsIconRow mSettingsIconRow;
Selim Cinek8d490d42015-04-10 00:05:50 -0700110 private NotificationGuts mGuts;
Selim Cinekda42d652015-12-04 15:51:16 -0800111 private NotificationData.Entry mEntry;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200112 private StatusBarNotification mStatusBarNotification;
Selim Cinek1a521f32014-11-03 17:39:29 +0100113 private boolean mIsHeadsUp;
Selim Cinek98713a42015-09-21 15:47:20 +0200114 private boolean mLastChronometerRunning = true;
Selim Cinekeef84282015-10-30 16:28:00 -0700115 private NotificationHeaderView mNotificationHeader;
Selim Cinek9c7712d2015-12-08 19:19:48 -0800116 private NotificationViewWrapper mNotificationHeaderWrapper;
Selim Cinekb5605e52015-02-20 18:21:41 +0100117 private ViewStub mChildrenContainerStub;
118 private NotificationGroupManager mGroupManager;
Selim Cinekb5605e52015-02-20 18:21:41 +0100119 private boolean mChildrenExpanded;
Selim Cinek263398f2015-10-21 17:40:23 -0700120 private boolean mIsSummaryWithChildren;
Selim Cinekb5605e52015-02-20 18:21:41 +0100121 private NotificationChildrenContainer mChildrenContainer;
Mady Mellor4b80b102016-01-22 08:03:58 -0800122 private ViewStub mSettingsIconRowStub;
Selim Cinekab29aeb2015-02-20 18:18:32 +0100123 private ViewStub mGutsStub;
Selim Cinekb5605e52015-02-20 18:21:41 +0100124 private boolean mIsSystemChildExpanded;
Selim Cinek684a4422015-04-15 16:18:39 -0700125 private boolean mIsPinned;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700126 private FalsingManager mFalsingManager;
Selim Cinek31aada42015-12-18 17:51:15 -0800127 private HeadsUpManager mHeadsUpManager;
Selim Cinekea4bef72015-12-02 15:51:10 -0800128 private NotificationHeaderUtil mHeaderUtil = new NotificationHeaderUtil(this);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200129
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700130 private boolean mJustClicked;
Selim Cinek5a175d92015-11-23 18:01:33 -0800131 private boolean mIconAnimationRunning;
Selim Cinek34d93b02015-10-22 12:30:38 -0700132 private boolean mShowNoBackground;
Selim Cinek388df6d2015-10-22 13:25:11 -0700133 private ExpandableNotificationRow mNotificationParent;
Selim Cinek570981d2015-12-01 11:37:01 -0800134 private OnExpandClickListener mOnExpandClickListener;
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800135 private OnClickListener mExpandClickListener = new OnClickListener() {
136 @Override
137 public void onClick(View v) {
Selim Cinek624c02db2015-12-14 21:00:02 -0800138 if (!mShowingPublic && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800139 mGroupManager.toggleGroupExpansion(mStatusBarNotification);
Selim Cinek31aada42015-12-18 17:51:15 -0800140 mOnExpandClickListener.onExpandClicked(mEntry,
Selim Cinek570981d2015-12-01 11:37:01 -0800141 mGroupManager.isGroupExpanded(mStatusBarNotification));
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800142 } else {
Selim Cinek31aada42015-12-18 17:51:15 -0800143 boolean nowExpanded;
144 if (isPinned()) {
145 nowExpanded = !mExpandedWhenPinned;
146 mExpandedWhenPinned = nowExpanded;
147 } else {
148 nowExpanded = !isExpanded();
149 setUserExpanded(nowExpanded);
150 }
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800151 notifyHeightChanged(true);
Selim Cinek31aada42015-12-18 17:51:15 -0800152 mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800153 }
154 }
155 };
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700156
Selim Cinek8d490d42015-04-10 00:05:50 -0700157 public NotificationContentView getPrivateLayout() {
158 return mPrivateLayout;
159 }
160
161 public NotificationContentView getPublicLayout() {
162 return mPublicLayout;
163 }
164
Selim Cinekcab4a602014-09-03 14:47:57 +0200165 public void setIconAnimationRunning(boolean running) {
166 setIconAnimationRunning(running, mPublicLayout);
167 setIconAnimationRunning(running, mPrivateLayout);
Selim Cinek5a175d92015-11-23 18:01:33 -0800168 setIconAnimationRunningForChild(running, mNotificationHeader);
169 if (mIsSummaryWithChildren) {
170 List<ExpandableNotificationRow> notificationChildren =
171 mChildrenContainer.getNotificationChildren();
172 for (int i = 0; i < notificationChildren.size(); i++) {
173 ExpandableNotificationRow child = notificationChildren.get(i);
174 child.setIconAnimationRunning(running);
175 }
176 }
177 mIconAnimationRunning = running;
Selim Cinekcab4a602014-09-03 14:47:57 +0200178 }
179
180 private void setIconAnimationRunning(boolean running, NotificationContentView layout) {
181 if (layout != null) {
182 View contractedChild = layout.getContractedChild();
183 View expandedChild = layout.getExpandedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -0700184 View headsUpChild = layout.getHeadsUpChild();
Selim Cinekcab4a602014-09-03 14:47:57 +0200185 setIconAnimationRunningForChild(running, contractedChild);
186 setIconAnimationRunningForChild(running, expandedChild);
Selim Cinek8d490d42015-04-10 00:05:50 -0700187 setIconAnimationRunningForChild(running, headsUpChild);
Selim Cinekcab4a602014-09-03 14:47:57 +0200188 }
189 }
190
191 private void setIconAnimationRunningForChild(boolean running, View child) {
192 if (child != null) {
193 ImageView icon = (ImageView) child.findViewById(com.android.internal.R.id.icon);
194 setIconRunning(icon, running);
195 ImageView rightIcon = (ImageView) child.findViewById(
196 com.android.internal.R.id.right_icon);
197 setIconRunning(rightIcon, running);
198 }
199 }
200
201 private void setIconRunning(ImageView imageView, boolean running) {
202 if (imageView != null) {
203 Drawable drawable = imageView.getDrawable();
204 if (drawable instanceof AnimationDrawable) {
205 AnimationDrawable animationDrawable = (AnimationDrawable) drawable;
206 if (running) {
207 animationDrawable.start();
208 } else {
209 animationDrawable.stop();
210 }
211 } else if (drawable instanceof AnimatedVectorDrawable) {
212 AnimatedVectorDrawable animationDrawable = (AnimatedVectorDrawable) drawable;
213 if (running) {
214 animationDrawable.start();
215 } else {
216 animationDrawable.stop();
217 }
218 }
219 }
220 }
221
Selim Cinekda42d652015-12-04 15:51:16 -0800222 public void onNotificationUpdated(NotificationData.Entry entry) {
223 mEntry = entry;
224 mStatusBarNotification = entry.notification;
Adrian Roosb88b1a12015-12-09 18:51:05 -0800225 mPrivateLayout.onNotificationUpdated(entry);
226 mPublicLayout.onNotificationUpdated(entry);
Selim Cinek757d8792016-01-28 16:21:08 -0800227 mShowingPublicInitialized = false;
228 updateClearability();
Selim Cinek8fc93c92015-11-23 17:48:07 -0800229 if (mIsSummaryWithChildren) {
230 recreateNotificationHeader();
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() {
245 boolean customView = getPrivateLayout().getContractedChild().getId()
246 != com.android.internal.R.id.status_bar_latest_event_content;
247 boolean beforeN = mEntry.targetSdk < Build.VERSION_CODES.N;
248 int minHeight = customView && beforeN && !mIsSummaryWithChildren ?
249 mNotificationMinHeightLegacy : mNotificationMinHeight;
Selim Cinek77019c72015-12-09 10:18:02 -0800250 boolean headsUpCustom = getPrivateLayout().getHeadsUpChild() != null &&
251 getPrivateLayout().getHeadsUpChild().getId()
252 != com.android.internal.R.id.status_bar_latest_event_content;
253 int headsUpheight = headsUpCustom && beforeN ? mMaxHeadsUpHeightLegacy
254 : mMaxHeadsUpHeight;
Selim Cinek860b6da2015-12-16 19:02:19 -0800255 mPrivateLayout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight);
256 mPublicLayout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200257 }
258
259 public StatusBarNotification getStatusBarNotification() {
260 return mStatusBarNotification;
261 }
262
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700263 public boolean isHeadsUp() {
264 return mIsHeadsUp;
265 }
266
Selim Cinek1a521f32014-11-03 17:39:29 +0100267 public void setHeadsUp(boolean isHeadsUp) {
Selim Cinekc80fdb12015-04-13 15:09:08 -0700268 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek1a521f32014-11-03 17:39:29 +0100269 mIsHeadsUp = isHeadsUp;
Selim Cinek8d490d42015-04-10 00:05:50 -0700270 mPrivateLayout.setHeadsUp(isHeadsUp);
Selim Cinekc80fdb12015-04-13 15:09:08 -0700271 if (intrinsicBefore != getIntrinsicHeight()) {
272 notifyHeightChanged(false /* needsAnimation */);
273 }
Selim Cinek1a521f32014-11-03 17:39:29 +0100274 }
275
Selim Cinekb5605e52015-02-20 18:21:41 +0100276 public void setGroupManager(NotificationGroupManager groupManager) {
277 mGroupManager = groupManager;
Selim Cinek83bc7832015-10-22 13:26:54 -0700278 mPrivateLayout.setGroupManager(groupManager);
Selim Cinekb5605e52015-02-20 18:21:41 +0100279 }
280
Adrian Roosb88b1a12015-12-09 18:51:05 -0800281 public void setRemoteInputController(RemoteInputController r) {
282 mPrivateLayout.setRemoteInputController(r);
283 }
284
Selim Cinekb5605e52015-02-20 18:21:41 +0100285 public void addChildNotification(ExpandableNotificationRow row) {
286 addChildNotification(row, -1);
287 }
288
289 /**
290 * Add a child notification to this view.
291 *
292 * @param row the row to add
293 * @param childIndex the index to add it at, if -1 it will be added at the end
294 */
295 public void addChildNotification(ExpandableNotificationRow row, int childIndex) {
296 if (mChildrenContainer == null) {
297 mChildrenContainerStub.inflate();
298 }
299 mChildrenContainer.addNotification(row, childIndex);
Selim Cinek263398f2015-10-21 17:40:23 -0700300 onChildrenCountChanged();
301 row.setIsChildInGroup(true, this);
Selim Cinekb5605e52015-02-20 18:21:41 +0100302 }
303
304 public void removeChildNotification(ExpandableNotificationRow row) {
305 if (mChildrenContainer != null) {
306 mChildrenContainer.removeNotification(row);
307 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800308 mHeaderUtil.restoreNotificationHeader(row);
Selim Cinek263398f2015-10-21 17:40:23 -0700309 onChildrenCountChanged();
310 row.setIsChildInGroup(false, null);
311 }
312
313 public boolean isChildInGroup() {
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700314 return mNotificationParent != null;
Selim Cinek263398f2015-10-21 17:40:23 -0700315 }
316
Selim Cinek388df6d2015-10-22 13:25:11 -0700317 public ExpandableNotificationRow getNotificationParent() {
318 return mNotificationParent;
319 }
320
Selim Cinek263398f2015-10-21 17:40:23 -0700321 /**
322 * @param isChildInGroup Is this notification now in a group
323 * @param parent the new parent notification
324 */
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700325 public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {;
326 boolean childInGroup = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
327 mNotificationParent = childInGroup ? parent : null;
328 mPrivateLayout.setIsChildInGroup(childInGroup);
329 updateNoBackgroundState();
Selim Cinek34d93b02015-10-22 12:30:38 -0700330 }
331
332 @Override
Selim Cinek72109472016-01-15 16:33:22 -0800333 public boolean onTouchEvent(MotionEvent event) {
334 if (event.getActionMasked() != MotionEvent.ACTION_DOWN
335 || !isChildInGroup() || isGroupExpanded()) {
336 return super.onTouchEvent(event);
337 } else {
338 return false;
339 }
340 }
341
342 @Override
Mady Mellorf0625802016-02-11 18:03:48 -0800343 protected boolean handleSlideBack() {
344 if (mSettingsIconRow != null && mSettingsIconRow.isVisible()) {
345 animateTranslateNotification(0 /* targetLeft */);
346 return true;
347 }
348 return false;
349 }
350
351 @Override
Selim Cinek34d93b02015-10-22 12:30:38 -0700352 protected boolean shouldHideBackground() {
353 return super.shouldHideBackground() || mShowNoBackground;
Selim Cinek263398f2015-10-21 17:40:23 -0700354 }
355
356 @Override
357 public boolean isSummaryWithChildren() {
358 return mIsSummaryWithChildren;
Selim Cinekb5605e52015-02-20 18:21:41 +0100359 }
360
361 @Override
362 public boolean areChildrenExpanded() {
363 return mChildrenExpanded;
364 }
365
366 public List<ExpandableNotificationRow> getNotificationChildren() {
367 return mChildrenContainer == null ? null : mChildrenContainer.getNotificationChildren();
368 }
369
Selim Cinekeef84282015-10-30 16:28:00 -0700370 public int getNumberOfNotificationChildren() {
371 if (mChildrenContainer == null) {
372 return 0;
373 }
374 return mChildrenContainer.getNotificationChildren().size();
375 }
376
Selim Cinekb5605e52015-02-20 18:21:41 +0100377 /**
378 * Apply the order given in the list to the children.
379 *
380 * @param childOrder the new list order
381 * @return whether the list order has changed
382 */
383 public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder) {
384 return mChildrenContainer != null && mChildrenContainer.applyChildOrder(childOrder);
385 }
386
387 public void getChildrenStates(StackScrollState resultState) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700388 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100389 StackViewState parentState = resultState.getViewStateForView(this);
390 mChildrenContainer.getState(resultState, parentState);
391 }
392 }
393
394 public void applyChildrenState(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700395 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100396 mChildrenContainer.applyState(state);
397 }
398 }
399
400 public void prepareExpansionChanged(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700401 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100402 mChildrenContainer.prepareExpansionChanged(state);
403 }
404 }
405
406 public void startChildAnimation(StackScrollState finalState,
Selim Cinek99695592016-01-12 17:51:35 -0800407 StackStateAnimator stateAnimator, long delay, long duration) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700408 if (mIsSummaryWithChildren) {
Selim Cinek99695592016-01-12 17:51:35 -0800409 mChildrenContainer.startAnimationToState(finalState, stateAnimator, delay,
Selim Cinekb5605e52015-02-20 18:21:41 +0100410 duration);
411 }
412 }
413
414 public ExpandableNotificationRow getViewAtPosition(float y) {
Selim Cineka26ddba2016-02-29 20:43:55 -0800415 if (!mIsSummaryWithChildren || !mChildrenExpanded
416 || (getNotificationChildren().size() == 1 && isClearable())) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100417 return this;
418 } else {
419 ExpandableNotificationRow view = mChildrenContainer.getViewAtPosition(y);
420 return view == null ? this : view;
421 }
422 }
423
Selim Cinekab29aeb2015-02-20 18:18:32 +0100424 public NotificationGuts getGuts() {
425 return mGuts;
426 }
427
Selim Cinek684a4422015-04-15 16:18:39 -0700428 /**
429 * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this
430 * the notification will be rendered on top of the screen.
431 *
432 * @param pinned whether it is pinned
433 */
434 public void setPinned(boolean pinned) {
435 mIsPinned = pinned;
Selim Cinek31aada42015-12-18 17:51:15 -0800436 if (pinned) {
437 setIconAnimationRunning(true);
438 mExpandedWhenPinned = false;
439 } else if (mExpandedWhenPinned) {
440 setUserExpanded(true);
441 }
Selim Cinek98713a42015-09-21 15:47:20 +0200442 setChronometerRunning(mLastChronometerRunning);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700443 }
444
Selim Cinek684a4422015-04-15 16:18:39 -0700445 public boolean isPinned() {
446 return mIsPinned;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700447 }
448
Selim Cinek31aada42015-12-18 17:51:15 -0800449 /**
450 * @param atLeastMinHeight should the value returned be at least the minimum height.
451 * Used to avoid cyclic calls
452 * @return the height of the heads up notification when pinned
453 */
454 public int getPinnedHeadsUpHeight(boolean atLeastMinHeight) {
Selim Cinek77019c72015-12-09 10:18:02 -0800455 if (mIsSummaryWithChildren) {
456 return mChildrenContainer.getIntrinsicHeight();
457 }
Selim Cinek31aada42015-12-18 17:51:15 -0800458 if(mExpandedWhenPinned) {
459 return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
460 } else if (atLeastMinHeight) {
461 return Math.max(getMinHeight(), mHeadsUpHeight);
462 } else {
463 return mHeadsUpHeight;
464 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700465 }
466
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700467 /**
468 * Mark whether this notification was just clicked, i.e. the user has just clicked this
469 * notification in this frame.
470 */
471 public void setJustClicked(boolean justClicked) {
472 mJustClicked = justClicked;
473 }
474
475 /**
476 * @return true if this notification has been clicked in this frame, false otherwise
477 */
478 public boolean wasJustClicked() {
479 return mJustClicked;
480 }
481
Selim Cinek98713a42015-09-21 15:47:20 +0200482 public void setChronometerRunning(boolean running) {
483 mLastChronometerRunning = running;
484 setChronometerRunning(running, mPrivateLayout);
485 setChronometerRunning(running, mPublicLayout);
486 if (mChildrenContainer != null) {
487 List<ExpandableNotificationRow> notificationChildren =
488 mChildrenContainer.getNotificationChildren();
489 for (int i = 0; i < notificationChildren.size(); i++) {
490 ExpandableNotificationRow child = notificationChildren.get(i);
491 child.setChronometerRunning(running);
492 }
493 }
494 }
495
496 private void setChronometerRunning(boolean running, NotificationContentView layout) {
497 if (layout != null) {
498 running = running || isPinned();
499 View contractedChild = layout.getContractedChild();
500 View expandedChild = layout.getExpandedChild();
501 View headsUpChild = layout.getHeadsUpChild();
502 setChronometerRunningForChild(running, contractedChild);
503 setChronometerRunningForChild(running, expandedChild);
504 setChronometerRunningForChild(running, headsUpChild);
505 }
506 }
507
508 private void setChronometerRunningForChild(boolean running, View child) {
509 if (child != null) {
510 View chronometer = child.findViewById(com.android.internal.R.id.chronometer);
511 if (chronometer instanceof Chronometer) {
512 ((Chronometer) chronometer).setStarted(running);
513 }
514 }
515 }
516
Selim Cinekea4bef72015-12-02 15:51:10 -0800517 public NotificationHeaderView getNotificationHeader() {
518 if (mNotificationHeader != null) {
519 return mNotificationHeader;
Selim Cinek8d6440d2015-10-22 13:00:05 -0700520 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800521 return mPrivateLayout.getNotificationHeader();
Selim Cinek8d6440d2015-10-22 13:00:05 -0700522 }
523
Selim Cinek34eda5e2016-02-18 17:10:43 -0800524 private NotificationHeaderView getVisibleNotificationHeader() {
525 if (mNotificationHeader != null) {
526 return mNotificationHeader;
527 }
528 return getShowingLayout().getVisibleNotificationHeader();
529 }
530
Selim Cinek570981d2015-12-01 11:37:01 -0800531 public void setOnExpandClickListener(OnExpandClickListener onExpandClickListener) {
532 mOnExpandClickListener = onExpandClickListener;
533 }
534
Selim Cinek31aada42015-12-18 17:51:15 -0800535 public void setHeadsUpManager(HeadsUpManager headsUpManager) {
536 mHeadsUpManager = headsUpManager;
537 }
538
Selim Cinek01af3342016-02-09 19:25:31 -0800539 public void reInflateViews() {
540 initDimens();
541 if (mIsSummaryWithChildren) {
542 removeView(mNotificationHeader);
543 mNotificationHeader = null;
544 recreateNotificationHeader();
545 if (mChildrenContainer != null) {
546 mChildrenContainer.reInflateViews();
547 }
548 }
549 if (mGuts != null) {
550 View oldGuts = mGuts;
551 int index = indexOfChild(oldGuts);
552 removeView(oldGuts);
553 mGuts = (NotificationGuts) LayoutInflater.from(mContext).inflate(
554 R.layout.notification_guts, this, false);
555 mGuts.setVisibility(oldGuts.getVisibility());
556 addView(mGuts, index);
557 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800558 if (mSettingsIconRow != null) {
559 View oldSettings = mSettingsIconRow;
560 int settingsIndex = indexOfChild(oldSettings);
561 removeView(oldSettings);
562 mSettingsIconRow = (NotificationSettingsIconRow) LayoutInflater.from(mContext).inflate(
563 R.layout.notification_settings_icon_row, this, false);
564 mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
565 mSettingsIconRow.setVisibility(oldSettings.getVisibility());
566 addView(mSettingsIconRow, settingsIndex);
567
568 }
Selim Cinekde33a4a2016-02-11 16:43:41 -0800569 mPrivateLayout.reInflateViews();
570 mPublicLayout.reInflateViews();
Selim Cinek01af3342016-02-09 19:25:31 -0800571 }
572
Chris Wren78403d72014-07-28 10:23:24 +0100573 public interface ExpansionLogger {
574 public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
575 }
Selim Cinek1685e632014-04-08 02:27:49 +0200576
Chris Wren51c75102013-07-16 20:49:17 -0400577 public ExpandableNotificationRow(Context context, AttributeSet attrs) {
578 super(context, attrs);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700579 mFalsingManager = FalsingManager.getInstance(context);
Selim Cinek01af3342016-02-09 19:25:31 -0800580 initDimens();
581 }
582
583 private void initDimens() {
Selim Cinekf619ffc2016-02-17 14:53:05 -0800584 mNotificationMinHeightLegacy = getFontScaledHeight(R.dimen.notification_min_height_legacy);
585 mNotificationMinHeight = getFontScaledHeight(R.dimen.notification_min_height);
586 mNotificationMaxHeight = getFontScaledHeight(R.dimen.notification_max_height);
587 mMaxHeadsUpHeightLegacy = getFontScaledHeight(
Selim Cinek77019c72015-12-09 10:18:02 -0800588 R.dimen.notification_max_heads_up_height_legacy);
Selim Cinekf619ffc2016-02-17 14:53:05 -0800589 mMaxHeadsUpHeight = getFontScaledHeight(R.dimen.notification_max_heads_up_height);
590 }
591
592 /**
593 * @param dimenId the dimen to look up
594 * @return the font scaled dimen as if it were in sp but doesn't shrink sizes below dp
595 */
596 private int getFontScaledHeight(int dimenId) {
597 int dimensionPixelSize = getResources().getDimensionPixelSize(dimenId);
598 float factor = Math.max(1.0f, getResources().getDisplayMetrics().scaledDensity /
599 getResources().getDisplayMetrics().density);
600 return (int) (dimensionPixelSize * factor);
Chris Wren51c75102013-07-16 20:49:17 -0400601 }
602
Christoph Studera7fe6312014-06-27 19:32:44 +0200603 /**
604 * Resets this view so it can be re-used for an updated notification.
605 */
Christoph Studer22f2ee52014-07-29 22:57:21 +0200606 @Override
Christoph Studera7fe6312014-06-27 19:32:44 +0200607 public void reset() {
Christoph Studer22f2ee52014-07-29 22:57:21 +0200608 super.reset();
Chris Wren78403d72014-07-28 10:23:24 +0100609 final boolean wasExpanded = isExpanded();
Christoph Studera7fe6312014-06-27 19:32:44 +0200610 mExpandable = false;
611 mHasUserChangedExpansion = false;
612 mUserLocked = false;
613 mShowingPublic = false;
Jorim Jaggiae441282014-08-01 02:45:18 +0200614 mSensitive = false;
615 mShowingPublicInitialized = false;
Christoph Studera7fe6312014-06-27 19:32:44 +0200616 mIsSystemExpanded = false;
Selim Cinek83bc7832015-10-22 13:26:54 -0700617 mOnKeyguard = false;
Selim Cinek1a521f32014-11-03 17:39:29 +0100618 mPublicLayout.reset(mIsHeadsUp);
619 mPrivateLayout.reset(mIsHeadsUp);
Selim Cinek31094df2014-08-14 19:28:15 +0200620 resetHeight();
Mady Mellor4b80b102016-01-22 08:03:58 -0800621 resetTranslation();
Selim Cinek31094df2014-08-14 19:28:15 +0200622 logExpansionEvent(false, wasExpanded);
623 }
624
625 public void resetHeight() {
Selim Cinek1a521f32014-11-03 17:39:29 +0100626 if (mIsHeadsUp) {
627 resetActualHeight();
628 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200629 mMaxExpandHeight = 0;
Selim Cinek8d490d42015-04-10 00:05:50 -0700630 mHeadsUpHeight = 0;
Selim Cineka5e211b2014-08-11 17:35:48 +0200631 mWasReset = true;
Selim Cinek31094df2014-08-14 19:28:15 +0200632 onHeightReset();
Selim Cinek6e28a672014-09-05 14:43:28 +0200633 requestLayout();
Christoph Studera7fe6312014-06-27 19:32:44 +0200634 }
635
Jorim Jaggi251957d2014-04-09 04:24:09 +0200636 @Override
637 protected void onFinishInflate() {
638 super.onFinishInflate();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200639 mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800640 mPublicLayout.setContainingNotification(this);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200641 mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800642 mPrivateLayout.setExpandClickListener(mExpandClickListener);
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800643 mPrivateLayout.setContainingNotification(this);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800644 mPublicLayout.setExpandClickListener(mExpandClickListener);
Mady Mellor4b80b102016-01-22 08:03:58 -0800645 mSettingsIconRowStub = (ViewStub) findViewById(R.id.settings_icon_row_stub);
646 mSettingsIconRowStub.setOnInflateListener(new ViewStub.OnInflateListener() {
647 @Override
648 public void onInflate(ViewStub stub, View inflated) {
649 mSettingsIconRow = (NotificationSettingsIconRow) inflated;
650 mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
651 }
652 });
Selim Cinekab29aeb2015-02-20 18:18:32 +0100653 mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
654 mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200655 @Override
656 public void onInflate(ViewStub stub, View inflated) {
657 mGuts = (NotificationGuts) inflated;
658 mGuts.setClipTopAmount(getClipTopAmount());
659 mGuts.setActualHeight(getActualHeight());
Selim Cinekab29aeb2015-02-20 18:18:32 +0100660 mGutsStub = null;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200661 }
662 });
Selim Cinekb5605e52015-02-20 18:21:41 +0100663 mChildrenContainerStub = (ViewStub) findViewById(R.id.child_container_stub);
664 mChildrenContainerStub.setOnInflateListener(new ViewStub.OnInflateListener() {
665
666 @Override
667 public void onInflate(ViewStub stub, View inflated) {
668 mChildrenContainer = (NotificationChildrenContainer) inflated;
Selim Cinek388df6d2015-10-22 13:25:11 -0700669 mChildrenContainer.setNotificationParent(ExpandableNotificationRow.this);
Mady Mellor4b80b102016-01-22 08:03:58 -0800670 mTranslateableViews.add(mChildrenContainer);
Selim Cinekb5605e52015-02-20 18:21:41 +0100671 }
672 });
Selim Cinek863834b2014-05-20 04:20:25 +0200673 mVetoButton = findViewById(R.id.veto);
Mady Mellor4b80b102016-01-22 08:03:58 -0800674
675 // Add the views that we translate to reveal the gear
676 mTranslateableViews = new ArrayList<View>();
677 for (int i = 0; i < getChildCount(); i++) {
678 mTranslateableViews.add(getChildAt(i));
679 }
680 // Remove views that don't translate
681 mTranslateableViews.remove(mVetoButton);
682 mTranslateableViews.remove(mSettingsIconRowStub);
683 mTranslateableViews.remove(mChildrenContainerStub);
684 mTranslateableViews.remove(mGutsStub);
685 }
686
687 public void setTranslationForOutline(float translationX) {
688 setOutlineRect(false, translationX, getTop(), getRight() + translationX, getBottom());
689 }
690
691 public void resetTranslation() {
692 if (mTranslateableViews != null) {
693 for (int i = 0; i < mTranslateableViews.size(); i++) {
694 mTranslateableViews.get(i).setTranslationX(0);
695 }
696 setTranslationForOutline(0);
697 }
698 if (mSettingsIconRow != null) {
699 mSettingsIconRow.resetState();
700 }
701 }
702
703 public void animateTranslateNotification(final float leftTarget) {
704 if (mTranslateAnim != null) {
705 mTranslateAnim.cancel();
706 }
707 AnimatorSet set = new AnimatorSet();
708 if (mTranslateableViews != null) {
709 for (int i = 0; i < mTranslateableViews.size(); i++) {
710 final View animView = mTranslateableViews.get(i);
711 final ObjectAnimator translateAnim = ObjectAnimator.ofFloat(
712 animView, "translationX", leftTarget);
713 if (i == 0) {
714 translateAnim.addUpdateListener(new AnimatorUpdateListener() {
715 @Override
716 public void onAnimationUpdate(ValueAnimator animation) {
717 setTranslationForOutline((float) animation.getAnimatedValue());
718 }
719 });
720 }
721 translateAnim.addListener(new AnimatorListenerAdapter() {
722 @Override
723 public void onAnimationEnd(Animator anim) {
724 if (mSettingsIconRow != null && leftTarget == 0) {
725 mSettingsIconRow.resetState();
726 }
727 mTranslateAnim = null;
728 }
729 });
730 set.play(translateAnim);
731 }
732 }
733 mTranslateAnim = set;
734 set.start();
735 }
736
737 public float getSpaceForGear() {
738 if (mSettingsIconRow != null) {
739 return mSettingsIconRow.getSpaceForGear();
740 }
741 return 0;
742 }
743
744 public NotificationSettingsIconRow getSettingsRow() {
745 if (mSettingsIconRow == null) {
746 mSettingsIconRowStub.inflate();
747 }
748 return mSettingsIconRow;
749 }
750
751 public ArrayList<View> getContentViews() {
752 return mTranslateableViews;
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200753 }
754
Selim Cinekab29aeb2015-02-20 18:18:32 +0100755 public void inflateGuts() {
756 if (mGuts == null) {
757 mGutsStub.inflate();
758 }
759 }
760
Selim Cinekda42d652015-12-04 15:51:16 -0800761 private void updateChildrenVisibility() {
Selim Cinekd84a5932015-12-15 11:45:36 -0800762 mPrivateLayout.setVisibility(!mShowingPublic && !mIsSummaryWithChildren ? VISIBLE
763 : INVISIBLE);
Selim Cinekef5127e2015-12-21 16:55:58 -0800764 if (mChildrenContainer != null) {
765 mChildrenContainer.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
766 : INVISIBLE);
Selim Cinekb5605e52015-02-20 18:21:41 +0100767 }
Selim Cinekef5127e2015-12-21 16:55:58 -0800768 if (mNotificationHeader != null) {
769 mNotificationHeader.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
770 : INVISIBLE);
771 }
Selim Cinekda42d652015-12-04 15:51:16 -0800772 // The limits might have changed if the view suddenly became a group or vice versa
773 updateLimits();
Selim Cinekb5605e52015-02-20 18:21:41 +0100774 }
775
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200776 @Override
Alan Viverettea54956a2015-01-07 16:05:02 -0800777 public boolean onRequestSendAccessibilityEventInternal(View child, AccessibilityEvent event) {
778 if (super.onRequestSendAccessibilityEventInternal(child, event)) {
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200779 // Add a record for the entire layout since its content is somehow small.
780 // The event comes from a leaf view that is interacted with.
781 AccessibilityEvent record = AccessibilityEvent.obtain();
782 onInitializeAccessibilityEvent(record);
783 dispatchPopulateAccessibilityEvent(record);
784 event.appendRecord(record);
785 return true;
786 }
787 return false;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200788 }
Chris Wren51c75102013-07-16 20:49:17 -0400789
John Spurlocke15452b2014-08-21 09:44:39 -0400790 @Override
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100791 public void setDark(boolean dark, boolean fade, long delay) {
792 super.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400793 final NotificationContentView showing = getShowingLayout();
794 if (showing != null) {
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100795 showing.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400796 }
Selim Cinek9c7712d2015-12-08 19:19:48 -0800797 if (mIsSummaryWithChildren) {
798 mChildrenContainer.setDark(dark, fade, delay);
799 mNotificationHeaderWrapper.setDark(dark, fade, delay);
800 }
John Spurlocke15452b2014-08-21 09:44:39 -0400801 }
802
Chris Wren51c75102013-07-16 20:49:17 -0400803 public boolean isExpandable() {
Selim Cinek388df6d2015-10-22 13:25:11 -0700804 if (mIsSummaryWithChildren && !mShowingPublic) {
805 return !mChildrenExpanded;
806 }
Chris Wren51c75102013-07-16 20:49:17 -0400807 return mExpandable;
808 }
809
810 public void setExpandable(boolean expandable) {
811 mExpandable = expandable;
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800812 mPrivateLayout.updateExpandButtons(isExpandable());
Chris Wren51c75102013-07-16 20:49:17 -0400813 }
814
Selim Cinek4ffd6362015-12-29 15:12:23 +0100815 @Override
816 public void setClipToActualHeight(boolean clipToActualHeight) {
Selim Cinek084c16b2016-01-22 17:48:22 -0800817 super.setClipToActualHeight(clipToActualHeight || isUserLocked());
818 getShowingLayout().setClipToActualHeight(clipToActualHeight || isUserLocked());
Selim Cinek4ffd6362015-12-29 15:12:23 +0100819 }
820
Selim Cinek1685e632014-04-08 02:27:49 +0200821 /**
822 * @return whether the user has changed the expansion state
823 */
824 public boolean hasUserChangedExpansion() {
825 return mHasUserChangedExpansion;
826 }
827
Chris Wren51c75102013-07-16 20:49:17 -0400828 public boolean isUserExpanded() {
829 return mUserExpanded;
830 }
831
Selim Cinek1685e632014-04-08 02:27:49 +0200832 /**
833 * Set this notification to be expanded by the user
834 *
835 * @param userExpanded whether the user wants this notification to be expanded
836 */
Chris Wren51c75102013-07-16 20:49:17 -0400837 public void setUserExpanded(boolean userExpanded) {
Selim Cinek388df6d2015-10-22 13:25:11 -0700838 setUserExpanded(userExpanded, false /* allowChildExpansion */);
839 }
840
841 /**
842 * Set this notification to be expanded by the user
843 *
844 * @param userExpanded whether the user wants this notification to be expanded
845 * @param allowChildExpansion whether a call to this method allows expanding children
846 */
847 public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700848 mFalsingManager.setNotificationExpanded();
Selim Cinek388df6d2015-10-22 13:25:11 -0700849 if (mIsSummaryWithChildren && !mShowingPublic && allowChildExpansion) {
850 mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
851 return;
852 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200853 if (userExpanded && !mExpandable) return;
Chris Wren78403d72014-07-28 10:23:24 +0100854 final boolean wasExpanded = isExpanded();
Selim Cinek1685e632014-04-08 02:27:49 +0200855 mHasUserChangedExpansion = true;
Chris Wren51c75102013-07-16 20:49:17 -0400856 mUserExpanded = userExpanded;
Chris Wren78403d72014-07-28 10:23:24 +0100857 logExpansionEvent(true, wasExpanded);
Chris Wren51c75102013-07-16 20:49:17 -0400858 }
859
Selim Cinekccd14fb2014-08-12 18:53:24 +0200860 public void resetUserExpansion() {
861 mHasUserChangedExpansion = false;
862 mUserExpanded = false;
863 }
864
Chris Wren51c75102013-07-16 20:49:17 -0400865 public boolean isUserLocked() {
866 return mUserLocked;
867 }
868
869 public void setUserLocked(boolean userLocked) {
870 mUserLocked = userLocked;
Selim Cinek8f2f6a62016-02-23 19:56:31 -0800871 mPrivateLayout.setUserExpanding(userLocked);
Selim Cinek42357e02016-02-24 18:48:01 -0800872 if (mIsSummaryWithChildren) {
873 mChildrenContainer.setUserLocked(userLocked);
874 }
Chris Wren51c75102013-07-16 20:49:17 -0400875 }
876
Selim Cinek1685e632014-04-08 02:27:49 +0200877 /**
878 * @return has the system set this notification to be expanded
879 */
880 public boolean isSystemExpanded() {
881 return mIsSystemExpanded;
882 }
883
884 /**
885 * Set this notification to be expanded by the system.
886 *
887 * @param expand whether the system wants this notification to be expanded.
888 */
889 public void setSystemExpanded(boolean expand) {
Selim Cinek31094df2014-08-14 19:28:15 +0200890 if (expand != mIsSystemExpanded) {
891 final boolean wasExpanded = isExpanded();
892 mIsSystemExpanded = expand;
Selim Cinekb5605e52015-02-20 18:21:41 +0100893 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200894 logExpansionEvent(false, wasExpanded);
Selim Cinek83bc7832015-10-22 13:26:54 -0700895 if (mChildrenContainer != null) {
896 mChildrenContainer.updateGroupOverflow();
897 }
Selim Cinek31094df2014-08-14 19:28:15 +0200898 }
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200899 }
900
901 /**
Selim Cinek83bc7832015-10-22 13:26:54 -0700902 * @param onKeyguard whether to prevent notification expansion
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200903 */
Selim Cinek83bc7832015-10-22 13:26:54 -0700904 public void setOnKeyguard(boolean onKeyguard) {
905 if (onKeyguard != mOnKeyguard) {
Selim Cinek31094df2014-08-14 19:28:15 +0200906 final boolean wasExpanded = isExpanded();
Selim Cinek83bc7832015-10-22 13:26:54 -0700907 mOnKeyguard = onKeyguard;
Selim Cinek31094df2014-08-14 19:28:15 +0200908 logExpansionEvent(false, wasExpanded);
909 if (wasExpanded != isExpanded()) {
Selim Cinek2108fe02015-12-10 12:56:13 -0800910 if (mIsSummaryWithChildren) {
911 mChildrenContainer.updateGroupOverflow();
912 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800913 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200914 }
915 }
Selim Cinek1685e632014-04-08 02:27:49 +0200916 }
917
918 /**
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400919 * @return Can the underlying notification be cleared?
920 */
921 public boolean isClearable() {
Selim Cineka37774f2014-11-11 19:16:18 +0100922 return mStatusBarNotification != null && mStatusBarNotification.isClearable();
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400923 }
924
925 /**
Selim Cinek1685e632014-04-08 02:27:49 +0200926 * Apply an expansion state to the layout.
Selim Cinek1685e632014-04-08 02:27:49 +0200927 */
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200928 public void applyExpansionToLayout() {
929 boolean expand = isExpanded();
Chris Wren51c75102013-07-16 20:49:17 -0400930 if (expand && mExpandable) {
Selim Cinekeef84282015-10-30 16:28:00 -0700931 setActualHeight(mMaxExpandHeight);
Chris Wren51c75102013-07-16 20:49:17 -0400932 } else {
Selim Cinek860b6da2015-12-16 19:02:19 -0800933 setActualHeight(getMinHeight());
Chris Wren51c75102013-07-16 20:49:17 -0400934 }
Chris Wren51c75102013-07-16 20:49:17 -0400935 }
Dan Sandlera5e0f412014-01-23 15:11:54 -0500936
Jorim Jaggi9cbadd32014-05-01 20:18:31 +0200937 @Override
938 public int getIntrinsicHeight() {
Jorim Jaggibe565df2014-04-28 17:51:23 +0200939 if (isUserLocked()) {
940 return getActualHeight();
941 }
Selim Cinekd84a5932015-12-15 11:45:36 -0800942 if (mGuts != null && mGuts.areGutsExposed()) {
943 return mGuts.getHeight();
944 } else if ((isChildInGroup() && !isGroupExpanded())) {
945 return mPrivateLayout.getMinHeight();
946 } else if (mSensitive && mHideSensitiveForIntrinsicHeight) {
947 return getMinHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -0700948 } else if (mIsSummaryWithChildren && !mOnKeyguard) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800949 return mChildrenContainer.getIntrinsicHeight();
Selim Cinek60122be2015-04-15 18:16:50 -0700950 } else if (mIsHeadsUp) {
Selim Cinek31aada42015-12-18 17:51:15 -0800951 if (isPinned()) {
952 return getPinnedHeadsUpHeight(true /* atLeastMinHeight */);
953 } else if (isExpanded()) {
Selim Cinekd84a5932015-12-15 11:45:36 -0800954 return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -0700955 } else {
Selim Cinekd84a5932015-12-15 11:45:36 -0800956 return Math.max(getMinHeight(), mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -0700957 }
Selim Cinek31aada42015-12-18 17:51:15 -0800958 } else if (isExpanded()) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700959 return getMaxExpandHeight();
Selim Cinekd84a5932015-12-15 11:45:36 -0800960 } else {
961 return getMinHeight();
Selim Cinek1685e632014-04-08 02:27:49 +0200962 }
Selim Cinekb5605e52015-02-20 18:21:41 +0100963 }
Selim Cinek1685e632014-04-08 02:27:49 +0200964
Selim Cinekeef84282015-10-30 16:28:00 -0700965 private boolean isGroupExpanded() {
966 return mGroupManager.isGroupExpanded(mStatusBarNotification);
Selim Cinekb5605e52015-02-20 18:21:41 +0100967 }
968
Selim Cinekeef84282015-10-30 16:28:00 -0700969 /**
970 * @return whether this view has a header on the top of the content
971 */
972 private boolean hasNotificationHeader() {
973 return mIsSummaryWithChildren;
Selim Cinek1685e632014-04-08 02:27:49 +0200974 }
975
Selim Cinek263398f2015-10-21 17:40:23 -0700976 private void onChildrenCountChanged() {
Selim Cinek8fc93c92015-11-23 17:48:07 -0800977 mIsSummaryWithChildren = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS
Selim Cinek263398f2015-10-21 17:40:23 -0700978 && mGroupManager.hasGroupChildren(mStatusBarNotification);
Selim Cinek8fc93c92015-11-23 17:48:07 -0800979 if (mIsSummaryWithChildren) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800980 if (mChildrenContainer == null) {
981 mChildrenContainerStub.inflate();
982 }
Selim Cinek8fc93c92015-11-23 17:48:07 -0800983 if (mNotificationHeader == null) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800984 recreateNotificationHeader();
985 }
Selim Cinek263398f2015-10-21 17:40:23 -0700986 }
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800987 mPrivateLayout.updateExpandButtons(isExpandable());
Selim Cinekea4bef72015-12-02 15:51:10 -0800988 updateChildrenHeaderAppearance();
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800989 updateHeaderChildCount();
Selim Cinekda42d652015-12-04 15:51:16 -0800990 updateChildrenVisibility();
Selim Cinek263398f2015-10-21 17:40:23 -0700991 }
992
Selim Cinek1685e632014-04-08 02:27:49 +0200993 /**
994 * Check whether the view state is currently expanded. This is given by the system in {@link
995 * #setSystemExpanded(boolean)} and can be overridden by user expansion or
996 * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
997 * view can differ from this state, if layout params are modified from outside.
998 *
999 * @return whether the view state is currently expanded.
1000 */
Selim Cinek83bc7832015-10-22 13:26:54 -07001001 public boolean isExpanded() {
1002 return !mOnKeyguard
Selim Cinekb5605e52015-02-20 18:21:41 +01001003 && (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded())
1004 || isUserExpanded());
1005 }
1006
1007 private boolean isSystemChildExpanded() {
1008 return mIsSystemChildExpanded;
1009 }
1010
1011 public void setSystemChildExpanded(boolean expanded) {
1012 mIsSystemChildExpanded = expanded;
Selim Cinek1685e632014-04-08 02:27:49 +02001013 }
1014
1015 @Override
1016 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
1017 super.onLayout(changed, left, top, right, bottom);
Selim Cineka5e211b2014-08-11 17:35:48 +02001018 boolean updateExpandHeight = mMaxExpandHeight == 0 && !mWasReset;
Selim Cinek8d490d42015-04-10 00:05:50 -07001019 updateMaxHeights();
Jorim Jaggibe565df2014-04-28 17:51:23 +02001020 if (updateExpandHeight) {
Jorim Jaggidce3c4c2014-04-29 23:12:24 +02001021 applyExpansionToLayout();
Jorim Jaggibe565df2014-04-28 17:51:23 +02001022 }
Selim Cineka5e211b2014-08-11 17:35:48 +02001023 mWasReset = false;
Selim Cinek1685e632014-04-08 02:27:49 +02001024 }
1025
Selim Cinek8d490d42015-04-10 00:05:50 -07001026 private void updateMaxHeights() {
Selim Cinekd2319fb2014-09-01 19:41:54 +02001027 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek8d490d42015-04-10 00:05:50 -07001028 View expandedChild = mPrivateLayout.getExpandedChild();
1029 if (expandedChild == null) {
1030 expandedChild = mPrivateLayout.getContractedChild();
1031 }
1032 mMaxExpandHeight = expandedChild.getHeight();
1033 View headsUpChild = mPrivateLayout.getHeadsUpChild();
Selim Cinek1f3f5442015-04-10 17:54:46 -07001034 if (headsUpChild == null) {
1035 headsUpChild = mPrivateLayout.getContractedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -07001036 }
Selim Cinek1f3f5442015-04-10 17:54:46 -07001037 mHeadsUpHeight = headsUpChild.getHeight();
Selim Cinekd2319fb2014-09-01 19:41:54 +02001038 if (intrinsicBefore != getIntrinsicHeight()) {
Selim Cinekb5605e52015-02-20 18:21:41 +01001039 notifyHeightChanged(false /* needsAnimation */);
Selim Cinekd2319fb2014-09-01 19:41:54 +02001040 }
1041 }
1042
Selim Cinekfa0a2d32016-01-14 13:02:21 -08001043 @Override
1044 public void notifyHeightChanged(boolean needsAnimation) {
1045 super.notifyHeightChanged(needsAnimation);
1046 getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked());
1047 }
1048
Selim Cinek3c76d502016-02-19 15:16:33 -08001049 public void setSensitive(boolean sensitive, boolean hideSensitive) {
Jorim Jaggiae441282014-08-01 02:45:18 +02001050 mSensitive = sensitive;
Selim Cinek3c76d502016-02-19 15:16:33 -08001051 mSensitiveHiddenInGeneral = hideSensitive;
Jorim Jaggiae441282014-08-01 02:45:18 +02001052 }
1053
1054 public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
Selim Cinek60122be2015-04-15 18:16:50 -07001055 mHideSensitiveForIntrinsicHeight = hideSensitive;
Selim Cineka52f6a12016-02-29 15:35:58 -08001056 if (mIsSummaryWithChildren) {
1057 List<ExpandableNotificationRow> notificationChildren =
1058 mChildrenContainer.getNotificationChildren();
1059 for (int i = 0; i < notificationChildren.size(); i++) {
1060 ExpandableNotificationRow child = notificationChildren.get(i);
1061 child.setHideSensitiveForIntrinsicHeight(hideSensitive);
1062 }
1063 }
Jorim Jaggiae441282014-08-01 02:45:18 +02001064 }
1065
1066 public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
1067 long duration) {
1068 boolean oldShowingPublic = mShowingPublic;
1069 mShowingPublic = mSensitive && hideSensitive;
1070 if (mShowingPublicInitialized && mShowingPublic == oldShowingPublic) {
1071 return;
1072 }
Dan Sandlera5e0f412014-01-23 15:11:54 -05001073
1074 // bail out if no public version
Selim Cinek1685e632014-04-08 02:27:49 +02001075 if (mPublicLayout.getChildCount() == 0) return;
Dan Sandlera5e0f412014-01-23 15:11:54 -05001076
Jorim Jaggiae441282014-08-01 02:45:18 +02001077 if (!animated) {
1078 mPublicLayout.animate().cancel();
1079 mPrivateLayout.animate().cancel();
1080 mPublicLayout.setAlpha(1f);
1081 mPrivateLayout.setAlpha(1f);
1082 mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
Selim Cinekd84a5932015-12-15 11:45:36 -08001083 updateChildrenVisibility();
Jorim Jaggiae441282014-08-01 02:45:18 +02001084 } else {
1085 animateShowingPublic(delay, duration);
1086 }
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001087
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001088 mPrivateLayout.updateExpandButtons(isExpandable());
Selim Cinek757d8792016-01-28 16:21:08 -08001089 updateClearability();
Jorim Jaggiae441282014-08-01 02:45:18 +02001090 mShowingPublicInitialized = true;
1091 }
1092
1093 private void animateShowingPublic(long delay, long duration) {
Selim Cinekd84a5932015-12-15 11:45:36 -08001094 View[] privateViews = mIsSummaryWithChildren ?
1095 new View[] {mChildrenContainer, mNotificationHeader}
1096 : new View[] {mPrivateLayout};
1097 View[] publicViews = new View[] {mPublicLayout};
1098 View[] hiddenChildren = mShowingPublic ? privateViews : publicViews;
1099 View[] shownChildren = mShowingPublic ? publicViews : privateViews;
1100 for (final View hiddenView : hiddenChildren) {
1101 hiddenView.setVisibility(View.VISIBLE);
1102 hiddenView.animate().cancel();
1103 hiddenView.animate()
1104 .alpha(0f)
1105 .setStartDelay(delay)
1106 .setDuration(duration)
1107 .withEndAction(new Runnable() {
1108 @Override
1109 public void run() {
1110 hiddenView.setVisibility(View.INVISIBLE);
1111 }
1112 });
1113 }
1114 for (View showView : shownChildren) {
1115 showView.setVisibility(View.VISIBLE);
1116 showView.setAlpha(0f);
1117 showView.animate().cancel();
1118 showView.animate()
1119 .alpha(1f)
1120 .setStartDelay(delay)
1121 .setDuration(duration);
1122 }
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001123 }
1124
Selim Cinek3776fe02016-02-04 13:32:43 -08001125 public boolean mustStayOnScreen() {
1126 return mIsHeadsUp;
1127 }
1128
Selim Cinek757d8792016-01-28 16:21:08 -08001129 private void updateClearability() {
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001130 // public versions cannot be dismissed
Selim Cinek3c76d502016-02-19 15:16:33 -08001131 mVetoButton.setVisibility(isClearable() && (!mShowingPublic
1132 || !mSensitiveHiddenInGeneral) ? View.VISIBLE : View.GONE);
Dan Sandlera5e0f412014-01-23 15:11:54 -05001133 }
Jorim Jaggi251957d2014-04-09 04:24:09 +02001134
Selim Cinekb5605e52015-02-20 18:21:41 +01001135 public void setChildrenExpanded(boolean expanded, boolean animate) {
1136 mChildrenExpanded = expanded;
Selim Cinek7b836392015-12-04 20:02:59 -08001137 if (mNotificationHeader != null) {
1138 mNotificationHeader.setExpanded(expanded);
1139 }
Selim Cinek83bc7832015-10-22 13:26:54 -07001140 if (mChildrenContainer != null) {
1141 mChildrenContainer.setChildrenExpanded(expanded);
1142 }
Selim Cinekb5605e52015-02-20 18:21:41 +01001143 }
1144
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001145 public void updateHeaderChildCount() {
1146 if (mIsSummaryWithChildren) {
1147 mNotificationHeader.setChildCount(
1148 mChildrenContainer.getNotificationChildren().size());
Selim Cinekb5605e52015-02-20 18:21:41 +01001149 }
Selim Cinekb5605e52015-02-20 18:21:41 +01001150 }
1151
1152 public static void applyTint(View v, int color) {
1153 int alpha;
1154 if (color != 0) {
1155 alpha = COLORED_DIVIDER_ALPHA;
1156 } else {
1157 color = 0xff000000;
1158 alpha = DEFAULT_DIVIDER_ALPHA;
1159 }
1160 if (v.getBackground() instanceof ColorDrawable) {
1161 ColorDrawable background = (ColorDrawable) v.getBackground();
1162 background.mutate();
1163 background.setColor(color);
1164 background.setAlpha(alpha);
1165 }
1166 }
1167
Selim Cinek1685e632014-04-08 02:27:49 +02001168 public int getMaxExpandHeight() {
Selim Cinekb5605e52015-02-20 18:21:41 +01001169 return mMaxExpandHeight;
Chris Wren51c75102013-07-16 20:49:17 -04001170 }
Jorim Jaggi584a7aa2014-04-10 23:26:13 +02001171
Jorim Jaggibe565df2014-04-28 17:51:23 +02001172 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001173 public boolean isContentExpandable() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001174 NotificationContentView showingLayout = getShowingLayout();
1175 return showingLayout.isContentExpandable();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001176 }
1177
1178 @Override
Selim Cinek560e64d2015-06-09 19:58:11 -07001179 protected View getContentView() {
1180 return getShowingLayout();
1181 }
1182
1183 @Override
Jorim Jaggid552d9d2014-05-07 19:41:13 +02001184 public void setActualHeight(int height, boolean notifyListeners) {
Selim Cinekb5605e52015-02-20 18:21:41 +01001185 super.setActualHeight(height, notifyListeners);
Mady Mellorb53bc272016-02-11 18:28:23 -08001186 if (mGuts != null && mGuts.areGutsExposed()) {
1187 mGuts.setActualHeight(height);
1188 return;
1189 }
Selim Cinekeef84282015-10-30 16:28:00 -07001190 int contentHeight = Math.max(getMinHeight(), height);
Selim Cinekb5605e52015-02-20 18:21:41 +01001191 mPrivateLayout.setContentHeight(contentHeight);
1192 mPublicLayout.setContentHeight(contentHeight);
Selim Cinek42357e02016-02-24 18:48:01 -08001193 if (mIsSummaryWithChildren) {
1194 mChildrenContainer.setActualHeight(height);
1195 }
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001196 if (mGuts != null) {
1197 mGuts.setActualHeight(height);
1198 }
Jorim Jaggibe565df2014-04-28 17:51:23 +02001199 }
1200
1201 @Override
Selim Cinekb5605e52015-02-20 18:21:41 +01001202 public int getMaxContentHeight() {
Selim Cinek83bc7832015-10-22 13:26:54 -07001203 if (mIsSummaryWithChildren && !mShowingPublic) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001204 return mChildrenContainer.getMaxContentHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -07001205 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001206 NotificationContentView showingLayout = getShowingLayout();
1207 return showingLayout.getMaxHeight();
Jorim Jaggibe565df2014-04-28 17:51:23 +02001208 }
1209
1210 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001211 public int getMinHeight() {
Selim Cinek31aada42015-12-18 17:51:15 -08001212 if (mIsHeadsUp && mHeadsUpManager.isTrackingHeadsUp()) {
1213 return getPinnedHeadsUpHeight(false /* atLeastMinHeight */);
1214 } else if (mIsSummaryWithChildren && !isGroupExpanded() && !mShowingPublic) {
Selim Cinekb55386d2015-12-16 17:26:49 -08001215 return mChildrenContainer.getMinHeight();
Selim Cinek31aada42015-12-18 17:51:15 -08001216 } else if (mIsHeadsUp) {
1217 return mHeadsUpHeight;
Selim Cinekb55386d2015-12-16 17:26:49 -08001218 }
Selim Cinek816c8e42015-11-19 12:00:45 -08001219 NotificationContentView showingLayout = getShowingLayout();
1220 return showingLayout.getMinHeight();
1221 }
1222
1223 @Override
1224 public int getMinExpandHeight() {
Selim Cinek2c584612016-02-29 16:14:25 -08001225 if (mIsSummaryWithChildren && !mShowingPublic) {
1226 return mChildrenContainer.getMinExpandHeight(mOnKeyguard);
Selim Cinek83bc7832015-10-22 13:26:54 -07001227 }
Selim Cinek816c8e42015-11-19 12:00:45 -08001228 return getMinHeight();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001229 }
1230
1231 @Override
Jorim Jaggibe565df2014-04-28 17:51:23 +02001232 public void setClipTopAmount(int clipTopAmount) {
1233 super.setClipTopAmount(clipTopAmount);
1234 mPrivateLayout.setClipTopAmount(clipTopAmount);
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001235 mPublicLayout.setClipTopAmount(clipTopAmount);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001236 if (mGuts != null) {
1237 mGuts.setClipTopAmount(clipTopAmount);
1238 }
Jorim Jaggibe565df2014-04-28 17:51:23 +02001239 }
1240
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001241 private void recreateNotificationHeader() {
1242 final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
1243 getStatusBarNotification().getNotification());
1244 final RemoteViews header = builder.makeNotificationHeader();
1245 if (mNotificationHeader == null) {
1246 mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
1247 final View expandButton = mNotificationHeader.findViewById(
1248 com.android.internal.R.id.expand_button);
1249 expandButton.setVisibility(VISIBLE);
1250 mNotificationHeader.setOnClickListener(mExpandClickListener);
Selim Cinek9c7712d2015-12-08 19:19:48 -08001251 mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
1252 mNotificationHeader);
Selim Cinekb5a83612015-12-11 14:14:39 -08001253 addView(mNotificationHeader, indexOfChild(mChildrenContainer) + 1);
Mady Mellor4b80b102016-01-22 08:03:58 -08001254 mTranslateableViews.add(mNotificationHeader);
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001255 } else {
1256 header.reapply(getContext(), mNotificationHeader);
Selim Cinek4ffd6362015-12-29 15:12:23 +01001257 mNotificationHeaderWrapper.notifyContentUpdated(mEntry.notification);
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001258 }
Selim Cinek7b836392015-12-04 20:02:59 -08001259 updateHeaderExpandButton();
Selim Cinekea4bef72015-12-02 15:51:10 -08001260 updateChildrenHeaderAppearance();
Selim Cinek8fc93c92015-11-23 17:48:07 -08001261 updateHeaderChildCount();
Selim Cinek343e6e22014-04-11 21:23:30 +02001262 }
Selim Cinek7d447722014-06-10 15:51:59 +02001263
Selim Cinek7b836392015-12-04 20:02:59 -08001264 private void updateHeaderExpandButton() {
1265 if (mIsSummaryWithChildren) {
1266 mNotificationHeader.setIsGroupHeader(true /* isGroupHeader*/);
1267 }
1268 }
1269
Selim Cinekea4bef72015-12-02 15:51:10 -08001270 public void updateChildrenHeaderAppearance() {
1271 if (mIsSummaryWithChildren) {
1272 mHeaderUtil.updateChildrenHeaderAppearance();
1273 }
1274 }
1275
Selim Cinek31094df2014-08-14 19:28:15 +02001276 public boolean isMaxExpandHeightInitialized() {
1277 return mMaxExpandHeight != 0;
Selim Cinek7d447722014-06-10 15:51:59 +02001278 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001279
Selim Cinek42357e02016-02-24 18:48:01 -08001280 public NotificationContentView getShowingLayout() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001281 return mShowingPublic ? mPublicLayout : mPrivateLayout;
1282 }
Chris Wren78403d72014-07-28 10:23:24 +01001283
Jorim Jaggi59ec3042015-06-05 15:18:43 -07001284 @Override
1285 public void setShowingLegacyBackground(boolean showing) {
1286 super.setShowingLegacyBackground(showing);
1287 mPrivateLayout.setShowingLegacyBackground(showing);
1288 mPublicLayout.setShowingLegacyBackground(showing);
1289 }
1290
Selim Cineka6c6bfb2015-10-29 16:27:08 -07001291 @Override
1292 protected void updateBackgroundTint() {
1293 super.updateBackgroundTint();
1294 updateNoBackgroundState();
1295 if (mIsSummaryWithChildren) {
1296 List<ExpandableNotificationRow> notificationChildren =
1297 mChildrenContainer.getNotificationChildren();
1298 for (int i = 0; i < notificationChildren.size(); i++) {
1299 ExpandableNotificationRow child = notificationChildren.get(i);
1300 child.updateNoBackgroundState();
1301 }
1302 }
1303 }
1304
1305 private void updateNoBackgroundState() {
1306 mShowNoBackground = isChildInGroup() && hasSameBgColor(mNotificationParent);
1307 updateBackground();
1308 }
1309
Chris Wren78403d72014-07-28 10:23:24 +01001310 public void setExpansionLogger(ExpansionLogger logger, String key) {
1311 mLogger = logger;
1312 mLoggingKey = key;
1313 }
1314
Selim Cinek6183d122016-01-14 18:48:41 -08001315 @Override
Selim Cinek42357e02016-02-24 18:48:01 -08001316 public float getIncreasedPaddingAmount() {
1317 if (mIsSummaryWithChildren) {
1318 if (isGroupExpanded()) {
1319 return 1.0f;
1320 } else if (isUserLocked()) {
1321 return mChildrenContainer.getChildExpandFraction();
1322 }
1323 }
1324 return 0.0f;
Selim Cinek61633a82016-01-25 15:54:10 -08001325 }
1326
1327 @Override
Selim Cinek6183d122016-01-14 18:48:41 -08001328 protected boolean disallowSingleClick(MotionEvent event) {
1329 float x = event.getX();
1330 float y = event.getY();
Selim Cinek34eda5e2016-02-18 17:10:43 -08001331 NotificationHeaderView header = getVisibleNotificationHeader();
Selim Cinek6183d122016-01-14 18:48:41 -08001332 if (header != null) {
1333 return header.isInTouchRect(x, y);
1334 }
1335 return super.disallowSingleClick(event);
1336 }
1337
Chris Wren78403d72014-07-28 10:23:24 +01001338 private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
1339 final boolean nowExpanded = isExpanded();
1340 if (wasExpanded != nowExpanded && mLogger != null) {
1341 mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
1342 }
1343 }
Selim Cinek570981d2015-12-01 11:37:01 -08001344
1345 public interface OnExpandClickListener {
Selim Cinek31aada42015-12-18 17:51:15 -08001346 void onExpandClicked(NotificationData.Entry clickedEntry, boolean nowExpanded);
Selim Cinek570981d2015-12-01 11:37:01 -08001347 }
Chris Wren51c75102013-07-16 20:49:17 -04001348}