blob: 360390023df3a131249759fa295457425d58ae6d [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
Selim Cineka6c6bfb2015-10-29 16:27:08 -070019import android.app.Notification;
Chris Wren51c75102013-07-16 20:49:17 -040020import android.content.Context;
Selim Cinekcab4a602014-09-03 14:47:57 +020021import android.graphics.drawable.AnimatedVectorDrawable;
22import android.graphics.drawable.AnimationDrawable;
Selim Cinekb5605e52015-02-20 18:21:41 +010023import android.graphics.drawable.ColorDrawable;
Selim Cinekcab4a602014-09-03 14:47:57 +020024import android.graphics.drawable.Drawable;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +020025import android.service.notification.StatusBarNotification;
Chris Wren51c75102013-07-16 20:49:17 -040026import android.util.AttributeSet;
Selim Cinek1a521f32014-11-03 17:39:29 +010027import android.view.MotionEvent;
Dan Sandlera5e0f412014-01-23 15:11:54 -050028import android.view.View;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +020029import android.view.ViewStub;
Jorim Jaggife40f7d2014-04-28 15:20:04 +020030import android.view.accessibility.AccessibilityEvent;
Selim Cinekb5605e52015-02-20 18:21:41 +010031import android.view.animation.LinearInterpolator;
Selim Cinek98713a42015-09-21 15:47:20 +020032import android.widget.Chronometer;
Selim Cinekcab4a602014-09-03 14:47:57 +020033import android.widget.ImageView;
Selim Cinekb5605e52015-02-20 18:21:41 +010034
Dan Sandlera5e0f412014-01-23 15:11:54 -050035import com.android.systemui.R;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070036import com.android.systemui.classifier.FalsingManager;
Selim Cinek8d6440d2015-10-22 13:00:05 -070037import com.android.systemui.statusbar.notification.NotificationHeaderView;
Selim Cinekb5605e52015-02-20 18:21:41 +010038import com.android.systemui.statusbar.phone.NotificationGroupManager;
Selim Cinekb5605e52015-02-20 18:21:41 +010039import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
40import com.android.systemui.statusbar.stack.StackScrollState;
41import com.android.systemui.statusbar.stack.StackStateAnimator;
42import com.android.systemui.statusbar.stack.StackViewState;
43
44import java.util.List;
Dan Sandlera5e0f412014-01-23 15:11:54 -050045
Jorim Jaggi4222d9a2014-04-23 16:13:15 +020046public class ExpandableNotificationRow extends ActivatableNotificationView {
Selim Cinekb5605e52015-02-20 18:21:41 +010047
48 private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
49 private static final int COLORED_DIVIDER_ALPHA = 0x7B;
50 private final LinearInterpolator mLinearInterpolator = new LinearInterpolator();
Selim Cinek1685e632014-04-08 02:27:49 +020051 private int mRowMinHeight;
Chris Wren51c75102013-07-16 20:49:17 -040052
Selim Cinek1685e632014-04-08 02:27:49 +020053 /** Does this row contain layouts that can adapt to row expansion */
Chris Wren51c75102013-07-16 20:49:17 -040054 private boolean mExpandable;
Selim Cinek1685e632014-04-08 02:27:49 +020055 /** Has the user actively changed the expansion state of this row */
56 private boolean mHasUserChangedExpansion;
57 /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */
Chris Wren51c75102013-07-16 20:49:17 -040058 private boolean mUserExpanded;
Selim Cinek1685e632014-04-08 02:27:49 +020059 /** Is the user touching this row */
Chris Wren51c75102013-07-16 20:49:17 -040060 private boolean mUserLocked;
Selim Cinek1685e632014-04-08 02:27:49 +020061 /** Are we showing the "public" version */
Dan Sandlera5e0f412014-01-23 15:11:54 -050062 private boolean mShowingPublic;
Jorim Jaggiae441282014-08-01 02:45:18 +020063 private boolean mSensitive;
64 private boolean mShowingPublicInitialized;
Selim Cinek60122be2015-04-15 18:16:50 -070065 private boolean mHideSensitiveForIntrinsicHeight;
Chris Wren51c75102013-07-16 20:49:17 -040066
Selim Cinek1685e632014-04-08 02:27:49 +020067 /**
68 * Is this notification expanded by the system. The expansion state can be overridden by the
69 * user expansion.
70 */
71 private boolean mIsSystemExpanded;
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020072
73 /**
Selim Cinek83bc7832015-10-22 13:26:54 -070074 * Whether the notification is on the keyguard and the expansion is disabled.
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020075 */
Selim Cinek83bc7832015-10-22 13:26:54 -070076 private boolean mOnKeyguard;
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020077
Jorim Jaggibe565df2014-04-28 17:51:23 +020078 private NotificationContentView mPublicLayout;
79 private NotificationContentView mPrivateLayout;
Selim Cinek1685e632014-04-08 02:27:49 +020080 private int mMaxExpandHeight;
Selim Cinek8d490d42015-04-10 00:05:50 -070081 private int mHeadsUpHeight;
Selim Cinek863834b2014-05-20 04:20:25 +020082 private View mVetoButton;
Dan Sandler0d3e62f2014-07-14 17:13:50 -040083 private boolean mClearable;
Chris Wren78403d72014-07-28 10:23:24 +010084 private ExpansionLogger mLogger;
85 private String mLoggingKey;
Selim Cineka5e211b2014-08-11 17:35:48 +020086 private boolean mWasReset;
Selim Cinek8d490d42015-04-10 00:05:50 -070087 private NotificationGuts mGuts;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +020088 private StatusBarNotification mStatusBarNotification;
Selim Cinek1a521f32014-11-03 17:39:29 +010089 private boolean mIsHeadsUp;
Selim Cinek98713a42015-09-21 15:47:20 +020090 private boolean mLastChronometerRunning = true;
Selim Cinekeef84282015-10-30 16:28:00 -070091 private NotificationHeaderView mNotificationHeader;
92 private ViewStub mNotificationHeaderStub;
Selim Cinekb5605e52015-02-20 18:21:41 +010093 private ViewStub mChildrenContainerStub;
94 private NotificationGroupManager mGroupManager;
Selim Cinekb5605e52015-02-20 18:21:41 +010095 private boolean mChildrenExpanded;
Selim Cinek263398f2015-10-21 17:40:23 -070096 private boolean mIsSummaryWithChildren;
Selim Cinekb5605e52015-02-20 18:21:41 +010097 private NotificationChildrenContainer mChildrenContainer;
Selim Cinekab29aeb2015-02-20 18:18:32 +010098 private ViewStub mGutsStub;
Selim Cinekeef84282015-10-30 16:28:00 -070099 private boolean mHasNotificationHeader;
Selim Cinekb5605e52015-02-20 18:21:41 +0100100 private boolean mIsSystemChildExpanded;
Selim Cinek684a4422015-04-15 16:18:39 -0700101 private boolean mIsPinned;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700102 private FalsingManager mFalsingManager;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200103
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700104 private boolean mJustClicked;
Selim Cinekeef84282015-10-30 16:28:00 -0700105 private NotificationData.Entry mEntry;
Selim Cinek34d93b02015-10-22 12:30:38 -0700106 private boolean mShowNoBackground;
Selim Cinek388df6d2015-10-22 13:25:11 -0700107 private ExpandableNotificationRow mNotificationParent;
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700108
Selim Cinek8d490d42015-04-10 00:05:50 -0700109 public NotificationContentView getPrivateLayout() {
110 return mPrivateLayout;
111 }
112
113 public NotificationContentView getPublicLayout() {
114 return mPublicLayout;
115 }
116
Selim Cinekcab4a602014-09-03 14:47:57 +0200117 public void setIconAnimationRunning(boolean running) {
118 setIconAnimationRunning(running, mPublicLayout);
119 setIconAnimationRunning(running, mPrivateLayout);
120 }
121
122 private void setIconAnimationRunning(boolean running, NotificationContentView layout) {
123 if (layout != null) {
124 View contractedChild = layout.getContractedChild();
125 View expandedChild = layout.getExpandedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -0700126 View headsUpChild = layout.getHeadsUpChild();
Selim Cinekcab4a602014-09-03 14:47:57 +0200127 setIconAnimationRunningForChild(running, contractedChild);
128 setIconAnimationRunningForChild(running, expandedChild);
Selim Cinek8d490d42015-04-10 00:05:50 -0700129 setIconAnimationRunningForChild(running, headsUpChild);
Selim Cinekcab4a602014-09-03 14:47:57 +0200130 }
131 }
132
133 private void setIconAnimationRunningForChild(boolean running, View child) {
134 if (child != null) {
135 ImageView icon = (ImageView) child.findViewById(com.android.internal.R.id.icon);
136 setIconRunning(icon, running);
137 ImageView rightIcon = (ImageView) child.findViewById(
138 com.android.internal.R.id.right_icon);
139 setIconRunning(rightIcon, running);
140 }
141 }
142
143 private void setIconRunning(ImageView imageView, boolean running) {
144 if (imageView != null) {
145 Drawable drawable = imageView.getDrawable();
146 if (drawable instanceof AnimationDrawable) {
147 AnimationDrawable animationDrawable = (AnimationDrawable) drawable;
148 if (running) {
149 animationDrawable.start();
150 } else {
151 animationDrawable.stop();
152 }
153 } else if (drawable instanceof AnimatedVectorDrawable) {
154 AnimatedVectorDrawable animationDrawable = (AnimatedVectorDrawable) drawable;
155 if (running) {
156 animationDrawable.start();
157 } else {
158 animationDrawable.stop();
159 }
160 }
161 }
162 }
163
Selim Cinekeef84282015-10-30 16:28:00 -0700164 private void setStatusBarNotification(StatusBarNotification statusBarNotification) {
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200165 mStatusBarNotification = statusBarNotification;
Selim Cinek83bc7832015-10-22 13:26:54 -0700166 mPrivateLayout.setStatusBarNotification(statusBarNotification);
Selim Cineka37774f2014-11-11 19:16:18 +0100167 updateVetoButton();
Selim Cinek263398f2015-10-21 17:40:23 -0700168 onChildrenCountChanged();
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200169 }
170
171 public StatusBarNotification getStatusBarNotification() {
172 return mStatusBarNotification;
173 }
174
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700175 public boolean isHeadsUp() {
176 return mIsHeadsUp;
177 }
178
Selim Cinek1a521f32014-11-03 17:39:29 +0100179 public void setHeadsUp(boolean isHeadsUp) {
Selim Cinekc80fdb12015-04-13 15:09:08 -0700180 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek1a521f32014-11-03 17:39:29 +0100181 mIsHeadsUp = isHeadsUp;
Selim Cinek8d490d42015-04-10 00:05:50 -0700182 mPrivateLayout.setHeadsUp(isHeadsUp);
Selim Cinekc80fdb12015-04-13 15:09:08 -0700183 if (intrinsicBefore != getIntrinsicHeight()) {
184 notifyHeightChanged(false /* needsAnimation */);
185 }
Selim Cinek1a521f32014-11-03 17:39:29 +0100186 }
187
Selim Cinekb5605e52015-02-20 18:21:41 +0100188 public void setGroupManager(NotificationGroupManager groupManager) {
189 mGroupManager = groupManager;
Selim Cinek83bc7832015-10-22 13:26:54 -0700190 mPrivateLayout.setGroupManager(groupManager);
Selim Cinekb5605e52015-02-20 18:21:41 +0100191 }
192
193 public void addChildNotification(ExpandableNotificationRow row) {
194 addChildNotification(row, -1);
195 }
196
197 /**
198 * Add a child notification to this view.
199 *
200 * @param row the row to add
201 * @param childIndex the index to add it at, if -1 it will be added at the end
202 */
203 public void addChildNotification(ExpandableNotificationRow row, int childIndex) {
204 if (mChildrenContainer == null) {
205 mChildrenContainerStub.inflate();
206 }
207 mChildrenContainer.addNotification(row, childIndex);
Selim Cinek263398f2015-10-21 17:40:23 -0700208 onChildrenCountChanged();
209 row.setIsChildInGroup(true, this);
Selim Cinekb5605e52015-02-20 18:21:41 +0100210 }
211
212 public void removeChildNotification(ExpandableNotificationRow row) {
213 if (mChildrenContainer != null) {
214 mChildrenContainer.removeNotification(row);
215 }
Selim Cinek263398f2015-10-21 17:40:23 -0700216 onChildrenCountChanged();
217 row.setIsChildInGroup(false, null);
218 }
219
220 public boolean isChildInGroup() {
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700221 return mNotificationParent != null;
Selim Cinek263398f2015-10-21 17:40:23 -0700222 }
223
Selim Cinek388df6d2015-10-22 13:25:11 -0700224 public ExpandableNotificationRow getNotificationParent() {
225 return mNotificationParent;
226 }
227
Selim Cinek263398f2015-10-21 17:40:23 -0700228 /**
229 * @param isChildInGroup Is this notification now in a group
230 * @param parent the new parent notification
231 */
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700232 public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {;
233 boolean childInGroup = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
234 mNotificationParent = childInGroup ? parent : null;
235 mPrivateLayout.setIsChildInGroup(childInGroup);
236 updateNoBackgroundState();
Selim Cinek34d93b02015-10-22 12:30:38 -0700237 }
238
239 @Override
240 protected boolean shouldHideBackground() {
241 return super.shouldHideBackground() || mShowNoBackground;
Selim Cinek263398f2015-10-21 17:40:23 -0700242 }
243
244 @Override
245 public boolean isSummaryWithChildren() {
246 return mIsSummaryWithChildren;
Selim Cinekb5605e52015-02-20 18:21:41 +0100247 }
248
249 @Override
250 public boolean areChildrenExpanded() {
251 return mChildrenExpanded;
252 }
253
254 public List<ExpandableNotificationRow> getNotificationChildren() {
255 return mChildrenContainer == null ? null : mChildrenContainer.getNotificationChildren();
256 }
257
Selim Cinekeef84282015-10-30 16:28:00 -0700258 public int getNumberOfNotificationChildren() {
259 if (mChildrenContainer == null) {
260 return 0;
261 }
262 return mChildrenContainer.getNotificationChildren().size();
263 }
264
Selim Cinekb5605e52015-02-20 18:21:41 +0100265 /**
266 * Apply the order given in the list to the children.
267 *
268 * @param childOrder the new list order
269 * @return whether the list order has changed
270 */
271 public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder) {
272 return mChildrenContainer != null && mChildrenContainer.applyChildOrder(childOrder);
273 }
274
275 public void getChildrenStates(StackScrollState resultState) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700276 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100277 StackViewState parentState = resultState.getViewStateForView(this);
278 mChildrenContainer.getState(resultState, parentState);
279 }
280 }
281
282 public void applyChildrenState(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700283 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100284 mChildrenContainer.applyState(state);
285 }
286 }
287
288 public void prepareExpansionChanged(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700289 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100290 mChildrenContainer.prepareExpansionChanged(state);
291 }
292 }
293
294 public void startChildAnimation(StackScrollState finalState,
295 StackStateAnimator stateAnimator, boolean withDelays, long delay, long duration) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700296 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100297 mChildrenContainer.startAnimationToState(finalState, stateAnimator, withDelays, delay,
298 duration);
299 }
300 }
301
302 public ExpandableNotificationRow getViewAtPosition(float y) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700303 if (!mIsSummaryWithChildren || !mChildrenExpanded) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100304 return this;
305 } else {
306 ExpandableNotificationRow view = mChildrenContainer.getViewAtPosition(y);
307 return view == null ? this : view;
308 }
309 }
310
Selim Cinekab29aeb2015-02-20 18:18:32 +0100311 public NotificationGuts getGuts() {
312 return mGuts;
313 }
314
Selim Cinek684a4422015-04-15 16:18:39 -0700315 /**
316 * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this
317 * the notification will be rendered on top of the screen.
318 *
319 * @param pinned whether it is pinned
320 */
321 public void setPinned(boolean pinned) {
322 mIsPinned = pinned;
Selim Cinek98713a42015-09-21 15:47:20 +0200323 setChronometerRunning(mLastChronometerRunning);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700324 }
325
Selim Cinek684a4422015-04-15 16:18:39 -0700326 public boolean isPinned() {
327 return mIsPinned;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700328 }
329
330 public int getHeadsUpHeight() {
Selim Cinek8d490d42015-04-10 00:05:50 -0700331 return mHeadsUpHeight;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700332 }
333
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700334 /**
335 * Mark whether this notification was just clicked, i.e. the user has just clicked this
336 * notification in this frame.
337 */
338 public void setJustClicked(boolean justClicked) {
339 mJustClicked = justClicked;
340 }
341
342 /**
343 * @return true if this notification has been clicked in this frame, false otherwise
344 */
345 public boolean wasJustClicked() {
346 return mJustClicked;
347 }
348
Selim Cinek98713a42015-09-21 15:47:20 +0200349 public void setChronometerRunning(boolean running) {
350 mLastChronometerRunning = running;
351 setChronometerRunning(running, mPrivateLayout);
352 setChronometerRunning(running, mPublicLayout);
353 if (mChildrenContainer != null) {
354 List<ExpandableNotificationRow> notificationChildren =
355 mChildrenContainer.getNotificationChildren();
356 for (int i = 0; i < notificationChildren.size(); i++) {
357 ExpandableNotificationRow child = notificationChildren.get(i);
358 child.setChronometerRunning(running);
359 }
360 }
361 }
362
363 private void setChronometerRunning(boolean running, NotificationContentView layout) {
364 if (layout != null) {
365 running = running || isPinned();
366 View contractedChild = layout.getContractedChild();
367 View expandedChild = layout.getExpandedChild();
368 View headsUpChild = layout.getHeadsUpChild();
369 setChronometerRunningForChild(running, contractedChild);
370 setChronometerRunningForChild(running, expandedChild);
371 setChronometerRunningForChild(running, headsUpChild);
372 }
373 }
374
375 private void setChronometerRunningForChild(boolean running, View child) {
376 if (child != null) {
377 View chronometer = child.findViewById(com.android.internal.R.id.chronometer);
378 if (chronometer instanceof Chronometer) {
379 ((Chronometer) chronometer).setStarted(running);
380 }
381 }
382 }
383
Selim Cinekeef84282015-10-30 16:28:00 -0700384 public void setEntry(NotificationData.Entry entry) {
385 mEntry = entry;
386 setStatusBarNotification(entry.notification);
387 }
388
Selim Cinek8d6440d2015-10-22 13:00:05 -0700389 public CharSequence getSubText() {
390 Notification notification = mStatusBarNotification.getNotification();
391 CharSequence subText = notification.extras.getCharSequence(Notification.EXTRA_SUMMARY_TEXT);
392 if (subText == null) {
393 subText = notification.extras.getCharSequence(Notification.EXTRA_SUB_TEXT);
394 }
395 return subText;
396 }
397
398 public void setContentSubTextVisible(boolean visible) {
399 mPrivateLayout.setSubTextVisible(visible);
400 }
401
Chris Wren78403d72014-07-28 10:23:24 +0100402 public interface ExpansionLogger {
403 public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
404 }
Selim Cinek1685e632014-04-08 02:27:49 +0200405
Chris Wren51c75102013-07-16 20:49:17 -0400406 public ExpandableNotificationRow(Context context, AttributeSet attrs) {
407 super(context, attrs);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700408 mFalsingManager = FalsingManager.getInstance(context);
Chris Wren51c75102013-07-16 20:49:17 -0400409 }
410
Christoph Studera7fe6312014-06-27 19:32:44 +0200411 /**
412 * Resets this view so it can be re-used for an updated notification.
413 */
Christoph Studer22f2ee52014-07-29 22:57:21 +0200414 @Override
Christoph Studera7fe6312014-06-27 19:32:44 +0200415 public void reset() {
Christoph Studer22f2ee52014-07-29 22:57:21 +0200416 super.reset();
Christoph Studera7fe6312014-06-27 19:32:44 +0200417 mRowMinHeight = 0;
Chris Wren78403d72014-07-28 10:23:24 +0100418 final boolean wasExpanded = isExpanded();
Selim Cinek379ff8f2015-02-20 17:03:16 +0100419 mMaxViewHeight = 0;
Christoph Studera7fe6312014-06-27 19:32:44 +0200420 mExpandable = false;
421 mHasUserChangedExpansion = false;
422 mUserLocked = false;
423 mShowingPublic = false;
Jorim Jaggiae441282014-08-01 02:45:18 +0200424 mSensitive = false;
425 mShowingPublicInitialized = false;
Christoph Studera7fe6312014-06-27 19:32:44 +0200426 mIsSystemExpanded = false;
Selim Cinek83bc7832015-10-22 13:26:54 -0700427 mOnKeyguard = false;
Selim Cinek1a521f32014-11-03 17:39:29 +0100428 mPublicLayout.reset(mIsHeadsUp);
429 mPrivateLayout.reset(mIsHeadsUp);
Selim Cinek31094df2014-08-14 19:28:15 +0200430 resetHeight();
431 logExpansionEvent(false, wasExpanded);
432 }
433
434 public void resetHeight() {
Selim Cinek1a521f32014-11-03 17:39:29 +0100435 if (mIsHeadsUp) {
436 resetActualHeight();
437 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200438 mMaxExpandHeight = 0;
Selim Cinek8d490d42015-04-10 00:05:50 -0700439 mHeadsUpHeight = 0;
Selim Cineka5e211b2014-08-11 17:35:48 +0200440 mWasReset = true;
Selim Cinek31094df2014-08-14 19:28:15 +0200441 onHeightReset();
Selim Cinek6e28a672014-09-05 14:43:28 +0200442 requestLayout();
Christoph Studera7fe6312014-06-27 19:32:44 +0200443 }
444
Jorim Jaggi251957d2014-04-09 04:24:09 +0200445 @Override
Selim Cinek1a521f32014-11-03 17:39:29 +0100446 protected boolean filterMotionEvent(MotionEvent event) {
447 return mIsHeadsUp || super.filterMotionEvent(event);
448 }
449
450 @Override
Jorim Jaggi251957d2014-04-09 04:24:09 +0200451 protected void onFinishInflate() {
452 super.onFinishInflate();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200453 mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
454 mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
Selim Cinekab29aeb2015-02-20 18:18:32 +0100455 mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
456 mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200457 @Override
458 public void onInflate(ViewStub stub, View inflated) {
459 mGuts = (NotificationGuts) inflated;
460 mGuts.setClipTopAmount(getClipTopAmount());
461 mGuts.setActualHeight(getActualHeight());
Selim Cinekab29aeb2015-02-20 18:18:32 +0100462 mGutsStub = null;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200463 }
464 });
Selim Cinekeef84282015-10-30 16:28:00 -0700465 mNotificationHeaderStub = (ViewStub) findViewById(R.id.notification_header_stub);
466 mNotificationHeaderStub.setOnInflateListener(new ViewStub.OnInflateListener() {
Selim Cinekb5605e52015-02-20 18:21:41 +0100467 @Override
468 public void onInflate(ViewStub stub, View inflated) {
Selim Cinekeef84282015-10-30 16:28:00 -0700469 mNotificationHeader = (NotificationHeaderView) inflated;
470 mNotificationHeader.setGroupManager(mGroupManager);
471 mNotificationHeader.bind(mEntry);
Selim Cinekb5605e52015-02-20 18:21:41 +0100472 }
473 });
474 mChildrenContainerStub = (ViewStub) findViewById(R.id.child_container_stub);
475 mChildrenContainerStub.setOnInflateListener(new ViewStub.OnInflateListener() {
476
477 @Override
478 public void onInflate(ViewStub stub, View inflated) {
479 mChildrenContainer = (NotificationChildrenContainer) inflated;
Selim Cinek388df6d2015-10-22 13:25:11 -0700480 mChildrenContainer.setNotificationParent(ExpandableNotificationRow.this);
Selim Cinekb5605e52015-02-20 18:21:41 +0100481 }
482 });
Selim Cinek863834b2014-05-20 04:20:25 +0200483 mVetoButton = findViewById(R.id.veto);
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200484 }
485
Selim Cinekab29aeb2015-02-20 18:18:32 +0100486 public void inflateGuts() {
487 if (mGuts == null) {
488 mGutsStub.inflate();
489 }
490 }
491
Selim Cinekb5605e52015-02-20 18:21:41 +0100492 private void updateChildrenVisibility(boolean animated) {
493 if (mChildrenContainer == null) {
494 return;
495 }
Selim Cinekeef84282015-10-30 16:28:00 -0700496 mChildrenContainer.setVisibility(mIsSummaryWithChildren ? VISIBLE : INVISIBLE);
497 mPrivateLayout.setVisibility(!mIsSummaryWithChildren ? VISIBLE : INVISIBLE);
Selim Cinekb5605e52015-02-20 18:21:41 +0100498 }
499
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200500 @Override
Alan Viverettea54956a2015-01-07 16:05:02 -0800501 public boolean onRequestSendAccessibilityEventInternal(View child, AccessibilityEvent event) {
502 if (super.onRequestSendAccessibilityEventInternal(child, event)) {
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200503 // Add a record for the entire layout since its content is somehow small.
504 // The event comes from a leaf view that is interacted with.
505 AccessibilityEvent record = AccessibilityEvent.obtain();
506 onInitializeAccessibilityEvent(record);
507 dispatchPopulateAccessibilityEvent(record);
508 event.appendRecord(record);
509 return true;
510 }
511 return false;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200512 }
Chris Wren51c75102013-07-16 20:49:17 -0400513
John Spurlocke15452b2014-08-21 09:44:39 -0400514 @Override
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100515 public void setDark(boolean dark, boolean fade, long delay) {
516 super.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400517 final NotificationContentView showing = getShowingLayout();
518 if (showing != null) {
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100519 showing.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400520 }
521 }
522
Selim Cinek1685e632014-04-08 02:27:49 +0200523 public void setHeightRange(int rowMinHeight, int rowMaxHeight) {
524 mRowMinHeight = rowMinHeight;
Selim Cinek379ff8f2015-02-20 17:03:16 +0100525 mMaxViewHeight = rowMaxHeight;
Chris Wren51c75102013-07-16 20:49:17 -0400526 }
527
528 public boolean isExpandable() {
Selim Cinek388df6d2015-10-22 13:25:11 -0700529 if (mIsSummaryWithChildren && !mShowingPublic) {
530 return !mChildrenExpanded;
531 }
Chris Wren51c75102013-07-16 20:49:17 -0400532 return mExpandable;
533 }
534
535 public void setExpandable(boolean expandable) {
536 mExpandable = expandable;
537 }
538
Selim Cinek1685e632014-04-08 02:27:49 +0200539 /**
540 * @return whether the user has changed the expansion state
541 */
542 public boolean hasUserChangedExpansion() {
543 return mHasUserChangedExpansion;
544 }
545
Chris Wren51c75102013-07-16 20:49:17 -0400546 public boolean isUserExpanded() {
547 return mUserExpanded;
548 }
549
Selim Cinek1685e632014-04-08 02:27:49 +0200550 /**
551 * Set this notification to be expanded by the user
552 *
553 * @param userExpanded whether the user wants this notification to be expanded
554 */
Chris Wren51c75102013-07-16 20:49:17 -0400555 public void setUserExpanded(boolean userExpanded) {
Selim Cinek388df6d2015-10-22 13:25:11 -0700556 setUserExpanded(userExpanded, false /* allowChildExpansion */);
557 }
558
559 /**
560 * Set this notification to be expanded by the user
561 *
562 * @param userExpanded whether the user wants this notification to be expanded
563 * @param allowChildExpansion whether a call to this method allows expanding children
564 */
565 public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700566 mFalsingManager.setNotificationExpanded();
Selim Cinek388df6d2015-10-22 13:25:11 -0700567 if (mIsSummaryWithChildren && !mShowingPublic && allowChildExpansion) {
568 mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
569 return;
570 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200571 if (userExpanded && !mExpandable) return;
Chris Wren78403d72014-07-28 10:23:24 +0100572 final boolean wasExpanded = isExpanded();
Selim Cinek1685e632014-04-08 02:27:49 +0200573 mHasUserChangedExpansion = true;
Chris Wren51c75102013-07-16 20:49:17 -0400574 mUserExpanded = userExpanded;
Chris Wren78403d72014-07-28 10:23:24 +0100575 logExpansionEvent(true, wasExpanded);
Chris Wren51c75102013-07-16 20:49:17 -0400576 }
577
Selim Cinekccd14fb2014-08-12 18:53:24 +0200578 public void resetUserExpansion() {
579 mHasUserChangedExpansion = false;
580 mUserExpanded = false;
581 }
582
Chris Wren51c75102013-07-16 20:49:17 -0400583 public boolean isUserLocked() {
584 return mUserLocked;
585 }
586
587 public void setUserLocked(boolean userLocked) {
588 mUserLocked = userLocked;
589 }
590
Selim Cinek1685e632014-04-08 02:27:49 +0200591 /**
592 * @return has the system set this notification to be expanded
593 */
594 public boolean isSystemExpanded() {
595 return mIsSystemExpanded;
596 }
597
598 /**
599 * Set this notification to be expanded by the system.
600 *
601 * @param expand whether the system wants this notification to be expanded.
602 */
603 public void setSystemExpanded(boolean expand) {
Selim Cinek31094df2014-08-14 19:28:15 +0200604 if (expand != mIsSystemExpanded) {
605 final boolean wasExpanded = isExpanded();
606 mIsSystemExpanded = expand;
Selim Cinekb5605e52015-02-20 18:21:41 +0100607 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200608 logExpansionEvent(false, wasExpanded);
Selim Cinek83bc7832015-10-22 13:26:54 -0700609 if (mChildrenContainer != null) {
610 mChildrenContainer.updateGroupOverflow();
611 }
Selim Cinek31094df2014-08-14 19:28:15 +0200612 }
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200613 }
614
615 /**
Selim Cinek83bc7832015-10-22 13:26:54 -0700616 * @param onKeyguard whether to prevent notification expansion
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200617 */
Selim Cinek83bc7832015-10-22 13:26:54 -0700618 public void setOnKeyguard(boolean onKeyguard) {
619 if (onKeyguard != mOnKeyguard) {
Selim Cinek31094df2014-08-14 19:28:15 +0200620 final boolean wasExpanded = isExpanded();
Selim Cinek83bc7832015-10-22 13:26:54 -0700621 mOnKeyguard = onKeyguard;
Selim Cinek31094df2014-08-14 19:28:15 +0200622 logExpansionEvent(false, wasExpanded);
623 if (wasExpanded != isExpanded()) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100624 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200625 }
626 }
Selim Cinek1685e632014-04-08 02:27:49 +0200627 }
628
629 /**
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400630 * @return Can the underlying notification be cleared?
631 */
632 public boolean isClearable() {
Selim Cineka37774f2014-11-11 19:16:18 +0100633 return mStatusBarNotification != null && mStatusBarNotification.isClearable();
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400634 }
635
636 /**
Selim Cinek1685e632014-04-08 02:27:49 +0200637 * Apply an expansion state to the layout.
Selim Cinek1685e632014-04-08 02:27:49 +0200638 */
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200639 public void applyExpansionToLayout() {
640 boolean expand = isExpanded();
Chris Wren51c75102013-07-16 20:49:17 -0400641 if (expand && mExpandable) {
Selim Cinekeef84282015-10-30 16:28:00 -0700642 setActualHeight(mMaxExpandHeight);
Chris Wren51c75102013-07-16 20:49:17 -0400643 } else {
Selim Cinekeef84282015-10-30 16:28:00 -0700644 setActualHeight(mRowMinHeight);
Chris Wren51c75102013-07-16 20:49:17 -0400645 }
Chris Wren51c75102013-07-16 20:49:17 -0400646 }
Dan Sandlera5e0f412014-01-23 15:11:54 -0500647
Jorim Jaggi9cbadd32014-05-01 20:18:31 +0200648 @Override
649 public int getIntrinsicHeight() {
Jorim Jaggibe565df2014-04-28 17:51:23 +0200650 if (isUserLocked()) {
651 return getActualHeight();
652 }
Selim Cinek1685e632014-04-08 02:27:49 +0200653 boolean inExpansionState = isExpanded();
Selim Cinek60122be2015-04-15 18:16:50 -0700654 if (mSensitive && mHideSensitiveForIntrinsicHeight) {
655 return mRowMinHeight;
Selim Cinek83bc7832015-10-22 13:26:54 -0700656 } else if (mIsSummaryWithChildren && !mOnKeyguard) {
657 return mChildrenContainer.getIntrinsicHeight()
658 + mNotificationHeader.getHeight();
Selim Cinek60122be2015-04-15 18:16:50 -0700659 } else if (mIsHeadsUp) {
Selim Cinek8d490d42015-04-10 00:05:50 -0700660 if (inExpansionState) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700661 return Math.max(mMaxExpandHeight, mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -0700662 } else {
Selim Cinek83bc7832015-10-22 13:26:54 -0700663 return Math.max(mRowMinHeight, mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -0700664 }
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700665 } else if (!inExpansionState || (isChildInGroup() && !isGroupExpanded())) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700666 return getMinHeight();
Selim Cinekb5605e52015-02-20 18:21:41 +0100667 } else {
Selim Cinek83bc7832015-10-22 13:26:54 -0700668 return getMaxExpandHeight();
Selim Cinek1685e632014-04-08 02:27:49 +0200669 }
Selim Cinekb5605e52015-02-20 18:21:41 +0100670 }
Selim Cinek1685e632014-04-08 02:27:49 +0200671
Selim Cinekeef84282015-10-30 16:28:00 -0700672 private boolean isGroupExpanded() {
673 return mGroupManager.isGroupExpanded(mStatusBarNotification);
Selim Cinekb5605e52015-02-20 18:21:41 +0100674 }
675
Selim Cinekeef84282015-10-30 16:28:00 -0700676 /**
677 * @return whether this view has a header on the top of the content
678 */
679 private boolean hasNotificationHeader() {
680 return mIsSummaryWithChildren;
Selim Cinek1685e632014-04-08 02:27:49 +0200681 }
682
Selim Cinek263398f2015-10-21 17:40:23 -0700683 private void onChildrenCountChanged() {
684 mIsSummaryWithChildren = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS
685 && mGroupManager.hasGroupChildren(mStatusBarNotification);
686 if (mIsSummaryWithChildren && mChildrenContainer == null) {
687 mChildrenContainerStub.inflate();
688 }
Selim Cinekeef84282015-10-30 16:28:00 -0700689 updateNotificationHeader();
Selim Cinek263398f2015-10-21 17:40:23 -0700690 updateChildrenVisibility(true);
691 }
692
Selim Cinek1685e632014-04-08 02:27:49 +0200693 /**
694 * Check whether the view state is currently expanded. This is given by the system in {@link
695 * #setSystemExpanded(boolean)} and can be overridden by user expansion or
696 * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
697 * view can differ from this state, if layout params are modified from outside.
698 *
699 * @return whether the view state is currently expanded.
700 */
Selim Cinek83bc7832015-10-22 13:26:54 -0700701 public boolean isExpanded() {
702 return !mOnKeyguard
Selim Cinekb5605e52015-02-20 18:21:41 +0100703 && (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded())
704 || isUserExpanded());
705 }
706
707 private boolean isSystemChildExpanded() {
708 return mIsSystemChildExpanded;
709 }
710
711 public void setSystemChildExpanded(boolean expanded) {
712 mIsSystemChildExpanded = expanded;
Selim Cinek1685e632014-04-08 02:27:49 +0200713 }
714
715 @Override
716 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
717 super.onLayout(changed, left, top, right, bottom);
Selim Cineka5e211b2014-08-11 17:35:48 +0200718 boolean updateExpandHeight = mMaxExpandHeight == 0 && !mWasReset;
Selim Cinek8d490d42015-04-10 00:05:50 -0700719 updateMaxHeights();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200720 if (updateExpandHeight) {
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200721 applyExpansionToLayout();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200722 }
Selim Cineka5e211b2014-08-11 17:35:48 +0200723 mWasReset = false;
Selim Cinek1685e632014-04-08 02:27:49 +0200724 }
725
Selim Cinek8d490d42015-04-10 00:05:50 -0700726 private void updateMaxHeights() {
Selim Cinekd2319fb2014-09-01 19:41:54 +0200727 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek8d490d42015-04-10 00:05:50 -0700728 View expandedChild = mPrivateLayout.getExpandedChild();
729 if (expandedChild == null) {
730 expandedChild = mPrivateLayout.getContractedChild();
731 }
732 mMaxExpandHeight = expandedChild.getHeight();
733 View headsUpChild = mPrivateLayout.getHeadsUpChild();
Selim Cinek1f3f5442015-04-10 17:54:46 -0700734 if (headsUpChild == null) {
735 headsUpChild = mPrivateLayout.getContractedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -0700736 }
Selim Cinek1f3f5442015-04-10 17:54:46 -0700737 mHeadsUpHeight = headsUpChild.getHeight();
Selim Cinekd2319fb2014-09-01 19:41:54 +0200738 if (intrinsicBefore != getIntrinsicHeight()) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100739 notifyHeightChanged(false /* needsAnimation */);
Selim Cinekd2319fb2014-09-01 19:41:54 +0200740 }
741 }
742
Jorim Jaggiae441282014-08-01 02:45:18 +0200743 public void setSensitive(boolean sensitive) {
744 mSensitive = sensitive;
745 }
746
747 public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
Selim Cinek60122be2015-04-15 18:16:50 -0700748 mHideSensitiveForIntrinsicHeight = hideSensitive;
Jorim Jaggiae441282014-08-01 02:45:18 +0200749 }
750
751 public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
752 long duration) {
753 boolean oldShowingPublic = mShowingPublic;
754 mShowingPublic = mSensitive && hideSensitive;
755 if (mShowingPublicInitialized && mShowingPublic == oldShowingPublic) {
756 return;
757 }
Dan Sandlera5e0f412014-01-23 15:11:54 -0500758
759 // bail out if no public version
Selim Cinek1685e632014-04-08 02:27:49 +0200760 if (mPublicLayout.getChildCount() == 0) return;
Dan Sandlera5e0f412014-01-23 15:11:54 -0500761
Jorim Jaggiae441282014-08-01 02:45:18 +0200762 if (!animated) {
763 mPublicLayout.animate().cancel();
764 mPrivateLayout.animate().cancel();
765 mPublicLayout.setAlpha(1f);
766 mPrivateLayout.setAlpha(1f);
767 mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
Selim Cinek263398f2015-10-21 17:40:23 -0700768 mPrivateLayout.setVisibility(!mShowingPublic && !mIsSummaryWithChildren ? View.VISIBLE
769 : View.INVISIBLE);
Jorim Jaggiae441282014-08-01 02:45:18 +0200770 } else {
771 animateShowingPublic(delay, duration);
772 }
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400773
774 updateVetoButton();
Jorim Jaggiae441282014-08-01 02:45:18 +0200775 mShowingPublicInitialized = true;
776 }
777
778 private void animateShowingPublic(long delay, long duration) {
779 final View source = mShowingPublic ? mPrivateLayout : mPublicLayout;
780 View target = mShowingPublic ? mPublicLayout : mPrivateLayout;
781 source.setVisibility(View.VISIBLE);
782 target.setVisibility(View.VISIBLE);
783 target.setAlpha(0f);
784 source.animate().cancel();
785 target.animate().cancel();
786 source.animate()
787 .alpha(0f)
Jorim Jaggiae441282014-08-01 02:45:18 +0200788 .setStartDelay(delay)
789 .setDuration(duration)
790 .withEndAction(new Runnable() {
791 @Override
792 public void run() {
793 source.setVisibility(View.INVISIBLE);
794 }
795 });
796 target.animate()
797 .alpha(1f)
Jorim Jaggiae441282014-08-01 02:45:18 +0200798 .setStartDelay(delay)
799 .setDuration(duration);
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400800 }
801
802 private void updateVetoButton() {
803 // public versions cannot be dismissed
804 mVetoButton.setVisibility(isClearable() && !mShowingPublic ? View.VISIBLE : View.GONE);
Dan Sandlera5e0f412014-01-23 15:11:54 -0500805 }
Jorim Jaggi251957d2014-04-09 04:24:09 +0200806
Selim Cinekb5605e52015-02-20 18:21:41 +0100807 public void setChildrenExpanded(boolean expanded, boolean animate) {
808 mChildrenExpanded = expanded;
Selim Cinek83bc7832015-10-22 13:26:54 -0700809 if (mChildrenContainer != null) {
810 mChildrenContainer.setChildrenExpanded(expanded);
811 }
Selim Cinekb5605e52015-02-20 18:21:41 +0100812 }
813
Selim Cinekeef84282015-10-30 16:28:00 -0700814 public void updateNotificationHeader() {
815 boolean hasHeader = hasNotificationHeader();
816 if (hasHeader != mHasNotificationHeader) {
817 if (hasHeader) {
818 if (mNotificationHeader == null) {
819 mNotificationHeaderStub.inflate();
Selim Cinekb5605e52015-02-20 18:21:41 +0100820 }
Selim Cinekeef84282015-10-30 16:28:00 -0700821 mNotificationHeader.setVisibility(View.VISIBLE);
822 } else if (mNotificationHeader != null) {
823 mNotificationHeader.setVisibility(View.GONE);
Selim Cinekb5605e52015-02-20 18:21:41 +0100824 }
825 notifyHeightChanged(true /* needsAnimation */);
826 }
Selim Cinekeef84282015-10-30 16:28:00 -0700827 if (hasHeader) {
828 mNotificationHeader.bind(mEntry);
Selim Cinekb5605e52015-02-20 18:21:41 +0100829 }
Selim Cinekeef84282015-10-30 16:28:00 -0700830 mHasNotificationHeader = hasHeader;
Selim Cinekb5605e52015-02-20 18:21:41 +0100831 }
832
833 public static void applyTint(View v, int color) {
834 int alpha;
835 if (color != 0) {
836 alpha = COLORED_DIVIDER_ALPHA;
837 } else {
838 color = 0xff000000;
839 alpha = DEFAULT_DIVIDER_ALPHA;
840 }
841 if (v.getBackground() instanceof ColorDrawable) {
842 ColorDrawable background = (ColorDrawable) v.getBackground();
843 background.mutate();
844 background.setColor(color);
845 background.setAlpha(alpha);
846 }
847 }
848
Selim Cinek1685e632014-04-08 02:27:49 +0200849 public int getMaxExpandHeight() {
Selim Cinekb5605e52015-02-20 18:21:41 +0100850 return mMaxExpandHeight;
Chris Wren51c75102013-07-16 20:49:17 -0400851 }
Jorim Jaggi584a7aa2014-04-10 23:26:13 +0200852
Jorim Jaggibe565df2014-04-28 17:51:23 +0200853 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200854 public boolean isContentExpandable() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200855 NotificationContentView showingLayout = getShowingLayout();
856 return showingLayout.isContentExpandable();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200857 }
858
859 @Override
Selim Cinek560e64d2015-06-09 19:58:11 -0700860 protected View getContentView() {
861 return getShowingLayout();
862 }
863
864 @Override
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200865 public void setActualHeight(int height, boolean notifyListeners) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100866 super.setActualHeight(height, notifyListeners);
Selim Cinekeef84282015-10-30 16:28:00 -0700867 int contentHeight = Math.max(getMinHeight(), height);
Selim Cinekb5605e52015-02-20 18:21:41 +0100868 mPrivateLayout.setContentHeight(contentHeight);
869 mPublicLayout.setContentHeight(contentHeight);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200870 if (mGuts != null) {
871 mGuts.setActualHeight(height);
872 }
Jorim Jaggibe565df2014-04-28 17:51:23 +0200873 invalidate();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200874 }
875
876 @Override
Selim Cinekb5605e52015-02-20 18:21:41 +0100877 public int getMaxContentHeight() {
Selim Cinek83bc7832015-10-22 13:26:54 -0700878 if (mIsSummaryWithChildren && !mShowingPublic) {
879 return mChildrenContainer.getMaxContentHeight()
880 + mNotificationHeader.getHeight();
881 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200882 NotificationContentView showingLayout = getShowingLayout();
883 return showingLayout.getMaxHeight();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200884 }
885
886 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200887 public int getMinHeight() {
Selim Cinek83bc7832015-10-22 13:26:54 -0700888 if (mIsSummaryWithChildren && !mOnKeyguard) {
889 return mChildrenContainer.getMinHeight()
890 + mNotificationHeader.getHeight();
891 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200892 NotificationContentView showingLayout = getShowingLayout();
893 return showingLayout.getMinHeight();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200894 }
895
896 @Override
Selim Cinek263398f2015-10-21 17:40:23 -0700897 protected boolean shouldLimitViewHeight() {
898 return !mIsSummaryWithChildren;
899 }
900
901 @Override
Jorim Jaggibe565df2014-04-28 17:51:23 +0200902 public void setClipTopAmount(int clipTopAmount) {
903 super.setClipTopAmount(clipTopAmount);
904 mPrivateLayout.setClipTopAmount(clipTopAmount);
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200905 mPublicLayout.setClipTopAmount(clipTopAmount);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200906 if (mGuts != null) {
907 mGuts.setClipTopAmount(clipTopAmount);
908 }
Jorim Jaggibe565df2014-04-28 17:51:23 +0200909 }
910
911 public void notifyContentUpdated() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200912 mPublicLayout.notifyContentUpdated();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200913 mPrivateLayout.notifyContentUpdated();
Selim Cinek343e6e22014-04-11 21:23:30 +0200914 }
Selim Cinek7d447722014-06-10 15:51:59 +0200915
Selim Cinek31094df2014-08-14 19:28:15 +0200916 public boolean isMaxExpandHeightInitialized() {
917 return mMaxExpandHeight != 0;
Selim Cinek7d447722014-06-10 15:51:59 +0200918 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200919
920 private NotificationContentView getShowingLayout() {
921 return mShowingPublic ? mPublicLayout : mPrivateLayout;
922 }
Chris Wren78403d72014-07-28 10:23:24 +0100923
Jorim Jaggi59ec3042015-06-05 15:18:43 -0700924 @Override
925 public void setShowingLegacyBackground(boolean showing) {
926 super.setShowingLegacyBackground(showing);
927 mPrivateLayout.setShowingLegacyBackground(showing);
928 mPublicLayout.setShowingLegacyBackground(showing);
929 }
930
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700931 @Override
932 protected void updateBackgroundTint() {
933 super.updateBackgroundTint();
934 updateNoBackgroundState();
935 if (mIsSummaryWithChildren) {
936 List<ExpandableNotificationRow> notificationChildren =
937 mChildrenContainer.getNotificationChildren();
938 for (int i = 0; i < notificationChildren.size(); i++) {
939 ExpandableNotificationRow child = notificationChildren.get(i);
940 child.updateNoBackgroundState();
941 }
942 }
943 }
944
945 private void updateNoBackgroundState() {
946 mShowNoBackground = isChildInGroup() && hasSameBgColor(mNotificationParent);
947 updateBackground();
948 }
949
Chris Wren78403d72014-07-28 10:23:24 +0100950 public void setExpansionLogger(ExpansionLogger logger, String key) {
951 mLogger = logger;
952 mLoggingKey = key;
953 }
954
Chris Wren78403d72014-07-28 10:23:24 +0100955 private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
956 final boolean nowExpanded = isExpanded();
957 if (wasExpanded != nowExpanded && mLogger != null) {
958 mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
959 }
960 }
Chris Wren51c75102013-07-16 20:49:17 -0400961}